Merge pull request #1687 from mermaid-js/sidv/mobile
feat: Add mobile support
This commit is contained in:
Vendored
+8
-1
@@ -2,12 +2,14 @@
|
||||
"editor.formatOnSave": true,
|
||||
"cSpell.blockCheckingWhenLineLengthGreaterThan": 150,
|
||||
"cSpell.words": [
|
||||
"appinstalled",
|
||||
"asyncable",
|
||||
"Browserslist",
|
||||
"ckppp",
|
||||
"corg",
|
||||
"cssnano",
|
||||
"esserializer",
|
||||
"fsegurai",
|
||||
"gantt",
|
||||
"gitgraph",
|
||||
"KROKI",
|
||||
@@ -16,14 +18,19 @@
|
||||
"mindmap",
|
||||
"Pageview",
|
||||
"pako",
|
||||
"panmove",
|
||||
"panstart",
|
||||
"panzoom",
|
||||
"pinchmove",
|
||||
"pinchstart",
|
||||
"pzoom",
|
||||
"roughjs",
|
||||
"Serde",
|
||||
"serdes",
|
||||
"Stackable",
|
||||
"tailwindcss",
|
||||
"uparrow"
|
||||
"uparrow",
|
||||
"zenuml"
|
||||
],
|
||||
"vitest.commandLine": "pnpm test:unit",
|
||||
"vitest.enable": true,
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"@sveltejs/adapter-static": "3.0.8",
|
||||
"@sveltejs/kit": "2.20.3",
|
||||
"@sveltejs/vite-plugin-svelte": "^4.0.4",
|
||||
"@types/hammerjs": "^2.0.46",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^22.14.1",
|
||||
"@types/pako": "2.0.3",
|
||||
@@ -81,10 +82,20 @@
|
||||
"vitest-dom": "^0.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/lang-json": "^6.0.1",
|
||||
"@codemirror/lang-markdown": "^6.3.2",
|
||||
"@codemirror/lang-yaml": "^6.1.2",
|
||||
"@codemirror/language": "^6.11.0",
|
||||
"@codemirror/state": "^6.5.2",
|
||||
"@codemirror/view": "^6.36.5",
|
||||
"@fontsource-variable/recursive": "^5.2.5",
|
||||
"@fsegurai/codemirror-theme-vscode-dark": "^6.1.2",
|
||||
"@fsegurai/codemirror-theme-vscode-light": "^6.1.2",
|
||||
"@mermaid-js/layout-elk": "^0.1.7",
|
||||
"@mermaid-js/mermaid-zenuml": "^0.2.0",
|
||||
"codemirror": "^6.0.1",
|
||||
"dayjs": "^1.11.13",
|
||||
"hammerjs": "^2.0.8",
|
||||
"js-base64": "3.7.7",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mermaid": "^11.6.0",
|
||||
|
||||
Generated
+318
@@ -8,18 +8,48 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@codemirror/lang-json':
|
||||
specifier: ^6.0.1
|
||||
version: 6.0.1
|
||||
'@codemirror/lang-markdown':
|
||||
specifier: ^6.3.2
|
||||
version: 6.3.2
|
||||
'@codemirror/lang-yaml':
|
||||
specifier: ^6.1.2
|
||||
version: 6.1.2
|
||||
'@codemirror/language':
|
||||
specifier: ^6.11.0
|
||||
version: 6.11.0
|
||||
'@codemirror/state':
|
||||
specifier: ^6.5.2
|
||||
version: 6.5.2
|
||||
'@codemirror/view':
|
||||
specifier: ^6.36.5
|
||||
version: 6.36.5
|
||||
'@fontsource-variable/recursive':
|
||||
specifier: ^5.2.5
|
||||
version: 5.2.5
|
||||
'@fsegurai/codemirror-theme-vscode-dark':
|
||||
specifier: ^6.1.2
|
||||
version: 6.1.2(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.36.5)(@lezer/highlight@1.2.1)
|
||||
'@fsegurai/codemirror-theme-vscode-light':
|
||||
specifier: ^6.1.2
|
||||
version: 6.1.2(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.36.5)(@lezer/highlight@1.2.1)
|
||||
'@mermaid-js/layout-elk':
|
||||
specifier: ^0.1.7
|
||||
version: 0.1.7(mermaid@11.6.0)
|
||||
'@mermaid-js/mermaid-zenuml':
|
||||
specifier: ^0.2.0
|
||||
version: 0.2.0(mermaid@11.6.0)(typescript@5.8.2)
|
||||
codemirror:
|
||||
specifier: ^6.0.1
|
||||
version: 6.0.1
|
||||
dayjs:
|
||||
specifier: ^1.11.13
|
||||
version: 1.11.13
|
||||
hammerjs:
|
||||
specifier: ^2.0.8
|
||||
version: 2.0.8
|
||||
js-base64:
|
||||
specifier: 3.7.7
|
||||
version: 3.7.7
|
||||
@@ -75,6 +105,9 @@ importers:
|
||||
'@sveltejs/vite-plugin-svelte':
|
||||
specifier: ^4.0.4
|
||||
version: 4.0.4(svelte@5.26.1)(vite@5.4.16(@types/node@22.14.1))
|
||||
'@types/hammerjs':
|
||||
specifier: ^2.0.46
|
||||
version: 2.0.46
|
||||
'@types/lodash-es':
|
||||
specifier: ^4.17.12
|
||||
version: 4.17.12
|
||||
@@ -284,6 +317,45 @@ packages:
|
||||
'@chevrotain/utils@11.0.3':
|
||||
resolution: {integrity: sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==}
|
||||
|
||||
'@codemirror/autocomplete@6.18.6':
|
||||
resolution: {integrity: sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg==}
|
||||
|
||||
'@codemirror/commands@6.8.1':
|
||||
resolution: {integrity: sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==}
|
||||
|
||||
'@codemirror/lang-css@6.3.1':
|
||||
resolution: {integrity: sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==}
|
||||
|
||||
'@codemirror/lang-html@6.4.9':
|
||||
resolution: {integrity: sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==}
|
||||
|
||||
'@codemirror/lang-javascript@6.2.3':
|
||||
resolution: {integrity: sha512-8PR3vIWg7pSu7ur8A07pGiYHgy3hHj+mRYRCSG8q+mPIrl0F02rgpGv+DsQTHRTc30rydOsf5PZ7yjKFg2Ackw==}
|
||||
|
||||
'@codemirror/lang-json@6.0.1':
|
||||
resolution: {integrity: sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==}
|
||||
|
||||
'@codemirror/lang-markdown@6.3.2':
|
||||
resolution: {integrity: sha512-c/5MYinGbFxYl4itE9q/rgN/sMTjOr8XL5OWnC+EaRMLfCbVUmmubTJfdgpfcSS2SCaT7b+Q+xi3l6CgoE+BsA==}
|
||||
|
||||
'@codemirror/lang-yaml@6.1.2':
|
||||
resolution: {integrity: sha512-dxrfG8w5Ce/QbT7YID7mWZFKhdhsaTNOYjOkSIMt1qmC4VQnXSDSYVHHHn8k6kJUfIhtLo8t1JJgltlxWdsITw==}
|
||||
|
||||
'@codemirror/language@6.11.0':
|
||||
resolution: {integrity: sha512-A7+f++LodNNc1wGgoRDTt78cOwWm9KVezApgjOMp1W4hM0898nsqBXwF+sbePE7ZRcjN7Sa1Z5m2oN27XkmEjQ==}
|
||||
|
||||
'@codemirror/lint@6.8.5':
|
||||
resolution: {integrity: sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==}
|
||||
|
||||
'@codemirror/search@6.5.10':
|
||||
resolution: {integrity: sha512-RMdPdmsrUf53pb2VwflKGHEe1XVM07hI7vV2ntgw1dmqhimpatSJKva4VA9h4TLUDOD4EIF02201oZurpnEFsg==}
|
||||
|
||||
'@codemirror/state@6.5.2':
|
||||
resolution: {integrity: sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==}
|
||||
|
||||
'@codemirror/view@6.36.5':
|
||||
resolution: {integrity: sha512-cd+FZEUlu3GQCYnguYm3EkhJ8KJVisqqUsCOKedBoAt/d9c76JUUap6U0UrpElln5k6VyrEOYliMuDAKIeDQLg==}
|
||||
|
||||
'@csstools/color-helpers@5.0.2':
|
||||
resolution: {integrity: sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -487,6 +559,22 @@ packages:
|
||||
resolution: {integrity: sha512-JUOtgFW6k9u4Y+xeIaEiLr3+cjoUPiAuLXoyKOJSia6Duzb7pq+A76P9ZdPDoAoxHdHzq6gE9/jKBGXlZT8FbA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
'@fsegurai/codemirror-theme-vscode-dark@6.1.2':
|
||||
resolution: {integrity: sha512-boId19KW7GTK9Auj2wJw2Woc2G1p3MTvhZPOtTRryiwjDTG+SWxI62fw2m0bA5U0NzDndGbg/6FwTFg+3b49FA==}
|
||||
peerDependencies:
|
||||
'@codemirror/language': ^6.0.0
|
||||
'@codemirror/state': ^6.0.0
|
||||
'@codemirror/view': ^6.0.0
|
||||
'@lezer/highlight': ^1.0.0
|
||||
|
||||
'@fsegurai/codemirror-theme-vscode-light@6.1.2':
|
||||
resolution: {integrity: sha512-/RV/om9okBxOPv6SXXnpDwqd1KdZuutBZnUFGhvVHLi2TIRWFpPMagdO8d2uKnEOMyRg/98DN7x3KLE19bSquw==}
|
||||
peerDependencies:
|
||||
'@codemirror/language': ^6.0.0
|
||||
'@codemirror/state': ^6.0.0
|
||||
'@codemirror/view': ^6.0.0
|
||||
'@lezer/highlight': ^1.0.0
|
||||
|
||||
'@headlessui-float/vue@0.14.4':
|
||||
resolution: {integrity: sha512-MSyWCxUTueeex+veRCf++q4KM/fa4HOe9HDttzGrtgVDBULkGduFK6ItJh7EHJp2U/dY7qpyDUqp2KCHpCEplw==}
|
||||
peerDependencies:
|
||||
@@ -559,6 +647,36 @@ packages:
|
||||
'@jridgewell/trace-mapping@0.3.25':
|
||||
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
|
||||
|
||||
'@lezer/common@1.2.3':
|
||||
resolution: {integrity: sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==}
|
||||
|
||||
'@lezer/css@1.1.11':
|
||||
resolution: {integrity: sha512-FuAnusbLBl1SEAtfN8NdShxYJiESKw9LAFysfea1T96jD3ydBn12oYjaSG1a04BQRIUd93/0D8e5CV1cUMkmQg==}
|
||||
|
||||
'@lezer/highlight@1.2.1':
|
||||
resolution: {integrity: sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==}
|
||||
|
||||
'@lezer/html@1.3.10':
|
||||
resolution: {integrity: sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==}
|
||||
|
||||
'@lezer/javascript@1.4.21':
|
||||
resolution: {integrity: sha512-lL+1fcuxWYPURMM/oFZLEDm0XuLN128QPV+VuGtKpeaOGdcl9F2LYC3nh1S9LkPqx9M0mndZFdXCipNAZpzIkQ==}
|
||||
|
||||
'@lezer/json@1.0.3':
|
||||
resolution: {integrity: sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==}
|
||||
|
||||
'@lezer/lr@1.4.2':
|
||||
resolution: {integrity: sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==}
|
||||
|
||||
'@lezer/markdown@1.4.2':
|
||||
resolution: {integrity: sha512-iYewCigG/517D0xJPQd7RGaCjZAFwROiH8T9h7OTtz0bRVtkxzFhGBFJ9JGKgBBs4uuo1cvxzyQ5iKhDLMcLUQ==}
|
||||
|
||||
'@lezer/yaml@1.0.3':
|
||||
resolution: {integrity: sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==}
|
||||
|
||||
'@marijn/find-cluster-break@1.0.2':
|
||||
resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==}
|
||||
|
||||
'@mermaid-js/layout-elk@0.1.7':
|
||||
resolution: {integrity: sha512-G3AJ2jMaCAqky2CT3z/sf3pK5UuS3tne98GsXDl3PkKByCmPmOYmJPf+6oX5PUlV3HNWWHuSgtZ9NU/CZDSuHQ==}
|
||||
peerDependencies:
|
||||
@@ -850,6 +968,9 @@ packages:
|
||||
'@types/geojson@7946.0.16':
|
||||
resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==}
|
||||
|
||||
'@types/hammerjs@2.0.46':
|
||||
resolution: {integrity: sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw==}
|
||||
|
||||
'@types/istanbul-lib-coverage@2.0.6':
|
||||
resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
|
||||
|
||||
@@ -1279,6 +1400,9 @@ packages:
|
||||
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
codemirror@6.0.1:
|
||||
resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
|
||||
|
||||
color-convert@2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
engines: {node: '>=7.0.0'}
|
||||
@@ -1340,6 +1464,9 @@ packages:
|
||||
cose-base@2.2.0:
|
||||
resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==}
|
||||
|
||||
crelt@1.0.6:
|
||||
resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
|
||||
|
||||
cross-spawn@7.0.6:
|
||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -2007,6 +2134,10 @@ packages:
|
||||
hachure-fill@0.5.2:
|
||||
resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==}
|
||||
|
||||
hammerjs@2.0.8:
|
||||
resolution: {integrity: sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==}
|
||||
engines: {node: '>=0.8.0'}
|
||||
|
||||
has-flag@4.0.0:
|
||||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -3259,6 +3390,9 @@ packages:
|
||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
style-mod@4.1.2:
|
||||
resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==}
|
||||
|
||||
style-to-object@1.0.8:
|
||||
resolution: {integrity: sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==}
|
||||
|
||||
@@ -3679,6 +3813,9 @@ packages:
|
||||
peerDependencies:
|
||||
vue: ^3.2.0
|
||||
|
||||
w3c-keyname@2.2.8:
|
||||
resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
|
||||
|
||||
w3c-xmlserializer@5.0.0:
|
||||
resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -3842,6 +3979,106 @@ snapshots:
|
||||
|
||||
'@chevrotain/utils@11.0.3': {}
|
||||
|
||||
'@codemirror/autocomplete@6.18.6':
|
||||
dependencies:
|
||||
'@codemirror/language': 6.11.0
|
||||
'@codemirror/state': 6.5.2
|
||||
'@codemirror/view': 6.36.5
|
||||
'@lezer/common': 1.2.3
|
||||
|
||||
'@codemirror/commands@6.8.1':
|
||||
dependencies:
|
||||
'@codemirror/language': 6.11.0
|
||||
'@codemirror/state': 6.5.2
|
||||
'@codemirror/view': 6.36.5
|
||||
'@lezer/common': 1.2.3
|
||||
|
||||
'@codemirror/lang-css@6.3.1':
|
||||
dependencies:
|
||||
'@codemirror/autocomplete': 6.18.6
|
||||
'@codemirror/language': 6.11.0
|
||||
'@codemirror/state': 6.5.2
|
||||
'@lezer/common': 1.2.3
|
||||
'@lezer/css': 1.1.11
|
||||
|
||||
'@codemirror/lang-html@6.4.9':
|
||||
dependencies:
|
||||
'@codemirror/autocomplete': 6.18.6
|
||||
'@codemirror/lang-css': 6.3.1
|
||||
'@codemirror/lang-javascript': 6.2.3
|
||||
'@codemirror/language': 6.11.0
|
||||
'@codemirror/state': 6.5.2
|
||||
'@codemirror/view': 6.36.5
|
||||
'@lezer/common': 1.2.3
|
||||
'@lezer/css': 1.1.11
|
||||
'@lezer/html': 1.3.10
|
||||
|
||||
'@codemirror/lang-javascript@6.2.3':
|
||||
dependencies:
|
||||
'@codemirror/autocomplete': 6.18.6
|
||||
'@codemirror/language': 6.11.0
|
||||
'@codemirror/lint': 6.8.5
|
||||
'@codemirror/state': 6.5.2
|
||||
'@codemirror/view': 6.36.5
|
||||
'@lezer/common': 1.2.3
|
||||
'@lezer/javascript': 1.4.21
|
||||
|
||||
'@codemirror/lang-json@6.0.1':
|
||||
dependencies:
|
||||
'@codemirror/language': 6.11.0
|
||||
'@lezer/json': 1.0.3
|
||||
|
||||
'@codemirror/lang-markdown@6.3.2':
|
||||
dependencies:
|
||||
'@codemirror/autocomplete': 6.18.6
|
||||
'@codemirror/lang-html': 6.4.9
|
||||
'@codemirror/language': 6.11.0
|
||||
'@codemirror/state': 6.5.2
|
||||
'@codemirror/view': 6.36.5
|
||||
'@lezer/common': 1.2.3
|
||||
'@lezer/markdown': 1.4.2
|
||||
|
||||
'@codemirror/lang-yaml@6.1.2':
|
||||
dependencies:
|
||||
'@codemirror/autocomplete': 6.18.6
|
||||
'@codemirror/language': 6.11.0
|
||||
'@codemirror/state': 6.5.2
|
||||
'@lezer/common': 1.2.3
|
||||
'@lezer/highlight': 1.2.1
|
||||
'@lezer/lr': 1.4.2
|
||||
'@lezer/yaml': 1.0.3
|
||||
|
||||
'@codemirror/language@6.11.0':
|
||||
dependencies:
|
||||
'@codemirror/state': 6.5.2
|
||||
'@codemirror/view': 6.36.5
|
||||
'@lezer/common': 1.2.3
|
||||
'@lezer/highlight': 1.2.1
|
||||
'@lezer/lr': 1.4.2
|
||||
style-mod: 4.1.2
|
||||
|
||||
'@codemirror/lint@6.8.5':
|
||||
dependencies:
|
||||
'@codemirror/state': 6.5.2
|
||||
'@codemirror/view': 6.36.5
|
||||
crelt: 1.0.6
|
||||
|
||||
'@codemirror/search@6.5.10':
|
||||
dependencies:
|
||||
'@codemirror/state': 6.5.2
|
||||
'@codemirror/view': 6.36.5
|
||||
crelt: 1.0.6
|
||||
|
||||
'@codemirror/state@6.5.2':
|
||||
dependencies:
|
||||
'@marijn/find-cluster-break': 1.0.2
|
||||
|
||||
'@codemirror/view@6.36.5':
|
||||
dependencies:
|
||||
'@codemirror/state': 6.5.2
|
||||
style-mod: 4.1.2
|
||||
w3c-keyname: 2.2.8
|
||||
|
||||
'@csstools/color-helpers@5.0.2': {}
|
||||
|
||||
'@csstools/css-calc@2.1.2(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)':
|
||||
@@ -3978,6 +4215,20 @@ snapshots:
|
||||
|
||||
'@fortawesome/fontawesome-free@6.7.2': {}
|
||||
|
||||
'@fsegurai/codemirror-theme-vscode-dark@6.1.2(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.36.5)(@lezer/highlight@1.2.1)':
|
||||
dependencies:
|
||||
'@codemirror/language': 6.11.0
|
||||
'@codemirror/state': 6.5.2
|
||||
'@codemirror/view': 6.36.5
|
||||
'@lezer/highlight': 1.2.1
|
||||
|
||||
'@fsegurai/codemirror-theme-vscode-light@6.1.2(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.36.5)(@lezer/highlight@1.2.1)':
|
||||
dependencies:
|
||||
'@codemirror/language': 6.11.0
|
||||
'@codemirror/state': 6.5.2
|
||||
'@codemirror/view': 6.36.5
|
||||
'@lezer/highlight': 1.2.1
|
||||
|
||||
'@headlessui-float/vue@0.14.4(@headlessui/vue@1.7.23(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))':
|
||||
dependencies:
|
||||
'@floating-ui/core': 1.6.9
|
||||
@@ -4064,6 +4315,53 @@ snapshots:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
|
||||
'@lezer/common@1.2.3': {}
|
||||
|
||||
'@lezer/css@1.1.11':
|
||||
dependencies:
|
||||
'@lezer/common': 1.2.3
|
||||
'@lezer/highlight': 1.2.1
|
||||
'@lezer/lr': 1.4.2
|
||||
|
||||
'@lezer/highlight@1.2.1':
|
||||
dependencies:
|
||||
'@lezer/common': 1.2.3
|
||||
|
||||
'@lezer/html@1.3.10':
|
||||
dependencies:
|
||||
'@lezer/common': 1.2.3
|
||||
'@lezer/highlight': 1.2.1
|
||||
'@lezer/lr': 1.4.2
|
||||
|
||||
'@lezer/javascript@1.4.21':
|
||||
dependencies:
|
||||
'@lezer/common': 1.2.3
|
||||
'@lezer/highlight': 1.2.1
|
||||
'@lezer/lr': 1.4.2
|
||||
|
||||
'@lezer/json@1.0.3':
|
||||
dependencies:
|
||||
'@lezer/common': 1.2.3
|
||||
'@lezer/highlight': 1.2.1
|
||||
'@lezer/lr': 1.4.2
|
||||
|
||||
'@lezer/lr@1.4.2':
|
||||
dependencies:
|
||||
'@lezer/common': 1.2.3
|
||||
|
||||
'@lezer/markdown@1.4.2':
|
||||
dependencies:
|
||||
'@lezer/common': 1.2.3
|
||||
'@lezer/highlight': 1.2.1
|
||||
|
||||
'@lezer/yaml@1.0.3':
|
||||
dependencies:
|
||||
'@lezer/common': 1.2.3
|
||||
'@lezer/highlight': 1.2.1
|
||||
'@lezer/lr': 1.4.2
|
||||
|
||||
'@marijn/find-cluster-break@1.0.2': {}
|
||||
|
||||
'@mermaid-js/layout-elk@0.1.7(mermaid@11.6.0)':
|
||||
dependencies:
|
||||
d3: 7.9.0
|
||||
@@ -4349,6 +4647,8 @@ snapshots:
|
||||
|
||||
'@types/geojson@7946.0.16': {}
|
||||
|
||||
'@types/hammerjs@2.0.46': {}
|
||||
|
||||
'@types/istanbul-lib-coverage@2.0.6': {}
|
||||
|
||||
'@types/json-schema@7.0.15': {}
|
||||
@@ -4901,6 +5201,16 @@ snapshots:
|
||||
|
||||
clsx@2.1.1: {}
|
||||
|
||||
codemirror@6.0.1:
|
||||
dependencies:
|
||||
'@codemirror/autocomplete': 6.18.6
|
||||
'@codemirror/commands': 6.8.1
|
||||
'@codemirror/language': 6.11.0
|
||||
'@codemirror/lint': 6.8.5
|
||||
'@codemirror/search': 6.5.10
|
||||
'@codemirror/state': 6.5.2
|
||||
'@codemirror/view': 6.36.5
|
||||
|
||||
color-convert@2.0.1:
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
@@ -4950,6 +5260,8 @@ snapshots:
|
||||
dependencies:
|
||||
layout-base: 2.0.1
|
||||
|
||||
crelt@1.0.6: {}
|
||||
|
||||
cross-spawn@7.0.6:
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
@@ -5735,6 +6047,8 @@ snapshots:
|
||||
|
||||
hachure-fill@0.5.2: {}
|
||||
|
||||
hammerjs@2.0.8: {}
|
||||
|
||||
has-flag@4.0.0: {}
|
||||
|
||||
has-symbols@1.1.0: {}
|
||||
@@ -6859,6 +7173,8 @@ snapshots:
|
||||
|
||||
strip-json-comments@3.1.1: {}
|
||||
|
||||
style-mod@4.1.2: {}
|
||||
|
||||
style-to-object@1.0.8:
|
||||
dependencies:
|
||||
inline-style-parser: 0.2.4
|
||||
@@ -7249,6 +7565,8 @@ snapshots:
|
||||
'@vue/devtools-api': 6.6.4
|
||||
vue: 3.5.13(typescript@5.8.2)
|
||||
|
||||
w3c-keyname@2.2.8: {}
|
||||
|
||||
w3c-xmlserializer@5.0.0:
|
||||
dependencies:
|
||||
xml-name-validator: 5.0.0
|
||||
|
||||
+2
-4
@@ -4,16 +4,14 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Online FlowChart & Diagrams Editor - Mermaid Live Editor</title>
|
||||
<meta
|
||||
name="og:image"
|
||||
content="https://github.com/mermaid-js/mermaid/raw/develop/img/header.png" />
|
||||
<meta name="og:image" content="%sveltekit.assets%/favicon.svg" />
|
||||
<link rel="canonical" href="https://mermaid.live" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Simplify documentation and avoid heavy tools. Open source Visio Alternative. Commonly used for explaining your code! Mermaid is a simple markdown-like script language for generating charts from text via javascript." />
|
||||
<link rel="icon" type="image/png" href="%sveltekit.assets%/favicon.svg" />
|
||||
<link rel="mask-icon" href="%sveltekit.assets%/favicon.svg" color="#000000" />
|
||||
<meta name="theme-color" content="#6366F1" />
|
||||
<meta name="theme-color" content="#ff3670" />
|
||||
<link rel="manifest" href="%sveltekit.assets%/manifest.json" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
<script lang="ts">
|
||||
import type { EditorProps } from '$/types';
|
||||
import { stateStore } from '$/util/state';
|
||||
import { initEditor } from '$lib/util/monacoExtra';
|
||||
import { errorDebug } from '$lib/util/util';
|
||||
import { mode } from 'mode-watcher';
|
||||
import * as monaco from 'monaco-editor';
|
||||
import monacoEditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
|
||||
import monacoJsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
const { onUpdate }: EditorProps = $props();
|
||||
|
||||
let divElement: HTMLDivElement | undefined = $state();
|
||||
let editor: monaco.editor.IStandaloneCodeEditor | undefined;
|
||||
let editorOptions = {
|
||||
minimap: {
|
||||
enabled: false
|
||||
},
|
||||
overviewRulerLanes: 0
|
||||
} satisfies monaco.editor.IStandaloneEditorConstructionOptions;
|
||||
let currentText = '';
|
||||
|
||||
onMount(() => {
|
||||
self.MonacoEnvironment = {
|
||||
getWorker(_, label) {
|
||||
if (label === 'json') {
|
||||
return new monacoJsonWorker();
|
||||
}
|
||||
return new monacoEditorWorker();
|
||||
}
|
||||
};
|
||||
|
||||
if (!divElement) {
|
||||
throw new Error('divEl is undefined');
|
||||
}
|
||||
|
||||
initEditor(monaco);
|
||||
errorDebug();
|
||||
editor = monaco.editor.create(divElement, editorOptions);
|
||||
editor.onDidChangeModelContent(({ isFlush }) => {
|
||||
const newText = editor?.getValue();
|
||||
if (!newText || currentText === newText || isFlush) {
|
||||
return;
|
||||
}
|
||||
currentText = newText;
|
||||
onUpdate(currentText);
|
||||
});
|
||||
|
||||
const unsubscribeState = stateStore.subscribe(({ errorMarkers, editorMode, code, mermaid }) => {
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update editor text if it's different
|
||||
const newText = editorMode === 'code' ? code : mermaid;
|
||||
if (newText !== currentText) {
|
||||
editor.setScrollTop(0);
|
||||
editor.setValue(newText);
|
||||
currentText = newText;
|
||||
}
|
||||
|
||||
// Update editor mode if it's different
|
||||
const language = editorMode === 'code' ? 'mermaid' : 'json';
|
||||
const model = editor.getModel();
|
||||
if (!model) {
|
||||
console.error("editor model doesn't exist");
|
||||
return;
|
||||
}
|
||||
if (model.getLanguageId() !== language) {
|
||||
monaco.editor.setModelLanguage(model, language);
|
||||
}
|
||||
|
||||
// Display/clear errors
|
||||
monaco.editor.setModelMarkers(model, 'mermaid', errorMarkers);
|
||||
});
|
||||
|
||||
const unsubscribeMode = mode.subscribe((mode) => {
|
||||
editor && monaco.editor.setTheme(`mermaid${mode === 'dark' ? '-dark' : ''}`);
|
||||
});
|
||||
const resizeObserver = new ResizeObserver((entries) => {
|
||||
editor?.layout({
|
||||
height: entries[0].contentRect.height,
|
||||
width: entries[0].contentRect.width
|
||||
});
|
||||
});
|
||||
|
||||
if (divElement.parentElement) {
|
||||
resizeObserver.observe(divElement);
|
||||
}
|
||||
|
||||
return () => {
|
||||
unsubscribeState();
|
||||
unsubscribeMode();
|
||||
resizeObserver.disconnect();
|
||||
editor?.dispose();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<div bind:this={divElement} id="editor" class="h-full flex-grow overflow-hidden"></div>
|
||||
@@ -1,117 +1,30 @@
|
||||
<script lang="ts">
|
||||
import DesktopEditor from '$/components/DesktopEditor.svelte';
|
||||
import McWrapper from '$/components/McWrapper.svelte';
|
||||
import MermaidChartIcon from '$/components/MermaidChartIcon.svelte';
|
||||
import MobileEditor from '$/components/MobileEditor.svelte';
|
||||
import { Button } from '$/components/ui/button';
|
||||
import { TID } from '$/constants';
|
||||
import { env } from '$/util/env';
|
||||
import type { EditorMode } from '$lib/types';
|
||||
import { initEditor } from '$lib/util/monacoExtra';
|
||||
import { stateStore, updateCode, updateConfig, urlsStore } from '$lib/util/state';
|
||||
import { errorDebug } from '$lib/util/util';
|
||||
import { mode } from 'mode-watcher';
|
||||
import * as monaco from 'monaco-editor';
|
||||
import monacoEditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
|
||||
import monacoJsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
|
||||
import { onMount } from 'svelte';
|
||||
import ExclamationCircleIcon from '~icons/material-symbols/error-outline-rounded';
|
||||
|
||||
let divElement: HTMLDivElement | undefined = $state();
|
||||
let editor: monaco.editor.IStandaloneCodeEditor | undefined;
|
||||
let editorOptions: monaco.editor.IStandaloneEditorConstructionOptions = {
|
||||
minimap: {
|
||||
enabled: false
|
||||
},
|
||||
theme: 'mermaid',
|
||||
overviewRulerLanes: 0
|
||||
};
|
||||
let currentText = '';
|
||||
|
||||
const unsubscribeState = stateStore.subscribe(({ errorMarkers, editorMode, code, mermaid }) => {
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update editor text if it's different
|
||||
const newText = editorMode === 'code' ? code : mermaid;
|
||||
if (newText !== currentText) {
|
||||
editor.setScrollTop(0);
|
||||
editor.setValue(newText);
|
||||
currentText = newText;
|
||||
}
|
||||
|
||||
// Update editor mode if it's different
|
||||
const language = editorMode === 'code' ? 'mermaid' : 'json';
|
||||
const model = editor.getModel();
|
||||
if (!model) {
|
||||
console.error("editor model doesn't exist");
|
||||
return;
|
||||
}
|
||||
if (model.getLanguageId() !== language) {
|
||||
monaco.editor.setModelLanguage(model, language);
|
||||
}
|
||||
|
||||
// Display/clear errors
|
||||
monaco.editor.setModelMarkers(model, 'mermaid', errorMarkers);
|
||||
});
|
||||
|
||||
const handleUpdate = (text: string, mode: EditorMode) => {
|
||||
if (mode === 'code') {
|
||||
let { isMobile }: { isMobile: boolean } = $props();
|
||||
const onUpdate = (text: string) => {
|
||||
if ($stateStore.editorMode === 'code') {
|
||||
updateCode(text);
|
||||
} else {
|
||||
updateConfig(text);
|
||||
}
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
self.MonacoEnvironment = {
|
||||
getWorker(_, label) {
|
||||
if (label === 'json') {
|
||||
return new monacoJsonWorker();
|
||||
}
|
||||
return new monacoEditorWorker();
|
||||
}
|
||||
};
|
||||
|
||||
if (!divElement) {
|
||||
throw new Error('divEl is undefined');
|
||||
}
|
||||
|
||||
initEditor(monaco);
|
||||
errorDebug();
|
||||
editor = monaco.editor.create(divElement, editorOptions);
|
||||
editor.onDidChangeModelContent(({ isFlush }) => {
|
||||
const newText = editor?.getValue();
|
||||
if (!newText || currentText === newText || isFlush) {
|
||||
return;
|
||||
}
|
||||
currentText = newText;
|
||||
handleUpdate(currentText, $stateStore.editorMode);
|
||||
});
|
||||
const unsubscribeMode = mode.subscribe((mode) => {
|
||||
editor && monaco.editor.setTheme(`mermaid${mode === 'dark' ? '-dark' : ''}`);
|
||||
});
|
||||
const resizeObserver = new ResizeObserver((entries) => {
|
||||
editor?.layout({
|
||||
height: entries[0].contentRect.height,
|
||||
width: entries[0].contentRect.width
|
||||
});
|
||||
});
|
||||
|
||||
if (divElement.parentElement) {
|
||||
resizeObserver.observe(divElement);
|
||||
}
|
||||
|
||||
return () => {
|
||||
unsubscribeState();
|
||||
unsubscribeMode();
|
||||
resizeObserver.disconnect();
|
||||
editor?.dispose();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="flex h-full flex-col pt-1">
|
||||
<div bind:this={divElement} id="editor" class="h-full flex-grow overflow-hidden"></div>
|
||||
<div class="flex h-full flex-col">
|
||||
{#if isMobile}
|
||||
<MobileEditor {onUpdate} />
|
||||
{:else}
|
||||
<DesktopEditor {onUpdate} />
|
||||
{/if}
|
||||
{#if $stateStore.error instanceof Error}
|
||||
<div class="flex flex-col text-sm" data-testid={TID.errorContainer}>
|
||||
<div class="flex items-center justify-between gap-2 bg-slate-900 p-2 text-white">
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
let { children }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="hidden h-12 items-center justify-between gap-2 rounded-2xl bg-muted p-3 md:flex">
|
||||
<div class="flex h-12 items-center justify-between gap-2 rounded-2xl bg-muted p-3">
|
||||
{@render children()}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
<script lang="ts">
|
||||
import type { EditorProps } from '$/types';
|
||||
import { stateStore } from '$/util/state';
|
||||
import { json, jsonLanguage } from '@codemirror/lang-json';
|
||||
import { markdown } from '@codemirror/lang-markdown';
|
||||
import { yamlFrontmatter } from '@codemirror/lang-yaml';
|
||||
import { language } from '@codemirror/language';
|
||||
import { Compartment, EditorState } from '@codemirror/state';
|
||||
import { EditorView } from '@codemirror/view';
|
||||
import { vsCodeDark } from '@fsegurai/codemirror-theme-vscode-dark';
|
||||
import { vsCodeLight } from '@fsegurai/codemirror-theme-vscode-light';
|
||||
import { basicSetup } from 'codemirror';
|
||||
import { mode } from 'mode-watcher';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let editorView: EditorView | undefined;
|
||||
let editorContainer: HTMLDivElement;
|
||||
let currentText = $state('');
|
||||
|
||||
const { onUpdate }: EditorProps = $props();
|
||||
|
||||
onMount(() => {
|
||||
const themeCompartment = new Compartment();
|
||||
const languageCompartment = new Compartment();
|
||||
|
||||
editorView = new EditorView({
|
||||
state: EditorState.create({
|
||||
doc: currentText,
|
||||
extensions: [
|
||||
basicSetup,
|
||||
languageCompartment.of([]),
|
||||
themeCompartment.of([]),
|
||||
EditorView.updateListener.of((update) => {
|
||||
if (update.docChanged) {
|
||||
const newText = update.state.doc.toString();
|
||||
if (currentText === newText) {
|
||||
return;
|
||||
}
|
||||
currentText = newText;
|
||||
onUpdate(newText);
|
||||
}
|
||||
}),
|
||||
EditorView.theme({
|
||||
'&.cm-focused': {
|
||||
outline: 'none'
|
||||
},
|
||||
'&.cm-editor': {
|
||||
height: '100%'
|
||||
},
|
||||
'&.cm-scroller': {
|
||||
overflow: 'auto'
|
||||
}
|
||||
})
|
||||
]
|
||||
}),
|
||||
parent: editorContainer
|
||||
});
|
||||
|
||||
const unsubscribeMode = mode.subscribe((mode) => {
|
||||
editorView?.dispatch({
|
||||
effects: themeCompartment.reconfigure(mode === 'dark' ? vsCodeDark : vsCodeLight)
|
||||
});
|
||||
});
|
||||
|
||||
const unsubscribeState = stateStore.subscribe(({ editorMode, code, mermaid }) => {
|
||||
const text = editorMode === 'code' ? code : mermaid;
|
||||
if (currentText === text || !editorView) {
|
||||
return;
|
||||
}
|
||||
currentText = text;
|
||||
editorView.dispatch({
|
||||
changes: {
|
||||
from: 0,
|
||||
to: editorView.state.doc.length,
|
||||
insert: text
|
||||
}
|
||||
});
|
||||
const stateLanguage = editorView.state.facet(language);
|
||||
const isStateJson = stateLanguage === jsonLanguage;
|
||||
const isCodeJson = editorMode === 'config';
|
||||
if (stateLanguage && isStateJson === isCodeJson) {
|
||||
return;
|
||||
}
|
||||
editorView.dispatch({
|
||||
effects: languageCompartment.reconfigure(
|
||||
isCodeJson ? json() : yamlFrontmatter({ content: markdown() })
|
||||
)
|
||||
});
|
||||
});
|
||||
|
||||
return () => {
|
||||
unsubscribeMode();
|
||||
unsubscribeState();
|
||||
editorView?.destroy();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<div bind:this={editorContainer} class="size-full"></div>
|
||||
@@ -22,10 +22,11 @@
|
||||
import DropdownNavMenu from './DropdownNavMenu.svelte';
|
||||
|
||||
interface Props {
|
||||
mobileToggle?: Snippet;
|
||||
children: Snippet;
|
||||
}
|
||||
|
||||
let { children }: Props = $props();
|
||||
let { children, mobileToggle }: Props = $props();
|
||||
|
||||
const isReferral = document.referrer.includes(MCBaseURL);
|
||||
|
||||
@@ -81,7 +82,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<nav class="z-50 flex p-6">
|
||||
<nav class="z-50 flex p-4 sm:p-6">
|
||||
<div class="flex flex-1 items-center gap-4">
|
||||
<MainMenu />
|
||||
<div
|
||||
@@ -89,7 +90,7 @@
|
||||
class="flex items-center justify-center gap-4 font-medium"
|
||||
class:flex-row-reverse={isReferral}>
|
||||
<a href="/" class="whitespace-nowrap text-accent">
|
||||
{#if !isReferral}
|
||||
{#if !isReferral && !mobileToggle}
|
||||
Mermaid
|
||||
{/if}
|
||||
Live Editor
|
||||
@@ -132,4 +133,5 @@
|
||||
<Separator orientation="vertical" />
|
||||
{@render children()}
|
||||
</div>
|
||||
{@render mobileToggle?.()}
|
||||
</nav>
|
||||
|
||||
@@ -17,13 +17,17 @@
|
||||
<ArrowsToCircleIcon />
|
||||
</Button>
|
||||
<Separator orientation="vertical" />
|
||||
<Button variant="ghost" size="icon" onclick={() => panZoomState.zoomOut()}>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
class="hidden sm:block"
|
||||
onclick={() => panZoomState.zoomOut()}>
|
||||
<MagnifyingGlassMinusIcon />
|
||||
</Button>
|
||||
<Button variant="ghost" size="icon" onclick={() => panZoomState.zoomIn()}>
|
||||
<Button variant="ghost" size="icon" class="hidden sm:block" onclick={() => panZoomState.zoomIn()}>
|
||||
<MagnifyingGlassPlusIcon />
|
||||
</Button>
|
||||
<Separator orientation="vertical" />
|
||||
<Separator orientation="vertical" class="hidden sm:block" />
|
||||
<Button variant="ghost" size="icon" title="Full Screen" href={$urlsStore.view} target="_blank">
|
||||
<ExpandIcon />
|
||||
</Button>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<Dialog.Trigger>
|
||||
<ShieldIcon />
|
||||
</Dialog.Trigger>
|
||||
<Dialog.Content>
|
||||
<Dialog.Content class="max-h-full overflow-y-auto">
|
||||
<Dialog.Header>
|
||||
<Dialog.Title class="flex items-center gap-2 text-xl">
|
||||
<ShieldIcon class="size-8 text-green-700" />
|
||||
|
||||
Vendored
+4
@@ -101,3 +101,7 @@ export interface ErrorHash {
|
||||
}
|
||||
|
||||
export type InputType = Exclude<HTMLInputTypeAttribute, 'file'>;
|
||||
|
||||
export interface EditorProps {
|
||||
onUpdate: (text: string) => void;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { State } from '$/types';
|
||||
import Hammer from 'hammerjs';
|
||||
import type { Point } from 'mermaid/dist/types.js';
|
||||
import panzoom from 'svg-pan-zoom';
|
||||
type PanZoom = typeof panzoom;
|
||||
@@ -24,9 +25,56 @@ export class PanZoomState {
|
||||
}
|
||||
|
||||
public updateElement(diagramView: SVGElement, { pan, zoom }: Pick<State, 'pan' | 'zoom'>) {
|
||||
this.pzoom?.destroy();
|
||||
let hammer: HammerManager | undefined;
|
||||
this.pzoom = panzoom(diagramView, {
|
||||
center: true,
|
||||
controlIconsEnabled: false,
|
||||
customEventsHandler: {
|
||||
haltEventListeners: ['touchstart', 'touchend', 'touchmove', 'touchleave', 'touchcancel'],
|
||||
init: function (options) {
|
||||
const instance = options.instance;
|
||||
let initialScale = 1;
|
||||
let pannedX = 0;
|
||||
let pannedY = 0;
|
||||
hammer = new Hammer(options.svgElement);
|
||||
|
||||
const resetPanned = () => {
|
||||
pannedX = 0;
|
||||
pannedY = 0;
|
||||
};
|
||||
const handlePan = (event: HammerInput) => {
|
||||
instance.panBy({ x: event.deltaX - pannedX, y: event.deltaY - pannedY });
|
||||
pannedX = event.deltaX;
|
||||
pannedY = event.deltaY;
|
||||
};
|
||||
|
||||
hammer.get('pinch').set({ enable: true });
|
||||
hammer.on('panstart panmove', function (event) {
|
||||
if (event.type === 'panstart') {
|
||||
resetPanned();
|
||||
}
|
||||
handlePan(event);
|
||||
});
|
||||
hammer.on('pinchstart pinchmove', function (event) {
|
||||
if (event.type === 'pinchstart') {
|
||||
initialScale = instance.getZoom();
|
||||
resetPanned();
|
||||
}
|
||||
instance.zoomAtPoint(initialScale * event.scale, {
|
||||
x: event.center.x,
|
||||
y: event.center.y
|
||||
});
|
||||
handlePan(event);
|
||||
});
|
||||
options.svgElement.addEventListener('touchmove', function (event) {
|
||||
event.preventDefault();
|
||||
});
|
||||
},
|
||||
destroy: function () {
|
||||
hammer?.destroy();
|
||||
}
|
||||
},
|
||||
fit: true,
|
||||
maxZoom: 12,
|
||||
minZoom: 0.2,
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="flex w-full bg-[#E0095F] p-1.5"
|
||||
class="flex w-full items-center bg-[#E0095F] p-1.5"
|
||||
role="banner"
|
||||
onmouseenter={() => (shouldAnimate = false)}
|
||||
onmouseleave={() => (shouldAnimate = true)}>
|
||||
|
||||
@@ -85,8 +85,10 @@ const delaysPerEvent = {
|
||||
loadGist: defaultDelay,
|
||||
loadSampleDiagram: defaultDelay,
|
||||
migration: defaultDelay,
|
||||
mobileViewToggle: defaultDelay,
|
||||
panZoom: minutesToMilliSeconds(10),
|
||||
playgroundToggle: 0,
|
||||
pwaInstalled: defaultDelay,
|
||||
render: minutesToMilliSeconds(5),
|
||||
renderDiagram: defaultDelay,
|
||||
themeChange: defaultDelay,
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<ModeWatcher />
|
||||
<Toaster />
|
||||
|
||||
<main class="h-screen">
|
||||
<main class="h-[100dvh]">
|
||||
{@render children()}
|
||||
</main>
|
||||
|
||||
|
||||
@@ -13,12 +13,14 @@
|
||||
import SyncRoughToolbar from '$/components/SyncRoughToolbar.svelte';
|
||||
import { Button } from '$/components/ui/button';
|
||||
import * as Resizable from '$/components/ui/resizable';
|
||||
import { Switch } from '$/components/ui/switch';
|
||||
import { Toggle } from '$/components/ui/toggle';
|
||||
import VersionSecurityToolbar from '$/components/VersionSecurityToolbar.svelte';
|
||||
import View from '$/components/View.svelte';
|
||||
import type { EditorMode, Tab } from '$/types';
|
||||
import { PanZoomState } from '$/util/panZoom';
|
||||
import { stateStore, updateCodeStore, urlsStore } from '$/util/state';
|
||||
import { logEvent } from '$/util/stats';
|
||||
import { initHandler } from '$/util/util';
|
||||
import { onMount } from 'svelte';
|
||||
import CodeIcon from '~icons/custom/code';
|
||||
@@ -45,15 +47,41 @@
|
||||
}
|
||||
];
|
||||
|
||||
let width = $state(0);
|
||||
let isMobile = $derived(width < 640);
|
||||
let isViewMode = $state(true);
|
||||
|
||||
onMount(async () => {
|
||||
await initHandler();
|
||||
window.addEventListener('appinstalled', () => {
|
||||
logEvent('pwaInstalled', { isMobile });
|
||||
});
|
||||
});
|
||||
|
||||
let isHistoryOpen = $state(false);
|
||||
|
||||
let editorPane: Resizable.Pane | undefined;
|
||||
$effect(() => {
|
||||
if (isMobile) {
|
||||
editorPane?.resize(50);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="flex h-full flex-col overflow-hidden">
|
||||
<Navbar>
|
||||
{#snippet mobileToggle()}
|
||||
<div class="flex items-center gap-2">
|
||||
Edit <Switch
|
||||
id="editorMode"
|
||||
class="data-[state=checked]:bg-accent"
|
||||
bind:checked={isViewMode}
|
||||
onclick={() => {
|
||||
logEvent('mobileViewToggle');
|
||||
}} /> View
|
||||
</div>
|
||||
{/snippet}
|
||||
|
||||
<Navbar mobileToggle={isMobile ? mobileToggle : undefined}>
|
||||
<Toggle bind:pressed={isHistoryOpen} size="sm">
|
||||
<HistoryIcon />
|
||||
</Toggle>
|
||||
@@ -70,47 +98,53 @@
|
||||
</McWrapper>
|
||||
</Navbar>
|
||||
|
||||
<div class="flex flex-1 overflow-hidden">
|
||||
<Resizable.PaneGroup direction="horizontal" autoSaveId="liveEditor" class="p-6 pt-0">
|
||||
<Resizable.Pane defaultSize={30} minSize={15} class="hidden md:block">
|
||||
<div class="flex h-full flex-col gap-6" id="editorPane">
|
||||
<Card
|
||||
onselect={tabSelectHandler}
|
||||
isOpen
|
||||
tabs={editorTabs}
|
||||
activeTabID={$stateStore.editorMode}
|
||||
isClosable={false}>
|
||||
{#snippet actions()}
|
||||
<DiagramDocButton />
|
||||
{/snippet}
|
||||
<Editor />
|
||||
</Card>
|
||||
<div class="flex flex-1 flex-col overflow-hidden" bind:clientWidth={width}>
|
||||
<div
|
||||
class={[
|
||||
'size-full',
|
||||
isMobile && ['w-[200%] duration-300', isViewMode && '-translate-x-1/2']
|
||||
]}>
|
||||
<Resizable.PaneGroup
|
||||
direction="horizontal"
|
||||
autoSaveId="liveEditor"
|
||||
class="gap-4 p-2 pt-0 sm:gap-0 sm:p-6 sm:pt-0">
|
||||
<Resizable.Pane bind:this={editorPane} defaultSize={30} minSize={15}>
|
||||
<div class="flex h-full flex-col gap-4 sm:gap-6">
|
||||
<Card
|
||||
onselect={tabSelectHandler}
|
||||
isOpen
|
||||
tabs={editorTabs}
|
||||
activeTabID={$stateStore.editorMode}
|
||||
isClosable={false}>
|
||||
{#snippet actions()}
|
||||
<DiagramDocButton />
|
||||
{/snippet}
|
||||
<Editor {isMobile} />
|
||||
</Card>
|
||||
|
||||
<div class="group flex flex-wrap justify-between gap-6">
|
||||
<Preset />
|
||||
<Actions />
|
||||
<div class="group flex flex-wrap justify-between gap-4 sm:gap-6">
|
||||
<Preset />
|
||||
<Actions />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Resizable.Pane>
|
||||
<Resizable.Handle class="mr-1 opacity-0" />
|
||||
<Resizable.Pane minSize={15} class="relative flex h-full flex-1 flex-col overflow-hidden">
|
||||
<View {panZoomState} shouldShowGrid={$stateStore.grid} />
|
||||
<div class="absolute right-0 top-0"><PanZoomToolbar {panZoomState} /></div>
|
||||
<div class="absolute bottom-0 right-0"><VersionSecurityToolbar /></div>
|
||||
<div class="absolute bottom-0 left-5"><SyncRoughToolbar /></div>
|
||||
<div class="rounded bg-primary p-2 text-center shadow md:hidden">
|
||||
Code editing not supported on mobile. Please use a desktop browser.
|
||||
</div>
|
||||
</Resizable.Pane>
|
||||
{#if isHistoryOpen}
|
||||
<Resizable.Handle class="ml-1 hidden opacity-0 md:block" />
|
||||
<Resizable.Pane
|
||||
minSize={15}
|
||||
defaultSize={30}
|
||||
class="hidden h-full flex-grow flex-col md:flex">
|
||||
<History />
|
||||
</Resizable.Pane>
|
||||
{/if}
|
||||
</Resizable.PaneGroup>
|
||||
<Resizable.Handle class="mr-1 hidden opacity-0 sm:block" />
|
||||
<Resizable.Pane minSize={15} class="relative flex h-full flex-1 flex-col overflow-hidden">
|
||||
<View {panZoomState} shouldShowGrid={$stateStore.grid} />
|
||||
<div class="absolute right-0 top-0"><PanZoomToolbar {panZoomState} /></div>
|
||||
<div class="absolute bottom-0 right-0"><VersionSecurityToolbar /></div>
|
||||
<div class="absolute bottom-0 left-0 sm:left-5"><SyncRoughToolbar /></div>
|
||||
</Resizable.Pane>
|
||||
{#if isHistoryOpen}
|
||||
<Resizable.Handle class="ml-1 hidden opacity-0 sm:block" />
|
||||
<Resizable.Pane
|
||||
minSize={15}
|
||||
defaultSize={30}
|
||||
class="hidden h-full flex-grow flex-col sm:flex">
|
||||
<History />
|
||||
</Resizable.Pane>
|
||||
{/if}
|
||||
</Resizable.PaneGroup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 491 491" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<path d="M490.16,84.61C490.16,37.912 452.248,0 405.55,0L84.61,0C37.912,0 0,37.912 0,84.61L0,405.55C0,452.248 37.912,490.16 84.61,490.16L405.55,490.16C452.248,490.16 490.16,452.248 490.16,405.55L490.16,84.61Z" style="fill:rgb(255,54,112);"/>
|
||||
<svg width="100%" height="100%" viewBox="0 0 490 490" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<path d="M490.16,84.61C490.16,37.912 452.248,0 405.55,0L84.61,0C37.912,0 0,37.912 0,84.61L0,405.55C0,452.248 37.912,490.16 84.61,490.16L405.55,490.16C452.248,490.16 490.16,452.248 490.16,405.55L490.16,84.61Z" style="fill:#ff3670;"/>
|
||||
<path d="M407.48,111.18C335.587,108.103 269.573,152.338 245.08,220C220.587,152.338 154.573,108.103 82.68,111.18C80.285,168.229 107.577,222.632 154.74,254.82C178.908,271.419 193.35,298.951 193.27,328.27L193.27,379.13L296.9,379.13L296.9,328.27C296.816,298.953 311.255,271.42 335.42,254.82C382.596,222.644 409.892,168.233 407.48,111.18Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -9,10 +9,10 @@
|
||||
}
|
||||
],
|
||||
"start_url": "/edit",
|
||||
"background_color": "#6366F1",
|
||||
"background_color": "#ff3670",
|
||||
"display": "standalone",
|
||||
"scope": "/edit",
|
||||
"theme_color": "#6366F1",
|
||||
"theme_color": "#ff3670",
|
||||
"description": "FlowChart & Diagrams Editor.",
|
||||
"orientation": "landscape"
|
||||
"orientation": "natural"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user