diff --git a/examples/dev-node-state-style/README.md b/examples/dev-node-state-style/README.md
new file mode 100644
index 00000000000..5e639ed3aca
--- /dev/null
+++ b/examples/dev-node-state-style/README.md
@@ -0,0 +1,13 @@
+# DEV Node State Style example
+
+Here we have an example that demonstrates how NodeState can be used with a
+DOMRenderExtension to override create and export behavior of any node.
+
+This example currently depends on unreleased features (v0.37+) and will not
+work outside of the monorepo.
+
+**Run it locally:** `npm i && npm run dev`
+
+[](https://stackblitz.com/github/facebook/lexical/tree/main?file=examples/dev-node-state-style/src/main.tsx&startCommand=npm%20run%20start:example%20dev-node-state-style)
+
+[](https://stackblitz.com/github/etrepum/lexical/tree/extensible-dom-export?file=examples/dev-node-state-style/src/main.tsx&startCommand=npm%20run%20start:example%20dev-node-state-style)
diff --git a/examples/dev-node-state-style/index.html b/examples/dev-node-state-style/index.html
new file mode 100644
index 00000000000..27517b253ae
--- /dev/null
+++ b/examples/dev-node-state-style/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Lexical Node State Example
+
+
+
+
+
+
diff --git a/examples/dev-node-state-style/package-lock.json b/examples/dev-node-state-style/package-lock.json
new file mode 100644
index 00000000000..98f1aaf5879
--- /dev/null
+++ b/examples/dev-node-state-style/package-lock.json
@@ -0,0 +1,2633 @@
+{
+ "name": "@lexical/node-state-style-example",
+ "version": "0.36.1",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "@lexical/node-state-style-example",
+ "version": "0.36.1",
+ "dependencies": {
+ "@ark-ui/react": "^5.6.0",
+ "@lexical/clipboard": "0.36.1",
+ "@lexical/html": "0.36.1",
+ "@lexical/react": "0.36.1",
+ "@lexical/selection": "0.36.1",
+ "@lexical/utils": "0.36.1",
+ "@shikijs/langs": "^3.3.0",
+ "@shikijs/themes": "^3.3.0",
+ "inline-style-parser": "^0.2.4",
+ "lexical": "0.36.1",
+ "lucide-react": "^0.503.0",
+ "prettier": "^3.5.3",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0",
+ "shiki": "^3.3.0"
+ },
+ "devDependencies": {
+ "@types/react": "^19.1.2",
+ "@types/react-dom": "^19.1.2",
+ "@vitejs/plugin-react": "^5.0.2",
+ "cross-env": "^7.0.3",
+ "csstype": "^3.1.3",
+ "typescript": "^5.9.2",
+ "vite": "^7.1.4"
+ }
+ },
+ "node_modules/@ark-ui/react": {
+ "version": "5.25.0",
+ "license": "MIT",
+ "dependencies": {
+ "@internationalized/date": "3.9.0",
+ "@zag-js/accordion": "1.24.1",
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/angle-slider": "1.24.1",
+ "@zag-js/async-list": "1.24.1",
+ "@zag-js/auto-resize": "1.24.1",
+ "@zag-js/avatar": "1.24.1",
+ "@zag-js/carousel": "1.24.1",
+ "@zag-js/checkbox": "1.24.1",
+ "@zag-js/clipboard": "1.24.1",
+ "@zag-js/collapsible": "1.24.1",
+ "@zag-js/collection": "1.24.1",
+ "@zag-js/color-picker": "1.24.1",
+ "@zag-js/color-utils": "1.24.1",
+ "@zag-js/combobox": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/date-picker": "1.24.1",
+ "@zag-js/date-utils": "1.24.1",
+ "@zag-js/dialog": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/editable": "1.24.1",
+ "@zag-js/file-upload": "1.24.1",
+ "@zag-js/file-utils": "1.24.1",
+ "@zag-js/floating-panel": "1.24.1",
+ "@zag-js/focus-trap": "1.24.1",
+ "@zag-js/highlight-word": "1.24.1",
+ "@zag-js/hover-card": "1.24.1",
+ "@zag-js/i18n-utils": "1.24.1",
+ "@zag-js/json-tree-utils": "1.24.1",
+ "@zag-js/listbox": "1.24.1",
+ "@zag-js/menu": "1.24.1",
+ "@zag-js/number-input": "1.24.1",
+ "@zag-js/pagination": "1.24.1",
+ "@zag-js/password-input": "1.24.1",
+ "@zag-js/pin-input": "1.24.1",
+ "@zag-js/popover": "1.24.1",
+ "@zag-js/presence": "1.24.1",
+ "@zag-js/progress": "1.24.1",
+ "@zag-js/qr-code": "1.24.1",
+ "@zag-js/radio-group": "1.24.1",
+ "@zag-js/rating-group": "1.24.1",
+ "@zag-js/react": "1.24.1",
+ "@zag-js/scroll-area": "1.24.1",
+ "@zag-js/select": "1.24.1",
+ "@zag-js/signature-pad": "1.24.1",
+ "@zag-js/slider": "1.24.1",
+ "@zag-js/splitter": "1.24.1",
+ "@zag-js/steps": "1.24.1",
+ "@zag-js/switch": "1.24.1",
+ "@zag-js/tabs": "1.24.1",
+ "@zag-js/tags-input": "1.24.1",
+ "@zag-js/timer": "1.24.1",
+ "@zag-js/toast": "1.24.1",
+ "@zag-js/toggle": "1.24.1",
+ "@zag-js/toggle-group": "1.24.1",
+ "@zag-js/tooltip": "1.24.1",
+ "@zag-js/tour": "1.24.1",
+ "@zag-js/tree-view": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ },
+ "peerDependencies": {
+ "react": ">=18.0.0",
+ "react-dom": ">=18.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.28.4",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.28.4",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.3",
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-module-transforms": "^7.28.3",
+ "@babel/helpers": "^7.28.4",
+ "@babel/parser": "^7.28.4",
+ "@babel/template": "^7.27.2",
+ "@babel/traverse": "^7.28.4",
+ "@babel/types": "^7.28.4",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.28.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.28.3",
+ "@babel/types": "^7.28.2",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.27.2",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.27.2",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.28.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "@babel/traverse": "^7.28.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.28.4",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.28.4",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.4"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.27.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.28.4",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.27.2",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/parser": "^7.27.2",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.28.4",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.3",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.4",
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.4",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.28.4",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.25.10",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@floating-ui/core": {
+ "version": "1.7.3",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.7.4",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/core": "^1.7.3",
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/react": {
+ "version": "0.27.16",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.1.6",
+ "@floating-ui/utils": "^0.2.10",
+ "tabbable": "^6.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=17.0.0",
+ "react-dom": ">=17.0.0"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.1.6",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "^1.7.4"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.10",
+ "license": "MIT"
+ },
+ "node_modules/@internationalized/date": {
+ "version": "3.9.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ }
+ },
+ "node_modules/@internationalized/number": {
+ "version": "3.6.5",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@lexical/clipboard": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/clipboard/-/clipboard-0.36.1.tgz",
+ "integrity": "sha512-qwOereYfHm1MgLu4Kq+nTsHwCoHtZE/PEMrs5k3lbsNk4SEZ8MLHI/Bx9TYijh24MnJhIoWdMLdAmhIaVs/IHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/html": "0.36.1",
+ "@lexical/list": "0.36.1",
+ "@lexical/selection": "0.36.1",
+ "@lexical/utils": "0.36.1",
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/code": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/code/-/code-0.36.1.tgz",
+ "integrity": "sha512-lybXf03xLGtzjYK5Wvpp8ZEdddbYzdnIE74+qXVVuN96XbpSHKkYqVkyIz1fAatEdrpdNXfqO8dZOyUS216wiA==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/utils": "0.36.1",
+ "lexical": "0.36.1",
+ "prismjs": "^1.30.0"
+ }
+ },
+ "node_modules/@lexical/devtools-core": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/devtools-core/-/devtools-core-0.36.1.tgz",
+ "integrity": "sha512-SRbYta2DZKZH+gCc0MaeqR/XLfbydbfMjwn7+XIUUTUE2BZEtYhKqN58kA9N50tJZF4jcHp7MzBIddCfQJqlOg==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/html": "0.36.1",
+ "@lexical/link": "0.36.1",
+ "@lexical/mark": "0.36.1",
+ "@lexical/table": "0.36.1",
+ "@lexical/utils": "0.36.1",
+ "lexical": "0.36.1"
+ },
+ "peerDependencies": {
+ "react": ">=17.x",
+ "react-dom": ">=17.x"
+ }
+ },
+ "node_modules/@lexical/dragon": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/dragon/-/dragon-0.36.1.tgz",
+ "integrity": "sha512-XIG/GnAMPQJXB+HFfHE2H+3pCeXumbL+7WcNWG18U8v4K9Zosd815ub4Cy9QR6VqWqILP9prCi+RhCrdY3RY2Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/extension": "0.36.1",
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/extension": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/extension/-/extension-0.36.1.tgz",
+ "integrity": "sha512-8QBYPda+tFpSkXZ6DFHk01gpqbri0Q8UvuivJfHsSBso6OVzub9q/7xg+0b7bezY9mjajAK8b5rqIQvhAsSlTg==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/utils": "0.36.1",
+ "@preact/signals-core": "^1.11.0",
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/hashtag": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/hashtag/-/hashtag-0.36.1.tgz",
+ "integrity": "sha512-Qr4WOVGSK/N5X2HQNTZsEI1p2O9S4RfFzeYJpMQJmvbmQlRg5qE5GZrtqH8VgaiD8Hp4ztYfCOUDCmu9gdw+AQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/text": "0.36.1",
+ "@lexical/utils": "0.36.1",
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/history": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/history/-/history-0.36.1.tgz",
+ "integrity": "sha512-3gUCS4tvhmRPkR5CLosIrLNmKIycOBFnHdek7e1Hpwh8dKPqMF2/NIBKS202ikSwnA/5mD2m6wbELmHBEdtXkg==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/extension": "0.36.1",
+ "@lexical/utils": "0.36.1",
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/html": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/html/-/html-0.36.1.tgz",
+ "integrity": "sha512-Uk83ot7033YRJmrnERgqg7Z0wT2T2VtCTcBYTdagLq3PGrka6B8eCBpj2ALmwAANU40Cy3JyL+p83m4bldObYA==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/selection": "0.36.1",
+ "@lexical/utils": "0.36.1",
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/link": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/link/-/link-0.36.1.tgz",
+ "integrity": "sha512-l9C4Vcm05eYeBk31oCmJBX4HX7mUSYrXW0v/5FNNabkoyA7m0HLYX7pR9truTl3E2IuWjHmeszkLMd0wKjVxyw==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/extension": "0.36.1",
+ "@lexical/utils": "0.36.1",
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/list": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/list/-/list-0.36.1.tgz",
+ "integrity": "sha512-7/9dxrAZyCU7CpEUhOxRIDjaYIjKVt4KJrZrd2BsgQKhruSH3pdB62kyObRVXMeq1ZJiOz+u43/1DUVHTqZJrw==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/extension": "0.36.1",
+ "@lexical/selection": "0.36.1",
+ "@lexical/utils": "0.36.1",
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/mark": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/mark/-/mark-0.36.1.tgz",
+ "integrity": "sha512-PwwuNU1KvXtAmgFECUOdt9GYj6ncUs4TbmsjHHjVnBEGFJBITm7vJq7uGf89vDRgA5Bhb5iaVV2uK4pnk9c7VA==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/utils": "0.36.1",
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/markdown": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/markdown/-/markdown-0.36.1.tgz",
+ "integrity": "sha512-Ue63kqdiUaWskICh50k3Da/4eANP7pJkKvnkw+qdyhIEMHR45w41ktnqfQViQQttOymBNEk6opTxbSgWFJu9hQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/code": "0.36.1",
+ "@lexical/link": "0.36.1",
+ "@lexical/list": "0.36.1",
+ "@lexical/rich-text": "0.36.1",
+ "@lexical/text": "0.36.1",
+ "@lexical/utils": "0.36.1",
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/offset": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/offset/-/offset-0.36.1.tgz",
+ "integrity": "sha512-4WZVcrME5+GGV7KenJCD1AavJZjKHBAiMUe6yuxOUr5z59V1MEp9Uthol+qeY/WV2/LWZPugrRaONrlFB+FfCg==",
+ "license": "MIT",
+ "dependencies": {
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/overflow": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/overflow/-/overflow-0.36.1.tgz",
+ "integrity": "sha512-Brc3sHPMbH742HzojpJ8DXoEaZEBA3f66Opp4sUhb+B3jIPMgcqxkmP8fDjNrTMBXuWQgjrrgWXZudTHQdjwug==",
+ "license": "MIT",
+ "dependencies": {
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/plain-text": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/plain-text/-/plain-text-0.36.1.tgz",
+ "integrity": "sha512-lCrVQOQ5+ZMff7+9f7B2TIYbkbkZAKbcA/J9HAoVAXh0eN5XKh1SIDWJvoWjAJK9v/xs2pbfS2YCczOEQOFuaA==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/clipboard": "0.36.1",
+ "@lexical/dragon": "0.36.1",
+ "@lexical/selection": "0.36.1",
+ "@lexical/utils": "0.36.1",
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/react": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/react/-/react-0.36.1.tgz",
+ "integrity": "sha512-+vgkGybbfFlgcYJMWp7tRjbWlsdbiOILJfj+VUpCgoqOEX7ouheIflaXwiNF16LPJAwSKiTfkXrRWhWHrF8fVA==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react": "^0.27.16",
+ "@lexical/devtools-core": "0.36.1",
+ "@lexical/dragon": "0.36.1",
+ "@lexical/extension": "0.36.1",
+ "@lexical/hashtag": "0.36.1",
+ "@lexical/history": "0.36.1",
+ "@lexical/link": "0.36.1",
+ "@lexical/list": "0.36.1",
+ "@lexical/mark": "0.36.1",
+ "@lexical/markdown": "0.36.1",
+ "@lexical/overflow": "0.36.1",
+ "@lexical/plain-text": "0.36.1",
+ "@lexical/rich-text": "0.36.1",
+ "@lexical/table": "0.36.1",
+ "@lexical/text": "0.36.1",
+ "@lexical/utils": "0.36.1",
+ "@lexical/yjs": "0.36.1",
+ "lexical": "0.36.1",
+ "react-error-boundary": "^6.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=17.x",
+ "react-dom": ">=17.x"
+ }
+ },
+ "node_modules/@lexical/rich-text": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/rich-text/-/rich-text-0.36.1.tgz",
+ "integrity": "sha512-XBTGecp60S0RdoHRYpEpwAoJFlXbd1Y4DSHdCCx2hzOIgMdlq/PE4RXXTPvqNWE7uIXFLNMkVFdlpdhcQSg8Eg==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/clipboard": "0.36.1",
+ "@lexical/dragon": "0.36.1",
+ "@lexical/selection": "0.36.1",
+ "@lexical/utils": "0.36.1",
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/selection": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/selection/-/selection-0.36.1.tgz",
+ "integrity": "sha512-wIZJsTneNhmB61BiOb0y6scgrS4GOiGUVoBQCpP++xfesh0Vife8Zq0oc7NaD0l0E6tvFW3CjMd8ITZ66Zg78A==",
+ "license": "MIT",
+ "dependencies": {
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/table": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/table/-/table-0.36.1.tgz",
+ "integrity": "sha512-7+wP0249pk+TnbzhX459Txu0JA66PXQK7zGJJLBS1f6JXycYba0hfaBhGCsTKQMOXkgCSMkVyhA2pkbRrUP+Hg==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/clipboard": "0.36.1",
+ "@lexical/extension": "0.36.1",
+ "@lexical/utils": "0.36.1",
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/text": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/text/-/text-0.36.1.tgz",
+ "integrity": "sha512-XboXh15srB1eHJ30x1D7sRH5NlW2GKWER8BpoLGJK9Q5j1QoS6gpL4EAEw6ID8NXgJhplKLtTYX/92JRDOSASg==",
+ "license": "MIT",
+ "dependencies": {
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/utils": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/utils/-/utils-0.36.1.tgz",
+ "integrity": "sha512-Uv3Mr4cFktJKEcMb8NLMo1mhYzcpOkwu2oGEhsFeYgSnWSb1BrVYsDp2yfkWfI8gZzqXH1v9s82NW2Skg42RPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/list": "0.36.1",
+ "@lexical/selection": "0.36.1",
+ "@lexical/table": "0.36.1",
+ "lexical": "0.36.1"
+ }
+ },
+ "node_modules/@lexical/yjs": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@lexical/yjs/-/yjs-0.36.1.tgz",
+ "integrity": "sha512-qBqIN/WJHmU739zjH/IczBMpzJ8u2uXvrPpG1bbH2zqnY3kd6nL96NHL96P9cTlE+u4XWgHugVxnki3yjnUNMg==",
+ "license": "MIT",
+ "dependencies": {
+ "@lexical/offset": "0.36.1",
+ "@lexical/selection": "0.36.1",
+ "lexical": "0.36.1"
+ },
+ "peerDependencies": {
+ "yjs": ">=13.5.22"
+ }
+ },
+ "node_modules/@preact/signals-core": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.12.1.tgz",
+ "integrity": "sha512-BwbTXpj+9QutoZLQvbttRg5x3l5468qaV2kufh+51yha1c53ep5dY4kTuZR35+3pAZxpfQerGJiQqg34ZNZ6uA==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/preact"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-beta.35",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.52.0",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@shikijs/core": {
+ "version": "3.13.0",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.13.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4",
+ "hast-util-to-html": "^9.0.5"
+ }
+ },
+ "node_modules/@shikijs/engine-javascript": {
+ "version": "3.13.0",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.13.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "oniguruma-to-es": "^4.3.3"
+ }
+ },
+ "node_modules/@shikijs/engine-oniguruma": {
+ "version": "3.13.0",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.13.0",
+ "@shikijs/vscode-textmate": "^10.0.2"
+ }
+ },
+ "node_modules/@shikijs/langs": {
+ "version": "3.13.0",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.13.0"
+ }
+ },
+ "node_modules/@shikijs/themes": {
+ "version": "3.13.0",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.13.0"
+ }
+ },
+ "node_modules/@shikijs/types": {
+ "version": "3.13.0",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
+ "node_modules/@shikijs/vscode-textmate": {
+ "version": "10.0.2",
+ "license": "MIT"
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.17",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/hast": {
+ "version": "3.0.4",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/mdast": {
+ "version": "4.0.4",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/react": {
+ "version": "19.1.13",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "19.1.9",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^19.0.0"
+ }
+ },
+ "node_modules/@types/unist": {
+ "version": "3.0.3",
+ "license": "MIT"
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.3.0",
+ "license": "ISC"
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "5.0.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.28.4",
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+ "@rolldown/pluginutils": "1.0.0-beta.35",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.17.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
+ }
+ },
+ "node_modules/@zag-js/accordion": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/anatomy": {
+ "version": "1.24.1",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/angle-slider": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/rect-utils": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/aria-hidden": {
+ "version": "1.24.1",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/async-list": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/core": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/auto-resize": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/avatar": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/carousel": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/scroll-snap": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/checkbox": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/focus-visible": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/clipboard": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/collapsible": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/collection": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/color-picker": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/color-utils": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dismissable": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/popper": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/color-utils": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/combobox": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/aria-hidden": "1.24.1",
+ "@zag-js/collection": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dismissable": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/popper": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/core": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/date-picker": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/date-utils": "1.24.1",
+ "@zag-js/dismissable": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/live-region": "1.24.1",
+ "@zag-js/popper": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ },
+ "peerDependencies": {
+ "@internationalized/date": ">=3.0.0"
+ }
+ },
+ "node_modules/@zag-js/date-utils": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "peerDependencies": {
+ "@internationalized/date": ">=3.0.0"
+ }
+ },
+ "node_modules/@zag-js/dialog": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/aria-hidden": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dismissable": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/focus-trap": "1.24.1",
+ "@zag-js/remove-scroll": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/dismissable": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/interact-outside": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/dom-query": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/editable": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/interact-outside": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/file-upload": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/file-utils": "1.24.1",
+ "@zag-js/i18n-utils": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/file-utils": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/i18n-utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/floating-panel": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/popper": "1.24.1",
+ "@zag-js/rect-utils": "1.24.1",
+ "@zag-js/store": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/focus-trap": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/focus-visible": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/highlight-word": {
+ "version": "1.24.1",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/hover-card": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dismissable": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/popper": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/i18n-utils": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/interact-outside": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/json-tree-utils": {
+ "version": "1.24.1",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/listbox": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/collection": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/focus-visible": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/live-region": {
+ "version": "1.24.1",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/menu": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dismissable": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/popper": "1.24.1",
+ "@zag-js/rect-utils": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/number-input": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@internationalized/number": "3.6.5",
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/pagination": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/password-input": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/pin-input": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/popover": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/aria-hidden": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dismissable": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/focus-trap": "1.24.1",
+ "@zag-js/popper": "1.24.1",
+ "@zag-js/remove-scroll": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/popper": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "1.7.4",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/presence": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/progress": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/qr-code": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1",
+ "proxy-memoize": "3.0.1",
+ "uqr": "0.1.2"
+ }
+ },
+ "node_modules/@zag-js/radio-group": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/focus-visible": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/rating-group": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/react": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/core": "1.24.1",
+ "@zag-js/store": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ },
+ "peerDependencies": {
+ "react": ">=18.0.0",
+ "react-dom": ">=18.0.0"
+ }
+ },
+ "node_modules/@zag-js/rect-utils": {
+ "version": "1.24.1",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/remove-scroll": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/scroll-area": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/scroll-snap": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/select": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/collection": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dismissable": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/popper": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/signature-pad": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1",
+ "perfect-freehand": "^1.2.2"
+ }
+ },
+ "node_modules/@zag-js/slider": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/splitter": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/steps": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/store": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "proxy-compare": "3.0.1"
+ }
+ },
+ "node_modules/@zag-js/switch": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/focus-visible": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/tabs": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/tags-input": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/auto-resize": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/interact-outside": "1.24.1",
+ "@zag-js/live-region": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/timer": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/toast": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dismissable": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/toggle": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/toggle-group": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/tooltip": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/focus-visible": "1.24.1",
+ "@zag-js/popper": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/tour": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dismissable": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/focus-trap": "1.24.1",
+ "@zag-js/interact-outside": "1.24.1",
+ "@zag-js/popper": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/tree-view": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.24.1",
+ "@zag-js/collection": "1.24.1",
+ "@zag-js/core": "1.24.1",
+ "@zag-js/dom-query": "1.24.1",
+ "@zag-js/types": "1.24.1",
+ "@zag-js/utils": "1.24.1"
+ }
+ },
+ "node_modules/@zag-js/types": {
+ "version": "1.24.1",
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "3.1.3"
+ }
+ },
+ "node_modules/@zag-js/utils": {
+ "version": "1.24.1",
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.8.6",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.26.2",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.8.3",
+ "caniuse-lite": "^1.0.30001741",
+ "electron-to-chromium": "^1.5.218",
+ "node-releases": "^2.0.21",
+ "update-browserslist-db": "^1.1.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001743",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/ccount": {
+ "version": "2.0.1",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-html4": {
+ "version": "2.1.0",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "3.0.0",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/comma-separated-tokens": {
+ "version": "2.0.3",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cross-env": {
+ "version": "7.0.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.1"
+ },
+ "bin": {
+ "cross-env": "src/bin/cross-env.js",
+ "cross-env-shell": "src/bin/cross-env-shell.js"
+ },
+ "engines": {
+ "node": ">=10.14",
+ "npm": ">=6",
+ "yarn": ">=1"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/devlop": {
+ "version": "1.1.0",
+ "license": "MIT",
+ "dependencies": {
+ "dequal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.222",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/esbuild": {
+ "version": "0.25.10",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.10",
+ "@esbuild/android-arm": "0.25.10",
+ "@esbuild/android-arm64": "0.25.10",
+ "@esbuild/android-x64": "0.25.10",
+ "@esbuild/darwin-arm64": "0.25.10",
+ "@esbuild/darwin-x64": "0.25.10",
+ "@esbuild/freebsd-arm64": "0.25.10",
+ "@esbuild/freebsd-x64": "0.25.10",
+ "@esbuild/linux-arm": "0.25.10",
+ "@esbuild/linux-arm64": "0.25.10",
+ "@esbuild/linux-ia32": "0.25.10",
+ "@esbuild/linux-loong64": "0.25.10",
+ "@esbuild/linux-mips64el": "0.25.10",
+ "@esbuild/linux-ppc64": "0.25.10",
+ "@esbuild/linux-riscv64": "0.25.10",
+ "@esbuild/linux-s390x": "0.25.10",
+ "@esbuild/linux-x64": "0.25.10",
+ "@esbuild/netbsd-arm64": "0.25.10",
+ "@esbuild/netbsd-x64": "0.25.10",
+ "@esbuild/openbsd-arm64": "0.25.10",
+ "@esbuild/openbsd-x64": "0.25.10",
+ "@esbuild/openharmony-arm64": "0.25.10",
+ "@esbuild/sunos-x64": "0.25.10",
+ "@esbuild/win32-arm64": "0.25.10",
+ "@esbuild/win32-ia32": "0.25.10",
+ "@esbuild/win32-x64": "0.25.10"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/hast-util-to-html": {
+ "version": "9.0.5",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "ccount": "^2.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "html-void-elements": "^3.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "stringify-entities": "^4.0.0",
+ "zwitch": "^2.0.4"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-whitespace": {
+ "version": "3.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/html-void-elements": {
+ "version": "3.0.0",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/inline-style-parser": {
+ "version": "0.2.4",
+ "license": "MIT"
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/lexical": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/lexical/-/lexical-0.36.1.tgz",
+ "integrity": "sha512-VD/rxRp40IvaKGgD+AfWAEPzovm7RTEp++j0P96iaBgiUAq8tDdW3GvPwA5pLk83aQZ5IV10jzEIvzAJkLw+pA==",
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/lucide-react": {
+ "version": "0.503.0",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/mdast-util-to-hast": {
+ "version": "13.2.0",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "@ungap/structured-clone": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "trim-lines": "^3.0.0",
+ "unist-util-position": "^5.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-util-character": {
+ "version": "2.1.1",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-encode": {
+ "version": "2.0.1",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-sanitize-uri": {
+ "version": "2.0.1",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-encode": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-symbol": {
+ "version": "2.0.1",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-types": {
+ "version": "2.0.2",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.21",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/oniguruma-parser": {
+ "version": "0.12.1",
+ "license": "MIT"
+ },
+ "node_modules/oniguruma-to-es": {
+ "version": "4.3.3",
+ "license": "MIT",
+ "dependencies": {
+ "oniguruma-parser": "^0.12.1",
+ "regex": "^6.0.1",
+ "regex-recursion": "^6.0.2"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/perfect-freehand": {
+ "version": "1.2.2",
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.3",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.6",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.6.2",
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prismjs": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
+ "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/property-information": {
+ "version": "7.1.0",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/proxy-compare": {
+ "version": "3.0.1",
+ "license": "MIT"
+ },
+ "node_modules/proxy-memoize": {
+ "version": "3.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "proxy-compare": "^3.0.0"
+ }
+ },
+ "node_modules/react": {
+ "version": "19.1.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "19.1.1",
+ "license": "MIT",
+ "dependencies": {
+ "scheduler": "^0.26.0"
+ },
+ "peerDependencies": {
+ "react": "^19.1.1"
+ }
+ },
+ "node_modules/react-error-boundary": {
+ "version": "6.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5"
+ },
+ "peerDependencies": {
+ "react": ">=16.13.1"
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.17.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/regex": {
+ "version": "6.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-recursion": {
+ "version": "6.0.2",
+ "license": "MIT",
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-utilities": {
+ "version": "2.3.0",
+ "license": "MIT"
+ },
+ "node_modules/rollup": {
+ "version": "4.52.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.8"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.52.0",
+ "@rollup/rollup-android-arm64": "4.52.0",
+ "@rollup/rollup-darwin-arm64": "4.52.0",
+ "@rollup/rollup-darwin-x64": "4.52.0",
+ "@rollup/rollup-freebsd-arm64": "4.52.0",
+ "@rollup/rollup-freebsd-x64": "4.52.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.52.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.52.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.52.0",
+ "@rollup/rollup-linux-arm64-musl": "4.52.0",
+ "@rollup/rollup-linux-loong64-gnu": "4.52.0",
+ "@rollup/rollup-linux-ppc64-gnu": "4.52.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.52.0",
+ "@rollup/rollup-linux-riscv64-musl": "4.52.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.52.0",
+ "@rollup/rollup-linux-x64-gnu": "4.52.0",
+ "@rollup/rollup-linux-x64-musl": "4.52.0",
+ "@rollup/rollup-openharmony-arm64": "4.52.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.52.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.52.0",
+ "@rollup/rollup-win32-x64-gnu": "4.52.0",
+ "@rollup/rollup-win32-x64-msvc": "4.52.0",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.26.0",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shiki": {
+ "version": "3.13.0",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/core": "3.13.0",
+ "@shikijs/engine-javascript": "3.13.0",
+ "@shikijs/engine-oniguruma": "3.13.0",
+ "@shikijs/langs": "3.13.0",
+ "@shikijs/themes": "3.13.0",
+ "@shikijs/types": "3.13.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/space-separated-tokens": {
+ "version": "2.0.2",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/stringify-entities": {
+ "version": "4.0.4",
+ "license": "MIT",
+ "dependencies": {
+ "character-entities-html4": "^2.0.0",
+ "character-entities-legacy": "^3.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/tabbable": {
+ "version": "6.2.0",
+ "license": "MIT"
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.15",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/trim-lines": {
+ "version": "3.0.1",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "license": "0BSD"
+ },
+ "node_modules/typescript": {
+ "version": "5.9.2",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/unist-util-is": {
+ "version": "6.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position": {
+ "version": "5.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-stringify-position": {
+ "version": "4.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit": {
+ "version": "5.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents": {
+ "version": "6.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.3",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uqr": {
+ "version": "0.1.2",
+ "license": "MIT"
+ },
+ "node_modules/vfile": {
+ "version": "6.0.3",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-message": {
+ "version": "4.0.3",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-stringify-position": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vite": {
+ "version": "7.1.6",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.25.0",
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3",
+ "postcss": "^8.5.6",
+ "rollup": "^4.43.0",
+ "tinyglobby": "^0.2.15"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "lightningcss": "^1.21.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/zwitch": {
+ "version": "2.0.4",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ }
+ }
+}
diff --git a/examples/dev-node-state-style/package.json b/examples/dev-node-state-style/package.json
new file mode 100644
index 00000000000..702774c0b29
--- /dev/null
+++ b/examples/dev-node-state-style/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "@lexical/dev-node-state-style-example",
+ "private": true,
+ "version": "0.37.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite -c vite.config.monorepo.ts",
+ "monorepo:dev": "vite -c vite.config.monorepo.ts",
+ "build": "tsc && vite build -c vite.config.monorepo.ts",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@ark-ui/react": "^5.6.0",
+ "@lexical/clipboard": "0.37.0",
+ "@lexical/extension": "0.37.0",
+ "@lexical/history": "0.37.0",
+ "@lexical/html": "0.37.0",
+ "@lexical/react": "0.37.0",
+ "@lexical/rich-text": "0.37.0",
+ "@lexical/selection": "0.37.0",
+ "@lexical/utils": "0.37.0",
+ "@shikijs/langs": "^3.3.0",
+ "@shikijs/themes": "^3.3.0",
+ "inline-style-parser": "^0.2.4",
+ "lexical": "0.37.0",
+ "lucide-react": "^0.503.0",
+ "prettier": "^3.5.3",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0",
+ "shiki": "^3.3.0"
+ },
+ "devDependencies": {
+ "@types/react": "^19.1.2",
+ "@types/react-dom": "^19.1.2",
+ "@vitejs/plugin-react": "^5.0.2",
+ "cross-env": "^7.0.3",
+ "csstype": "^3.1.3",
+ "typescript": "^5.9.2",
+ "vite": "^7.1.4"
+ }
+}
diff --git a/examples/dev-node-state-style/src/App.tsx b/examples/dev-node-state-style/src/App.tsx
new file mode 100644
index 00000000000..16fb6777edf
--- /dev/null
+++ b/examples/dev-node-state-style/src/App.tsx
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+
+import {Tabs} from '@ark-ui/react/tabs';
+import {AutoFocusExtension} from '@lexical/extension';
+import {HistoryExtension} from '@lexical/history';
+import {ContentEditable} from '@lexical/react/LexicalContentEditable';
+import {LexicalExtensionComposer} from '@lexical/react/LexicalExtensionComposer';
+import {RichTextExtension} from '@lexical/rich-text';
+import {defineExtension, ParagraphNode, TextNode} from 'lexical';
+
+import ExampleTheme from './ExampleTheme';
+import {ShikiViewPlugin} from './plugins/ShikiViewPlugin';
+import {StyleViewPlugin} from './plugins/StyleViewPlugin';
+import {ToolbarPlugin} from './plugins/ToolbarPlugin';
+import {StyleStateExtension} from './styleState';
+
+const placeholder = 'Enter some rich text...';
+
+const editorExtension = defineExtension({
+ dependencies: [
+ RichTextExtension,
+ HistoryExtension,
+ AutoFocusExtension,
+ StyleStateExtension,
+ ],
+ name: '@lexical/examples/node-state-style',
+ namespace: 'NodeState Demo',
+ nodes: [ParagraphNode, TextNode],
+ onError(error: Error) {
+ throw error;
+ },
+ theme: ExampleTheme,
+});
+
+export default function App() {
+ return (
+
+
+
+
+ {placeholder}
+ }
+ />
+
+
+
+
+ Style Tree
+ HTML
+ JSON
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/examples/dev-node-state-style/src/ExampleTheme.ts b/examples/dev-node-state-style/src/ExampleTheme.ts
new file mode 100644
index 00000000000..234afe01563
--- /dev/null
+++ b/examples/dev-node-state-style/src/ExampleTheme.ts
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+
+export default {
+ code: 'editor-code',
+ heading: {
+ h1: 'editor-heading-h1',
+ h2: 'editor-heading-h2',
+ h3: 'editor-heading-h3',
+ h4: 'editor-heading-h4',
+ h5: 'editor-heading-h5',
+ },
+ image: 'editor-image',
+ link: 'editor-link',
+ list: {
+ listitem: 'editor-listitem',
+ nested: {
+ listitem: 'editor-nested-listitem',
+ },
+ ol: 'editor-list-ol',
+ ul: 'editor-list-ul',
+ },
+ paragraph: 'editor-paragraph',
+ placeholder: 'editor-placeholder',
+ quote: 'editor-quote',
+ text: {
+ bold: 'editor-text-bold',
+ code: 'editor-text-code',
+ hashtag: 'editor-text-hashtag',
+ italic: 'editor-text-italic',
+ overflowed: 'editor-text-overflowed',
+ strikethrough: 'editor-text-strikethrough',
+ underline: 'editor-text-underline',
+ underlineStrikethrough: 'editor-text-underlineStrikethrough',
+ },
+};
diff --git a/examples/dev-node-state-style/src/icons/LICENSE.md b/examples/dev-node-state-style/src/icons/LICENSE.md
new file mode 100644
index 00000000000..ce74f6abeed
--- /dev/null
+++ b/examples/dev-node-state-style/src/icons/LICENSE.md
@@ -0,0 +1,5 @@
+Bootstrap Icons
+https://icons.getbootstrap.com
+
+Licensed under MIT license
+https://github.com/twbs/icons/blob/main/LICENSE.md
diff --git a/examples/dev-node-state-style/src/icons/arrow-clockwise.svg b/examples/dev-node-state-style/src/icons/arrow-clockwise.svg
new file mode 100644
index 00000000000..b072eb097ab
--- /dev/null
+++ b/examples/dev-node-state-style/src/icons/arrow-clockwise.svg
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/examples/dev-node-state-style/src/icons/arrow-counterclockwise.svg b/examples/dev-node-state-style/src/icons/arrow-counterclockwise.svg
new file mode 100644
index 00000000000..b0b23b9bbc4
--- /dev/null
+++ b/examples/dev-node-state-style/src/icons/arrow-counterclockwise.svg
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/examples/dev-node-state-style/src/icons/text-paragraph.svg b/examples/dev-node-state-style/src/icons/text-paragraph.svg
new file mode 100644
index 00000000000..9779beabf1c
--- /dev/null
+++ b/examples/dev-node-state-style/src/icons/text-paragraph.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/examples/dev-node-state-style/src/icons/type-bold.svg b/examples/dev-node-state-style/src/icons/type-bold.svg
new file mode 100644
index 00000000000..276d133c25c
--- /dev/null
+++ b/examples/dev-node-state-style/src/icons/type-bold.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/examples/dev-node-state-style/src/icons/type-italic.svg b/examples/dev-node-state-style/src/icons/type-italic.svg
new file mode 100644
index 00000000000..3ac6b09f02a
--- /dev/null
+++ b/examples/dev-node-state-style/src/icons/type-italic.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/examples/dev-node-state-style/src/icons/type-strikethrough.svg b/examples/dev-node-state-style/src/icons/type-strikethrough.svg
new file mode 100644
index 00000000000..1c940e42a87
--- /dev/null
+++ b/examples/dev-node-state-style/src/icons/type-strikethrough.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/examples/dev-node-state-style/src/icons/type-underline.svg b/examples/dev-node-state-style/src/icons/type-underline.svg
new file mode 100644
index 00000000000..c299b8bf2f0
--- /dev/null
+++ b/examples/dev-node-state-style/src/icons/type-underline.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/examples/dev-node-state-style/src/main.tsx b/examples/dev-node-state-style/src/main.tsx
new file mode 100644
index 00000000000..efedcf1fced
--- /dev/null
+++ b/examples/dev-node-state-style/src/main.tsx
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import './styles.css';
+
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+
+import App from './App.tsx';
+
+ReactDOM.createRoot(document.getElementById('root')!).render(
+
+
+
NodeState Style Example
+
+
+ ,
+);
diff --git a/examples/dev-node-state-style/src/plugins/ShikiViewPlugin.css b/examples/dev-node-state-style/src/plugins/ShikiViewPlugin.css
new file mode 100644
index 00000000000..c2f75f2d89a
--- /dev/null
+++ b/examples/dev-node-state-style/src/plugins/ShikiViewPlugin.css
@@ -0,0 +1,5 @@
+.shiki-view-plugin > pre.shiki {
+ margin: 0;
+ padding: 10px;
+ white-space: pre-wrap;
+}
diff --git a/examples/dev-node-state-style/src/plugins/ShikiViewPlugin.tsx b/examples/dev-node-state-style/src/plugins/ShikiViewPlugin.tsx
new file mode 100644
index 00000000000..d7b30435e4f
--- /dev/null
+++ b/examples/dev-node-state-style/src/plugins/ShikiViewPlugin.tsx
@@ -0,0 +1,92 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import './ShikiViewPlugin.css';
+
+import {$generateHtmlFromNodes} from '@lexical/html';
+import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
+import {EditorState, LexicalEditor} from 'lexical';
+import * as prettier from 'prettier';
+import {useEffect, useMemo, useState} from 'react';
+import {createHighlighterCore} from 'shiki/core';
+import {createJavaScriptRegexEngine} from 'shiki/engine/javascript';
+
+const jsEngine = createJavaScriptRegexEngine({target: 'ES2024'});
+
+const shikiPromise = createHighlighterCore({
+ engine: jsEngine,
+ langs: [import('@shikijs/langs/html'), import('@shikijs/langs/json')],
+ themes: [import('@shikijs/themes/nord')],
+});
+const prettierPlugins = [
+ import('prettier/plugins/babel'),
+ import('prettier/plugins/estree'),
+ import('prettier/plugins/html'),
+];
+
+function editorHTML(editor: LexicalEditor, editorState: EditorState): string {
+ return editorState.read(() => $generateHtmlFromNodes(editor, null), {editor});
+}
+
+function editorJSON(_editor: LexicalEditor, editorState: EditorState): string {
+ return JSON.stringify(editorState.toJSON(), null, 2);
+}
+
+const langs = {
+ html: editorHTML,
+ json: editorJSON,
+} as const;
+
+export interface ShikiViewPluginProps {
+ lang: keyof typeof langs;
+}
+
+export function ShikiViewPlugin({lang}: ShikiViewPluginProps) {
+ const [editor] = useLexicalComposerContext();
+ const [editorState, setEditorState] = useState(() => editor.getEditorState());
+ useEffect(
+ () =>
+ editor.registerUpdateListener((payload) =>
+ setEditorState(payload.editorState),
+ ),
+ [editor],
+ );
+ const rawCode = useMemo(
+ () => langs[lang](editor, editorState),
+ [lang, editor, editorState],
+ );
+ const htmlPromise = useMemo(
+ () =>
+ (async () => {
+ const prettified = await prettier.format(rawCode, {
+ parser: lang,
+ plugins: (await Promise.all(prettierPlugins)).map(
+ (mod) => mod.default,
+ ),
+ });
+ return (await shikiPromise).codeToHtml(prettified, {
+ lang,
+ theme: 'nord',
+ });
+ })(),
+ [lang, rawCode],
+ );
+ const [html, setHtml] = useState('');
+ useEffect(() => {
+ let canceled = false;
+ htmlPromise.then((formatted) => canceled || setHtml(formatted));
+ return () => {
+ canceled = true;
+ };
+ }, [htmlPromise]);
+ return (
+
+ );
+}
diff --git a/examples/dev-node-state-style/src/plugins/StyleViewPlugin.css b/examples/dev-node-state-style/src/plugins/StyleViewPlugin.css
new file mode 100644
index 00000000000..8db74fd35f8
--- /dev/null
+++ b/examples/dev-node-state-style/src/plugins/StyleViewPlugin.css
@@ -0,0 +1,205 @@
+/* tree-view */
+[data-scope='tree-view'][data-part='tree'] {
+ width: 240px;
+}
+
+[data-scope='tree-view'][data-part='item'],
+[data-scope='tree-view'][data-part='branch-control'] {
+ user-select: none;
+ --padding-inline: 16px;
+ padding-inline-start: calc(var(--depth) * var(--padding-inline));
+ padding-inline-end: var(--padding-inline);
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ border-radius: 2px;
+
+ & svg {
+ width: 16px;
+ height: 16px;
+ opacity: 0.5;
+ position: relative;
+ top: 3px;
+ }
+
+ &:hover {
+ background: rgb(243, 243, 243);
+ }
+
+ &[data-selected] {
+ background: rgb(226, 226, 226);
+ }
+
+ &:focus {
+ outline: 1px solid rgb(148, 148, 148);
+ outline-offset: -1px;
+ }
+}
+
+[data-scope='tree-view'][data-part='item-text'],
+[data-scope='tree-view'][data-part='branch-text'] {
+ flex: 1;
+}
+
+[data-scope='tree-view'][data-part='branch-content'] {
+ position: relative;
+ isolation: isolate;
+}
+
+[data-scope='tree-view'][data-part='branch-indent-guide'] {
+ position: absolute;
+ content: '';
+ border-left: 1px solid rgb(226, 226, 226);
+ height: 100%;
+ translate: calc(var(--depth) * 1.25rem);
+ z-index: 0;
+}
+
+[data-scope='tree-view'][data-part='branch-indicator'] {
+ display: flex;
+ /* align-items: center; */
+ &[data-state='open'] svg {
+ transform: rotate(90deg);
+ }
+}
+
+@keyframes slideDown {
+ from {
+ opacity: 0.01;
+ height: 0;
+ }
+ to {
+ opacity: 1;
+ height: var(--height);
+ }
+}
+
+@keyframes slideUp {
+ from {
+ opacity: 1;
+ height: var(--height);
+ }
+ to {
+ opacity: 0.01;
+ height: 0;
+ }
+}
+
+[data-scope='tree-view'][data-part='branch-content'] {
+ overflow: hidden;
+ max-width: 400px;
+}
+
+[data-scope='tree-view'][data-part='branch-content'][data-state='open'] {
+ animation: slideDown 250ms cubic-bezier(0, 0, 0.38, 0.9);
+}
+
+[data-scope='tree-view'][data-part='branch-content'][data-state='closed'] {
+ animation: slideUp 200ms cubic-bezier(0, 0, 0.38, 0.9);
+}
+
+/* splitter */
+[data-scope='splitter'][data-part='root'] {
+ gap: 4px;
+}
+
+[data-scope='splitter'][data-part='root'][data-orientation='horizontal'] {
+ min-height: 300px;
+}
+
+[data-scope='splitter'][data-part='root'][data-orientation='vertical'] {
+ min-height: 300px;
+}
+
+[data-scope='splitter'][data-part='panel'] {
+ display: flex;
+ /* align-items: center; */
+ /* justify-content: center; */
+ border: 1px solid lightgray;
+ overflow: auto;
+ padding: 10px;
+}
+
+[data-scope='splitter'][data-part='panel']:has(
+ [data-scope='splitter'][data-part='panel']
+ ) {
+ border: none;
+}
+
+[data-scope='splitter'][data-part='resize-trigger'][data-orientation='vertical'] {
+ min-height: 12px;
+}
+
+.style-view-node-button-delete {
+ padding: 0;
+ display: inline-flex;
+ position: absolute;
+ top: 0.125em;
+ left: 0;
+ border: none;
+}
+.style-view-node-button-delete svg {
+ height: 1em;
+ width: 1em;
+}
+
+.style-view-node-button {
+ cursor: pointer;
+}
+
+.style-view-node-text-contents::before,
+.style-view-node-text-contents::after {
+ content: '"';
+}
+
+.style-view-node-text-contents {
+ max-width: 75ch;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.style-view-text-pane {
+ font-family: monospace;
+}
+
+.style-view-entry {
+ position: relative;
+ padding-left: 4ch;
+ text-indent: -2ch;
+}
+
+.style-view-key {
+ color: #0288d1;
+}
+
+.style-view-style-heading {
+ color: #616161;
+}
+
+.style-view-value,
+.style-view-value > p {
+ display: inline;
+}
+.style-view-value:focus-visible {
+ outline: 1px auto rgba(20, 20, 20, 0.2);
+ outline-offset: 4px;
+}
+
+.style-view-actions {
+ padding-left: 2ch;
+}
+
+[data-scope='combobox'][data-part='item-group'] {
+ padding: 2px;
+}
+[data-scope='combobox'][data-part='content'] {
+ border: 1px solid #000;
+ background-color: #fff;
+}
+[data-scope='combobox'][data-part='item'] {
+ cursor: pointer;
+ padding: 0 0.5rem;
+}
+[data-scope='combobox'][data-part='item'][data-highlighted] {
+ background-color: rgba(0, 0, 0, 0.2);
+}
diff --git a/examples/dev-node-state-style/src/plugins/StyleViewPlugin.tsx b/examples/dev-node-state-style/src/plugins/StyleViewPlugin.tsx
new file mode 100644
index 00000000000..933b5f411f5
--- /dev/null
+++ b/examples/dev-node-state-style/src/plugins/StyleViewPlugin.tsx
@@ -0,0 +1,838 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+
+import './StyleViewPlugin.css';
+
+import {
+ Combobox,
+ createListCollection,
+ useCombobox,
+} from '@ark-ui/react/combobox';
+import {Portal} from '@ark-ui/react/portal';
+import {Splitter, useSplitter} from '@ark-ui/react/splitter';
+import {
+ createTreeCollection,
+ TreeCollection,
+ TreeView,
+ useTreeView,
+ UseTreeViewReturn,
+} from '@ark-ui/react/tree-view';
+import {LexicalComposer} from '@lexical/react/LexicalComposer';
+import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
+import {ContentEditable} from '@lexical/react/LexicalContentEditable';
+import {LexicalErrorBoundary} from '@lexical/react/LexicalErrorBoundary';
+import {PlainTextPlugin} from '@lexical/react/LexicalPlainTextPlugin';
+import {$getAdjacentCaret, mergeRegister} from '@lexical/utils';
+import {type SelectionDetails} from '@zag-js/combobox';
+import {
+ $addUpdateTag,
+ $createLineBreakNode,
+ $createParagraphNode,
+ $createTabNode,
+ $createTextNode,
+ $getCaretRange,
+ $getChildCaret,
+ $getNodeByKey,
+ $getPreviousSelection,
+ $getRoot,
+ $getSelection,
+ $getSiblingCaret,
+ $isDecoratorNode,
+ $isElementNode,
+ $isLineBreakNode,
+ $isParagraphNode,
+ $isRangeSelection,
+ $isRootNode,
+ $isTabNode,
+ $isTextNode,
+ $normalizeCaret,
+ $setSelection,
+ $setSelectionFromCaretRange,
+ BLUR_COMMAND,
+ COMMAND_PRIORITY_LOW,
+ type EditorState,
+ ElementNode,
+ KEY_DOWN_COMMAND,
+ LexicalEditor,
+ LexicalNode,
+ NodeCaret,
+ NodeKey,
+} from 'lexical';
+import {
+ ChevronRightIcon,
+ CircleXIcon,
+ CodeXmlIcon,
+ CornerDownLeftIcon,
+ FolderIcon,
+ FolderRoot,
+ TextIcon,
+} from 'lucide-react';
+import React, {
+ createContext,
+ Fragment,
+ type JSX,
+ KeyboardEventHandler,
+ use,
+ useCallback,
+ useEffect,
+ useMemo,
+ useReducer,
+ useRef,
+ useState,
+} from 'react';
+
+import {
+ $removeStyleProperty,
+ $setStyleProperty,
+ getStyleObjectDirect,
+ StyleObject,
+ styleObjectToArray,
+} from '../styleState';
+
+const SKIP_DOM_SELECTION_TAG = 'skip-dom-selection';
+const SKIP_SCROLL_INTO_VIEW_TAG = 'skip-scroll-into-view';
+
+function $preserveSelection(): void {
+ const selection = $getSelection();
+ if (!selection) {
+ const prevSelection = $getPreviousSelection();
+ if (prevSelection) {
+ $setSelection(prevSelection.clone());
+ }
+ }
+}
+
+const EditorStateContext = createContext(undefined);
+function useEditorState() {
+ const editorState = use(EditorStateContext);
+ if (editorState === undefined) {
+ throw new Error('Missing EditorStateContext');
+ }
+ return editorState;
+}
+
+const NodeTreeViewContext = createContext<
+ undefined | UseTreeViewReturn
+>(undefined);
+function useNodeTreeViewContext() {
+ const ctx = use(NodeTreeViewContext);
+ if (ctx === undefined) {
+ throw new Error('Missing NodeTreeViewContext');
+ }
+ return ctx;
+}
+
+export function StyleViewPlugin(): JSX.Element {
+ const [editor] = useLexicalComposerContext();
+ const [editorState, setEditorState] = useState(() => editor.getEditorState());
+ useEffect(
+ () =>
+ editor.registerUpdateListener(() => {
+ setEditorState(editor.getEditorState());
+ }),
+ [editor],
+ );
+ return (
+
+
+
+ );
+}
+
+function NodeLabel({node}: {node: LexicalNode}) {
+ const [editor] = useLexicalComposerContext();
+ const key = node.getKey();
+ const type = node.getType();
+ const reactLabel = (
+ <>
+ {
+ event.preventDefault();
+ editor.update(() => {
+ const caretRange = $isElementNode(node)
+ ? $getCaretRange(
+ $getChildCaret(node, 'previous').getFlipped(),
+ $getChildCaret(node, 'next'),
+ )
+ : $getCaretRange(
+ $normalizeCaret(
+ $getSiblingCaret(node, 'previous').getFlipped(),
+ ),
+ $normalizeCaret($getSiblingCaret(node, 'next')),
+ );
+ $setSelectionFromCaretRange(caretRange);
+ });
+ }}>
+ ({key})
+ {' '}
+ {type}
+ >
+ );
+ if ($isTextNode(node)) {
+ const text = node.__text;
+ return (
+ <>
+ {reactLabel}{' '}
+
+ {text}
+
+ >
+ );
+ }
+ return reactLabel;
+}
+
+function describeNode(node: LexicalNode): [string, React.ReactNode] {
+ return [`(${node.getKey()}) ${node.getType()}`, ];
+}
+
+function LexicalNodeTreeViewItem(props: TreeView.NodeProviderProps) {
+ const id = props.node;
+ const editorState = useEditorState();
+ const node =
+ typeof id === 'string'
+ ? editorState.read(() => $getNodeByKey(id, editorState))
+ : null;
+ const indexPathString = JSON.stringify(props.indexPath);
+ return useMemo(() => {
+ if (!node) {
+ return null;
+ }
+ const indexPath = JSON.parse(indexPathString);
+ const [_ariaLabel, label] = describeNode(node);
+ const nextNode = node.__next && (
+
+ );
+ const icon = $isRootNode(node) ? (
+
+ ) : $isElementNode(node) ? (
+
+ ) : $isTextNode(node) ? (
+
+ ) : $isDecoratorNode(node) ? (
+
+ ) : $isLineBreakNode(node) ? (
+
+ ) : null;
+ let content: React.ReactNode;
+ if ($isElementNode(node)) {
+ content = (
+
+
+
+ {icon} {label}
+
+
+ {node.__first ? : null}
+
+
+
+
+ {node.__first ? (
+
+ ) : null}
+
+
+ );
+ } else {
+ content = (
+
+
+ {icon} {label}
+
+
+ );
+ }
+ return (
+
+
+ {content}
+
+ {nextNode}
+
+ );
+ }, [id, node, indexPathString]);
+}
+
+function getSelectedNodeKey(
+ api: UseTreeViewReturn,
+): undefined | NodeKey {
+ return api.selectedValue.at(0);
+}
+
+interface SelectedNodeStateAction {
+ panelNodeKey: undefined | NodeKey;
+ editorState: EditorState;
+}
+interface SelectedNodeState extends SelectedNodeStateAction {
+ panelNodeKey: NodeKey;
+ selectionNodeKey: NodeKey | null;
+ panelNode: LexicalNode | null;
+ cached: React.ReactNode;
+}
+interface InitialSelectedNodeState extends SelectedNodeStateAction {
+ selectionNodeKey?: undefined;
+ panelNode?: undefined;
+ cached?: undefined;
+}
+
+interface StyleValueEditorProps {
+ ref?: React.Ref;
+ prop: keyof StyleObject;
+ value: string;
+ onChange: (prop: keyof StyleObject, value: string) => void;
+}
+
+type ParsedChunk = '\n' | '\r\n' | '\t' | string;
+
+function parseRawText(text: string): ParsedChunk[] {
+ return text.split(/(\r?\n|\t)/);
+}
+
+function $patchNodes(
+ parent: T,
+ nodes: LexicalNode[],
+): T {
+ const childrenSize = parent.getChildrenSize();
+ if (
+ childrenSize === nodes.length &&
+ parent.getChildren().every((node, i) => node === nodes[i])
+ ) {
+ // no-op, do not mark as dirty
+ return parent;
+ }
+ return $getChildCaret(parent, 'next').splice(childrenSize, nodes).origin;
+}
+
+function $patchParsedText(
+ parent: T,
+ chunks: readonly ParsedChunk[],
+): T {
+ let caret: null | NodeCaret<'next'> = $getChildCaret(parent, 'next');
+ const nodes: LexicalNode[] = [];
+ for (const chunk of chunks) {
+ caret = $getAdjacentCaret(caret);
+ const node = caret ? caret.origin : null;
+ if (chunk === '\r\n' || chunk === '\n') {
+ nodes.push($isLineBreakNode(node) ? node : $createLineBreakNode());
+ } else if (chunk === '\t') {
+ nodes.push($isTabNode(node) ? node : $createTabNode());
+ } else if (chunk) {
+ nodes.push(
+ $isTextNode(node)
+ ? node.getTextContent() === chunk
+ ? node
+ : node.setTextContent(chunk)
+ : $createTextNode(chunk),
+ );
+ }
+ }
+ return $patchNodes(parent, nodes);
+}
+
+function $patchParsedTextAtRoot(chunks: readonly ParsedChunk[]): void {
+ const root = $getRoot();
+ const firstNode = root.getFirstChild();
+ const p = $isParagraphNode(firstNode) ? firstNode : $createParagraphNode();
+ $getChildCaret(root, 'next').splice(root.getChildrenSize(), [p]);
+ $patchParsedText(p, chunks);
+}
+
+function StyleValuePlugin(props: StyleValueEditorProps) {
+ const [editor] = useLexicalComposerContext();
+ const {prop, onChange, ref} = props;
+ const valueRef = useRef(props.value);
+ useEffect(() => {
+ const setRef =
+ typeof ref === 'function'
+ ? ref
+ : ref
+ ? (value: LexicalEditor | null) => {
+ ref.current = value;
+ }
+ : () => {};
+ setRef(editor);
+ return () => {
+ setRef(null);
+ };
+ }, [editor, ref]);
+ useEffect(() => {
+ valueRef.current = props.value;
+ }, [props.value]);
+ useEffect(() => {
+ let timer: undefined | ReturnType;
+ function clearTimer() {
+ if (timer) {
+ clearTimeout(timer);
+ timer = undefined;
+ }
+ }
+ function handleInput() {
+ clearTimer();
+ setTimeout(handleFlush, 300);
+ }
+ function handleFlush() {
+ clearTimer();
+ const value = editor
+ .getEditorState()
+ .read(() => $getRoot().getTextContent());
+ if (valueRef.current !== value) {
+ onChange(prop, value);
+ }
+ }
+ return mergeRegister(
+ editor.registerUpdateListener((payload) => {
+ if (payload.editorState !== payload.prevEditorState) {
+ handleInput();
+ }
+ }),
+ editor.registerCommand(
+ BLUR_COMMAND,
+ () => {
+ handleFlush();
+ return true;
+ },
+ COMMAND_PRIORITY_LOW,
+ ),
+ editor.registerCommand(
+ KEY_DOWN_COMMAND,
+ (e) => {
+ if (e.key === 'Enter') {
+ e.preventDefault();
+ editor.blur();
+ return true;
+ }
+ return false;
+ },
+ COMMAND_PRIORITY_LOW,
+ ),
+ );
+ }, [editor, prop, onChange]);
+ return (
+
+ }
+ ErrorBoundary={LexicalErrorBoundary}
+ />
+ );
+}
+
+function StyleValueEditor(props: StyleValueEditorProps) {
+ return (
+ {
+ $patchParsedTextAtRoot(parseRawText(props.value));
+ },
+ namespace: 'style-view-value',
+ onError: (err) => {
+ throw err;
+ },
+ }}>
+
+
+ );
+}
+
+function LexicalTextSelectionPaneContents({node}: {node: LexicalNode}) {
+ const [editor] = useLexicalComposerContext();
+ const [registeredNodes] = useState(
+ () => new Map(),
+ );
+ const styles = getStyleObjectDirect(node);
+ const focusPropertyRef = useRef('');
+
+ const nodeRef = useRef(node);
+ useEffect(() => {
+ nodeRef.current = node;
+ }, [node]);
+ const {handleChange, handleAddProperty} = useMemo(() => {
+ // eslint-disable-next-line no-shadow
+ const handleAddProperty = (prop: keyof StyleObject) => {
+ const reg = registeredNodes.get(prop);
+ if (reg) {
+ reg.focus();
+ } else {
+ focusPropertyRef.current = prop;
+ editor.update(
+ () => {
+ $setStyleProperty(nodeRef.current, prop, '');
+ },
+ {tag: [SKIP_DOM_SELECTION_TAG, SKIP_SCROLL_INTO_VIEW_TAG]},
+ );
+ }
+ };
+ // eslint-disable-next-line no-shadow
+ const handleChange = (
+ prop: keyof StyleObject,
+ textContent: string | null,
+ ) => {
+ editor.update(
+ () => {
+ $preserveSelection();
+ $addUpdateTag(SKIP_DOM_SELECTION_TAG);
+ $addUpdateTag(SKIP_SCROLL_INTO_VIEW_TAG);
+ $setStyleProperty(nodeRef.current, prop, textContent || undefined);
+ },
+ {tag: [SKIP_DOM_SELECTION_TAG, SKIP_SCROLL_INTO_VIEW_TAG]},
+ );
+ };
+ return {handleAddProperty, handleChange};
+ }, [editor, registeredNodes]);
+
+ const rows = useMemo(
+ () =>
+ styleObjectToArray(styles).map(([k, v]) => (
+
+ {
+ e.preventDefault();
+ editor.update(
+ () => {
+ $removeStyleProperty(nodeRef.current, k);
+ },
+ {tag: [SKIP_DOM_SELECTION_TAG, SKIP_SCROLL_INTO_VIEW_TAG]},
+ );
+ }}>
+
+
+ {k}:
+ {
+ if (el === null) {
+ registeredNodes.delete(k);
+ return;
+ }
+ if (focusPropertyRef.current === k) {
+ el.focus();
+ focusPropertyRef.current = '';
+ }
+ registeredNodes.set(k, el);
+ }}
+ />
+
+ )),
+ [editor, registeredNodes, styles, handleChange],
+ );
+ return (
+
+
{describeNode(node)[1]}
+
+
+ style {'{'}
+
+ {rows}
+
+
+
+
{'}'}
+
+
+ );
+}
+
+function initTextSelectionPaneReducer(action: SelectedNodeStateAction) {
+ return textSelectionPaneReducer(action, action);
+}
+
+function textSelectionPaneReducer(
+ state: InitialSelectedNodeState | SelectedNodeState,
+ action: SelectedNodeStateAction,
+): SelectedNodeState {
+ return action.editorState.read(() => {
+ const selection = $getSelection();
+ const selectionNodeKey = $isRangeSelection(selection)
+ ? selection.focus.key
+ : null;
+ const {
+ // selectionNodeKey: prevSelectionNodeKey = null,
+ panelNode: prevPanelNode = null,
+ cached: prevCached = null,
+ } = state;
+ let panelNodeKey =
+ selectionNodeKey || action.panelNodeKey || state.panelNodeKey;
+ if (selectionNodeKey) {
+ panelNodeKey = selectionNodeKey;
+ } else if (!panelNodeKey) {
+ panelNodeKey = 'root';
+ }
+ const panelNode = $getNodeByKey(panelNodeKey);
+ if (panelNode === prevPanelNode && state.cached) {
+ return state;
+ }
+ const cached =
+ panelNode === prevPanelNode && prevCached ? (
+ prevCached
+ ) : panelNode === null ? (
+ Node {panelNodeKey} no longer in the document
+ ) : (
+
+ );
+ return {...action, cached, panelNode, panelNodeKey, selectionNodeKey};
+ });
+}
+
+function getSuggestedStyleKeys(): readonly (keyof StyleObject)[] {
+ const keys = new Set();
+ if (typeof document !== 'undefined') {
+ const {style} = document.body;
+ for (const k in style) {
+ if (typeof style[k] === 'string') {
+ const kebab = k
+ .replace(/[A-Z]/g, (s) => '-' + s.toLowerCase())
+ .replace(/^(webkit|moz|ms|o)-/, '-$1-')
+ .replace(/^css-/, '');
+ keys.add(kebab as keyof StyleObject);
+ }
+ }
+ }
+ return [...keys].sort();
+}
+
+function isNotVendorProperty(item: string): boolean {
+ return !item.startsWith('-');
+}
+
+function useSuggestedStylesCombobox(props: CSSPropertyComboBoxProps) {
+ const initialItems = useMemo(getSuggestedStyleKeys, []);
+ const [items, setItems] = useState(() =>
+ initialItems.filter(isNotVendorProperty).join('\n'),
+ );
+ const collection = useMemo(
+ () => createListCollection({items: items.split(/\n/g)}),
+ [items],
+ );
+ const handleInputValueChange = (
+ details: Combobox.InputValueChangeDetails,
+ ) => {
+ const search = details.inputValue.toLowerCase();
+ setItems(
+ initialItems
+ .filter(
+ search
+ ? (item) => item.toLowerCase().startsWith(search)
+ : isNotVendorProperty,
+ )
+ .join('\n'),
+ );
+ };
+ const handleSelect = (details: SelectionDetails) => {
+ props.onAddProperty(details.itemValue as keyof StyleObject);
+ combobox.setInputValue('');
+ };
+
+ const combobox = useCombobox({
+ allowCustomValue: true,
+ collection: collection,
+ inputBehavior: 'autocomplete',
+ onInputValueChange: handleInputValueChange,
+ onSelect: handleSelect,
+ placeholder: 'Add CSS Property',
+ positioning: {
+ placement: 'bottom-start',
+ sameWidth: false,
+ },
+ });
+ return combobox;
+}
+
+interface CSSPropertyComboBoxProps {
+ onAddProperty: (property: keyof StyleObject) => void;
+}
+
+const CSSPropertyComboBox = (props: CSSPropertyComboBoxProps) => {
+ const {onAddProperty} = props;
+ const combobox = useSuggestedStylesCombobox(props);
+ const handleKeydown = useCallback>(
+ (event) => {
+ const {inputValue} = combobox;
+ if (event.key === 'Enter') {
+ event.preventDefault();
+ if (inputValue) {
+ onAddProperty(inputValue as keyof StyleObject);
+ combobox.setInputValue('');
+ }
+ } else if (event.key === 'Tab') {
+ event.preventDefault();
+ if (inputValue) {
+ const [autocomplete] = combobox.collection.items;
+ if (autocomplete) {
+ onAddProperty(autocomplete as keyof StyleObject);
+ combobox.setInputValue('');
+ }
+ }
+ }
+ },
+ [combobox, onAddProperty],
+ );
+
+ return (
+
+
+
+
+
+
+
+
+ {combobox.collection.items.map((item) => (
+
+ {item}
+ ✓
+
+ ))}
+
+
+
+
+
+ );
+};
+
+function LexicalTextSelectionPane() {
+ const editorState = useEditorState();
+ const api = useNodeTreeViewContext();
+ const panelNodeKey = getSelectedNodeKey(api);
+ const [state, dispatch] = useReducer(
+ textSelectionPaneReducer,
+ {editorState, panelNodeKey},
+ initTextSelectionPaneReducer,
+ );
+ useEffect(() => {
+ dispatch({editorState, panelNodeKey});
+ }, [panelNodeKey, editorState]);
+ return state.cached || null;
+}
+
+function LexicalTreeView() {
+ const collectionState = useEditorCollectionState();
+ const {collection, focusNodeKey} = collectionState;
+ const [editor] = useLexicalComposerContext();
+ const editorRef = useRef(editor);
+ useEffect(() => {
+ editorRef.current = editor;
+ }, [editor]);
+ const treeView = useTreeView({
+ collection,
+ defaultExpandedValue: ['root'],
+ });
+ useEffect(() => {
+ if (
+ focusNodeKey !== null &&
+ !treeView.expandedValue.includes(focusNodeKey)
+ ) {
+ treeView.expand([focusNodeKey]);
+ }
+ }, [treeView, focusNodeKey]);
+ const splitter = useSplitter({
+ defaultSize: [50, 50],
+ panels: [{id: 'tree'}, {id: 'node'}],
+ });
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+interface EditorCollectionState {
+ editor: LexicalEditor;
+ editorState: EditorState;
+ collection: TreeCollection;
+ focusNodeKey: null | NodeKey;
+}
+
+function nextFocusNodeKey(state: EditorCollectionState): null | NodeKey {
+ return state.editorState.read(() => {
+ const selection = $getSelection();
+ return selection && $isRangeSelection(selection)
+ ? selection.focus.getNode().getKey()
+ : null;
+ });
+}
+
+function initEditorCollection(
+ state: Omit &
+ Partial>,
+): EditorCollectionState {
+ return Object.assign(state, {
+ collection: createTreeCollection({
+ isNodeDisabled: () => false,
+ nodeToChildren: (nodeKey) =>
+ state.editorState.read(() => {
+ const node = $getNodeByKey(nodeKey);
+ return $isElementNode(node) ? node.getChildrenKeys() : [];
+ }),
+ nodeToString: (nodeKey) => nodeKey,
+ nodeToValue: (nodeKey) => nodeKey,
+ rootNode: 'root',
+ }),
+ focusNodeKey: null,
+ });
+}
+
+function editorCollectionReducer(
+ state: EditorCollectionState,
+ action: Partial,
+) {
+ let nextState = {...state, ...action};
+ if (action.editor && action.editor !== state.editor) {
+ nextState = initEditorCollection(nextState);
+ }
+ nextState.focusNodeKey = nextFocusNodeKey(nextState);
+ return nextState;
+}
+
+function useEditorCollectionState() {
+ const [editor] = useLexicalComposerContext();
+ const editorState = useEditorState();
+ const [state, dispatch] = useReducer(
+ editorCollectionReducer,
+ {editor, editorState},
+ initEditorCollection,
+ );
+ useEffect(() => {
+ dispatch({editor, editorState});
+ }, [editor, editorState]);
+ return state;
+}
diff --git a/examples/dev-node-state-style/src/plugins/ToolbarPlugin.tsx b/examples/dev-node-state-style/src/plugins/ToolbarPlugin.tsx
new file mode 100644
index 00000000000..bc3af4583cb
--- /dev/null
+++ b/examples/dev-node-state-style/src/plugins/ToolbarPlugin.tsx
@@ -0,0 +1,162 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
+import {mergeRegister} from '@lexical/utils';
+import {
+ $getSelection,
+ $isRangeSelection,
+ CAN_REDO_COMMAND,
+ CAN_UNDO_COMMAND,
+ COMMAND_PRIORITY_LOW,
+ FORMAT_TEXT_COMMAND,
+ REDO_COMMAND,
+ SELECTION_CHANGE_COMMAND,
+ UNDO_COMMAND,
+} from 'lexical';
+import {useCallback, useEffect, useRef, useState} from 'react';
+
+import {
+ $selectionHasStyle,
+ NO_STYLE,
+ PATCH_TEXT_STYLE_COMMAND,
+} from '../styleState';
+
+function Divider() {
+ return
;
+}
+
+export function ToolbarPlugin() {
+ const [editor] = useLexicalComposerContext();
+ const toolbarRef = useRef(null);
+ const [canUndo, setCanUndo] = useState(false);
+ const [canRedo, setCanRedo] = useState(false);
+ const [isBold, setIsBold] = useState(false);
+ const [isItalic, setIsItalic] = useState(false);
+ const [isUnderline, setIsUnderline] = useState(false);
+ const [isStrikethrough, setIsStrikethrough] = useState(false);
+ const [isStyled, setIsStyled] = useState(false);
+
+ const $updateToolbar = useCallback(() => {
+ const selection = $getSelection();
+ setIsStyled($selectionHasStyle());
+ if ($isRangeSelection(selection)) {
+ // Update text format
+ setIsBold(selection.hasFormat('bold'));
+ setIsItalic(selection.hasFormat('italic'));
+ setIsUnderline(selection.hasFormat('underline'));
+ setIsStrikethrough(selection.hasFormat('strikethrough'));
+ }
+ }, []);
+
+ useEffect(() => {
+ return mergeRegister(
+ editor.registerUpdateListener(({editorState}) => {
+ editorState.read(() => {
+ $updateToolbar();
+ });
+ }),
+ editor.registerCommand(
+ SELECTION_CHANGE_COMMAND,
+ (_payload, _newEditor) => {
+ $updateToolbar();
+ return false;
+ },
+ COMMAND_PRIORITY_LOW,
+ ),
+ editor.registerCommand(
+ CAN_UNDO_COMMAND,
+ (payload) => {
+ setCanUndo(payload);
+ return false;
+ },
+ COMMAND_PRIORITY_LOW,
+ ),
+ editor.registerCommand(
+ CAN_REDO_COMMAND,
+ (payload) => {
+ setCanRedo(payload);
+ return false;
+ },
+ COMMAND_PRIORITY_LOW,
+ ),
+ );
+ }, [editor, $updateToolbar]);
+
+ return (
+
+
{
+ editor.dispatchCommand(UNDO_COMMAND, undefined);
+ }}
+ className="toolbar-item spaced"
+ aria-label="Undo">
+
+
+
{
+ editor.dispatchCommand(REDO_COMMAND, undefined);
+ }}
+ className="toolbar-item"
+ aria-label="Redo">
+
+
+
+
{
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'bold');
+ }}
+ className={'toolbar-item spaced ' + (isBold ? 'active' : '')}
+ aria-label="Format Bold">
+
+
+
{
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'italic');
+ }}
+ className={'toolbar-item spaced ' + (isItalic ? 'active' : '')}
+ aria-label="Format Italics">
+
+
+
{
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'underline');
+ }}
+ className={'toolbar-item spaced ' + (isUnderline ? 'active' : '')}
+ aria-label="Format Underline">
+
+
+
{
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'strikethrough');
+ }}
+ className={'toolbar-item spaced ' + (isStrikethrough ? 'active' : '')}
+ aria-label="Format Strikethrough">
+
+
+
+
{
+ editor.dispatchCommand(
+ PATCH_TEXT_STYLE_COMMAND,
+ isStyled
+ ? () => NO_STYLE
+ : {
+ 'text-shadow':
+ '1px 1px 2px red, 0 0 1em blue, 0 0 0.2em blue',
+ },
+ );
+ }}
+ className="toolbar-item spaced"
+ aria-label="Toggle Text Style">
+
+
+
+ );
+}
diff --git a/examples/dev-node-state-style/src/styleState.ts b/examples/dev-node-state-style/src/styleState.ts
new file mode 100644
index 00000000000..69d5b66dda8
--- /dev/null
+++ b/examples/dev-node-state-style/src/styleState.ts
@@ -0,0 +1,449 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+
+import type {PropertiesHyphenFallback} from 'csstype';
+
+import {domOverride, DOMRenderExtension} from '@lexical/html';
+import {$forEachSelectedTextNode} from '@lexical/selection';
+import InlineStyleParser from 'inline-style-parser';
+import {
+ $caretRangeFromSelection,
+ $getPreviousSelection,
+ $getSelection,
+ $getState,
+ $isRangeSelection,
+ $isTextNode,
+ $setSelection,
+ $setState,
+ COMMAND_PRIORITY_EDITOR,
+ configExtension,
+ createCommand,
+ createState,
+ defineExtension,
+ DOMConversionMap,
+ isHTMLElement,
+ LexicalNode,
+ TextNode,
+ ValueOrUpdater,
+} from 'lexical';
+
+/**
+ * Creates an object containing all the styles and their values provided in the CSS string.
+ * @param css - The CSS string of styles and their values.
+ * @returns The styleObject containing all the styles and their values.
+ */
+export function getStyleObjectFromRawCSS(css: string): StyleObject {
+ let styleObject: undefined | Record;
+ for (const token of InlineStyleParser(css, {silent: true})) {
+ if (token.type === 'declaration' && token.value) {
+ styleObject = styleObject || {};
+ styleObject[token.property] = token.value;
+ }
+ }
+ return styleObject || NO_STYLE;
+}
+
+export type Prettify = {[K in keyof T]: T[K]} & {};
+
+export type StyleObject = Prettify<{
+ [K in keyof PropertiesHyphenFallback]?:
+ | undefined
+ // This is simplified to not deal with arrays or numbers.
+ // This is an example after all!
+ | Extract;
+}>;
+
+export type StyleTuple = Exclude<
+ {
+ [K in keyof StyleObject]: [K, null | Exclude];
+ }[keyof StyleObject],
+ undefined
+>;
+
+export const NO_STYLE: StyleObject = Object.freeze({});
+
+function parse(v: unknown): StyleObject {
+ return typeof v === 'string' ? getStyleObjectFromRawCSS(v) : NO_STYLE;
+}
+
+function unparse(style: StyleObject): string {
+ const styles: string[] = [];
+ for (const [k, v] of Object.entries(style)) {
+ if (k && v) {
+ styles.push(`${k}: ${v};`);
+ }
+ }
+ return styles.sort().join(' ');
+}
+
+function isEqualValue(
+ a: StyleObject[keyof StyleObject],
+ b: StyleObject[keyof StyleObject],
+): boolean {
+ return a === b || (!a && !b);
+}
+
+function isEqual(a: StyleObject, b: StyleObject): boolean {
+ if (a === b) {
+ return true;
+ }
+ for (const k in a) {
+ if (
+ !(
+ k in b &&
+ isEqualValue(a[k as keyof StyleObject], b[k as keyof StyleObject])
+ )
+ ) {
+ return false;
+ }
+ }
+ for (const k in b) {
+ if (!(k in a)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+export const styleState = createState('style', {
+ isEqual,
+ parse,
+ unparse,
+});
+
+export function $getStyleProperty(
+ node: LexicalNode,
+ prop: Prop,
+): undefined | StyleObject[Prop] {
+ return $getStyleObject(node)[prop];
+}
+
+// eslint-disable-next-line @lexical/rules-of-lexical
+export function getStyleObjectDirect(node: LexicalNode): StyleObject {
+ return $getState(node, styleState, 'direct');
+}
+
+export function $getStyleObject(node: LexicalNode): StyleObject {
+ return $getState(node, styleState);
+}
+
+export function $setStyleObject(
+ node: T,
+ valueOrUpdater: ValueOrUpdater,
+): T {
+ return $setState(node, styleState, valueOrUpdater);
+}
+
+export function $removeStyleProperty<
+ T extends LexicalNode,
+ Prop extends keyof StyleObject,
+>(node: T, prop: Prop): T {
+ return $setStyleObject(node, (prevStyle) => {
+ if (prop in prevStyle) {
+ const {[prop]: _ignore, ...nextStyle} = prevStyle;
+ return nextStyle;
+ }
+ return prevStyle;
+ });
+}
+
+export function $setStyleProperty<
+ T extends LexicalNode,
+ Prop extends keyof StyleObject,
+>(node: T, prop: Prop, value: ValueOrUpdater): T {
+ return $setStyleObject(node, (prevStyle) => {
+ const prevValue = prevStyle[prop];
+ const nextValue = typeof value === 'function' ? value(prevValue) : value;
+ return prevValue === nextValue
+ ? prevStyle
+ : {...prevStyle, [prop]: nextValue};
+ });
+}
+
+export function applyStyle(
+ element: HTMLElement,
+ styleObject: StyleObject,
+): void {
+ for (const k_ in styleObject) {
+ const k = k_ as keyof StyleObject;
+ element.style.setProperty(k, styleObject[k] ?? null);
+ }
+}
+
+export function diffStyleObjects(
+ prevStyles: StyleObject,
+ nextStyles: StyleObject,
+): StyleObject {
+ let styleDiff: undefined | Record;
+ if (prevStyles !== nextStyles) {
+ for (const k_ in nextStyles) {
+ const k = k_ as keyof StyleObject;
+ const nextV = nextStyles[k];
+ const prevV = prevStyles[k];
+ if (!isEqualValue(nextV, prevV)) {
+ styleDiff = styleDiff || {};
+ styleDiff[k] = nextV;
+ }
+ }
+ for (const k in prevStyles) {
+ if (!(k in nextStyles)) {
+ styleDiff = styleDiff || {};
+ styleDiff[k] = undefined;
+ }
+ }
+ }
+ return styleDiff || NO_STYLE;
+}
+
+export function mergeStyleObjects(
+ prevStyles: StyleObject,
+ nextStyles: StyleObject,
+): StyleObject {
+ return prevStyles === NO_STYLE || prevStyles === nextStyles
+ ? nextStyles
+ : {...prevStyles, ...nextStyles};
+}
+
+export function styleObjectToArray(styleObject: StyleObject): StyleTuple[] {
+ const entries: StyleTuple[] = [];
+ for (const k_ in styleObject) {
+ const k = k_ as keyof StyleObject;
+ entries.push([k, styleObject[k] ?? null] as StyleTuple);
+ }
+ entries.sort(([a], [b]) => a.localeCompare(b));
+ return entries;
+}
+
+export const PATCH_TEXT_STYLE_COMMAND = createCommand<
+ StyleObject | ((prevStyles: StyleObject) => StyleObject)
+>('PATCH_TEXT_STYLE_COMMAND');
+
+function $nodeHasStyle(node: LexicalNode): boolean {
+ return !isEqual(NO_STYLE, $getStyleObject(node));
+}
+
+export function $selectionHasStyle(): boolean {
+ const selection = $getSelection();
+ if ($isRangeSelection(selection)) {
+ const caretRange = $caretRangeFromSelection(selection);
+ for (const slice of caretRange.getTextSlices()) {
+ if (slice && $nodeHasStyle(slice.caret.origin)) {
+ return true;
+ }
+ }
+ for (const caret of caretRange.iterNodeCarets('root')) {
+ if ($isTextNode(caret.origin) && $nodeHasStyle(caret.origin)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+export function $patchSelectedTextStyle(
+ styleObjectOrCallback:
+ | StyleObject
+ | ((prevStyles: StyleObject) => StyleObject),
+): boolean {
+ let selection = $getSelection();
+ if (!selection) {
+ const prevSelection = $getPreviousSelection();
+ if (!prevSelection) {
+ return false;
+ }
+ selection = prevSelection.clone();
+ $setSelection(selection);
+ }
+ const styleCallback =
+ typeof styleObjectOrCallback === 'function'
+ ? styleObjectOrCallback
+ : (prevStyles: StyleObject) =>
+ mergeStyleObjects(prevStyles, styleObjectOrCallback);
+ if ($isRangeSelection(selection) && selection.isCollapsed()) {
+ const node = selection.focus.getNode();
+ if ($isTextNode(node)) {
+ $setStyleObject(node, styleCallback);
+ }
+ } else {
+ $forEachSelectedTextNode((node) => $setStyleObject(node, styleCallback));
+ }
+ return true;
+}
+
+const PREV_STYLE_STATE = Symbol.for('styleState');
+interface HTMLElementWithManagedStyle extends HTMLElement {
+ // Store the last reconciled style object directly on the DOM
+ // so we don't have to track the previous DOM
+ // which can happen even when nodeMutation is 'updated'
+ [PREV_STYLE_STATE]?: StyleObject;
+}
+
+interface LexicalNodeWithUnknownStyle extends LexicalNode {
+ // This property exists on all TextNode and ElementNode
+ // and likely also some DecoratorNode by convention.
+ // We use it as a heuristic to see if the style has likely
+ // been overwritten to see if we should apply a diff
+ // or all styles.
+ __style?: unknown;
+}
+
+function styleStringChanged(
+ node: LexicalNodeWithUnknownStyle,
+ prevNode: LexicalNodeWithUnknownStyle,
+): boolean {
+ return typeof node.__style === 'string' && prevNode.__style !== node.__style;
+}
+
+function getPreviousStyleObject(
+ node: LexicalNode,
+ prevNode: null | LexicalNode,
+ dom: HTMLElementWithManagedStyle,
+): StyleObject {
+ const prevStyleObject = dom[PREV_STYLE_STATE];
+ return prevStyleObject && prevNode && !styleStringChanged(node, prevNode)
+ ? prevStyleObject
+ : NO_STYLE;
+}
+
+const IGNORE_STYLES: Set = new Set([
+ 'font-weight',
+ 'text-decoration',
+ 'font-style',
+ 'vertical-align',
+]);
+
+export type StyleMapping = (input: StyleObject) => StyleObject;
+
+// TODO there's no reasonable way to hook into importDOM from a plug-in https://github.com/facebook/lexical/issues/7259
+export function constructStyleImportMap(
+ styleMapping: StyleMapping = (input) => input,
+): DOMConversionMap {
+ const importMap: DOMConversionMap = {};
+
+ // Wrap all TextNode importers with a function that also imports
+ // styles that are not otherwise imported
+ for (const [tag, fn] of Object.entries(TextNode.importDOM() || {})) {
+ importMap[tag] = (importNode) => {
+ const importer = fn(importNode);
+ if (!importer) {
+ return null;
+ }
+ return {
+ ...importer,
+ conversion: (element) => {
+ const output = importer.conversion(element);
+ if (
+ output === null ||
+ output.forChild === undefined ||
+ output.after !== undefined ||
+ output.node !== null ||
+ !element.hasAttribute('style')
+ ) {
+ return output;
+ }
+ let extraStyles: undefined | Record;
+ for (const k of element.style) {
+ if (IGNORE_STYLES.has(k as keyof StyleObject)) {
+ continue;
+ }
+ extraStyles = extraStyles || {};
+ extraStyles[k] = element.style.getPropertyValue(k);
+ }
+ if (extraStyles) {
+ const {forChild} = output;
+ return {
+ ...output,
+ forChild: (child, parent) => {
+ const node = forChild(child, parent);
+ return $isTextNode(node)
+ ? $setStyleObject(
+ node,
+ styleMapping(extraStyles as StyleObject),
+ )
+ : node;
+ },
+ };
+ }
+ return output;
+ },
+ };
+ };
+ }
+ return importMap;
+}
+
+export const StyleStateExtension = defineExtension({
+ dependencies: [
+ configExtension(DOMRenderExtension, {
+ overrides: [
+ domOverride('*', {
+ $createDOM(node, $next) {
+ const dom: HTMLElementWithManagedStyle = $next();
+ const nextStyleObject = $getStyleObject(node);
+ dom[PREV_STYLE_STATE] = nextStyleObject;
+ applyStyle(dom, nextStyleObject);
+ return dom;
+ },
+ $exportDOM(node, $next) {
+ const output = $next();
+ const style = $getStyleObject(node);
+ if (output.element && style !== NO_STYLE) {
+ if (output.after) {
+ return {
+ ...output,
+ after: (generatedElement) => {
+ const el = output.after
+ ? output.after(generatedElement)
+ : generatedElement;
+ if (isHTMLElement(el)) {
+ applyStyle(el, style);
+ }
+ return el;
+ },
+ };
+ } else if (isHTMLElement(output.element)) {
+ applyStyle(output.element, style);
+ }
+ }
+ return output;
+ },
+ $updateDOM(
+ nextNode,
+ prevNode,
+ dom: HTMLElementWithManagedStyle,
+ $next,
+ ) {
+ if ($next()) {
+ return true;
+ }
+ const prevStyleObject = getPreviousStyleObject(
+ nextNode,
+ prevNode,
+ dom,
+ );
+ const nextStyleObject = $getStyleObject(nextNode);
+ dom[PREV_STYLE_STATE] = nextStyleObject;
+ applyStyle(dom, diffStyleObjects(prevStyleObject, nextStyleObject));
+ return false;
+ },
+ }),
+ ],
+ }),
+ ],
+ html: {
+ import: constructStyleImportMap(),
+ },
+ name: '@lexical/examples/node-state-style/StyleState',
+ register(editor) {
+ return editor.registerCommand(
+ PATCH_TEXT_STYLE_COMMAND,
+ $patchSelectedTextStyle,
+ COMMAND_PRIORITY_EDITOR,
+ );
+ },
+});
diff --git a/examples/dev-node-state-style/src/styles.css b/examples/dev-node-state-style/src/styles.css
new file mode 100644
index 00000000000..7921f7ed21e
--- /dev/null
+++ b/examples/dev-node-state-style/src/styles.css
@@ -0,0 +1,442 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+
+body {
+ margin: 0;
+ background: #eee;
+ font-family:
+ system-ui,
+ -apple-system,
+ BlinkMacSystemFont,
+ '.SFNSText-Regular',
+ sans-serif;
+ font-weight: 500;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+.other h2 {
+ font-size: 18px;
+ color: #444;
+ margin-bottom: 7px;
+}
+
+.other a {
+ color: #777;
+ text-decoration: underline;
+ font-size: 14px;
+}
+
+.other ul {
+ padding: 0;
+ margin: 0;
+ list-style-type: none;
+}
+
+.App {
+ font-family: sans-serif;
+}
+.App > h1 {
+ text-align: center;
+}
+
+h1 {
+ font-size: 24px;
+ color: #333;
+}
+
+.editor-container {
+ margin: 20px auto 20px auto;
+ border-radius: 2px;
+ max-width: 600px;
+ color: #000;
+ position: relative;
+ line-height: 20px;
+ font-weight: 400;
+ text-align: left;
+ border-top-left-radius: 10px;
+ border-top-right-radius: 10px;
+}
+
+.editor-inner {
+ background: #fff;
+ position: relative;
+}
+
+.editor-input {
+ min-height: 150px;
+ resize: none;
+ font-size: 15px;
+ caret-color: rgb(5, 5, 5);
+ position: relative;
+ tab-size: 1;
+ outline: 0;
+ padding: 15px 10px;
+ caret-color: #444;
+}
+
+.editor-placeholder {
+ color: #999;
+ overflow: hidden;
+ position: absolute;
+ text-overflow: ellipsis;
+ top: 15px;
+ left: 10px;
+ font-size: 15px;
+ user-select: none;
+ display: inline-block;
+ pointer-events: none;
+}
+
+.editor-text-bold {
+ font-weight: bold;
+}
+
+.editor-text-italic {
+ font-style: italic;
+}
+
+.editor-text-underline {
+ text-decoration: underline;
+}
+
+.editor-text-strikethrough {
+ text-decoration: line-through;
+}
+
+.editor-text-underlineStrikethrough {
+ text-decoration: underline line-through;
+}
+
+.editor-text-code {
+ background-color: rgb(240, 242, 245);
+ padding: 1px 0.25rem;
+ font-family: Menlo, Consolas, Monaco, monospace;
+ font-size: 94%;
+}
+
+.editor-link {
+ color: rgb(33, 111, 219);
+ text-decoration: none;
+}
+
+.tree-view-output {
+ display: block;
+ background: #222;
+ color: #fff;
+ padding: 5px;
+ font-size: 12px;
+ white-space: pre-wrap;
+ margin: 1px auto 10px auto;
+ max-height: 250px;
+ position: relative;
+ border-bottom-left-radius: 10px;
+ border-bottom-right-radius: 10px;
+ overflow: auto;
+ line-height: 14px;
+}
+
+.editor-code {
+ background-color: rgb(240, 242, 245);
+ font-family: Menlo, Consolas, Monaco, monospace;
+ display: block;
+ padding: 8px 8px 8px 52px;
+ line-height: 1.53;
+ font-size: 13px;
+ margin: 0;
+ margin-top: 8px;
+ margin-bottom: 8px;
+ tab-size: 2;
+ /* white-space: pre; */
+ overflow-x: auto;
+ position: relative;
+}
+
+.editor-code:before {
+ content: attr(data-gutter);
+ position: absolute;
+ background-color: #eee;
+ left: 0;
+ top: 0;
+ border-right: 1px solid #ccc;
+ padding: 8px;
+ color: #777;
+ white-space: pre-wrap;
+ text-align: right;
+ min-width: 25px;
+}
+.editor-code:after {
+ content: attr(data-highlight-language);
+ top: 0;
+ right: 3px;
+ padding: 3px;
+ font-size: 10px;
+ text-transform: uppercase;
+ position: absolute;
+ color: rgba(0, 0, 0, 0.5);
+}
+
+.editor-tokenComment {
+ color: slategray;
+}
+
+.editor-tokenPunctuation {
+ color: #999;
+}
+
+.editor-tokenProperty {
+ color: #905;
+}
+
+.editor-tokenSelector {
+ color: #690;
+}
+
+.editor-tokenOperator {
+ color: #9a6e3a;
+}
+
+.editor-tokenAttr {
+ color: #07a;
+}
+
+.editor-tokenVariable {
+ color: #e90;
+}
+
+.editor-tokenFunction {
+ color: #dd4a68;
+}
+
+.editor-paragraph {
+ margin: 0;
+ margin-bottom: 8px;
+ position: relative;
+}
+
+.editor-paragraph:last-child {
+ margin-bottom: 0;
+}
+
+.editor-heading-h1 {
+ font-size: 24px;
+ color: rgb(5, 5, 5);
+ font-weight: 400;
+ margin: 0;
+ margin-bottom: 12px;
+ padding: 0;
+}
+
+.editor-heading-h2 {
+ font-size: 15px;
+ color: rgb(101, 103, 107);
+ font-weight: 700;
+ margin: 0;
+ margin-top: 10px;
+ padding: 0;
+ text-transform: uppercase;
+}
+
+.editor-quote {
+ margin: 0;
+ margin-left: 20px;
+ font-size: 15px;
+ color: rgb(101, 103, 107);
+ border-left-color: rgb(206, 208, 212);
+ border-left-width: 4px;
+ border-left-style: solid;
+ padding-left: 16px;
+}
+
+.editor-list-ol {
+ padding: 0;
+ margin: 0;
+ margin-left: 16px;
+}
+
+.editor-list-ul {
+ padding: 0;
+ margin: 0;
+ margin-left: 16px;
+}
+
+.editor-listitem {
+ margin: 8px 32px 8px 32px;
+}
+
+.editor-nested-listitem {
+ list-style-type: none;
+}
+
+pre::-webkit-scrollbar {
+ background: transparent;
+ width: 10px;
+}
+
+pre::-webkit-scrollbar-thumb {
+ background: #999;
+}
+
+.debug-timetravel-panel {
+ overflow: hidden;
+ padding: 0 0 10px 0;
+ margin: auto;
+ display: flex;
+}
+
+.debug-timetravel-panel-slider {
+ padding: 0;
+ flex: 8;
+}
+
+.debug-timetravel-panel-button {
+ padding: 0;
+ border: 0;
+ background: none;
+ flex: 1;
+ color: #fff;
+ font-size: 12px;
+}
+
+.debug-timetravel-panel-button:hover {
+ text-decoration: underline;
+}
+
+.debug-timetravel-button {
+ border: 0;
+ padding: 0;
+ font-size: 12px;
+ top: 10px;
+ right: 15px;
+ position: absolute;
+ background: none;
+ color: #fff;
+}
+
+.debug-timetravel-button:hover {
+ text-decoration: underline;
+}
+
+.toolbar {
+ display: flex;
+ margin-bottom: 1px;
+ background: #fff;
+ padding: 4px;
+ border-top-left-radius: 10px;
+ border-top-right-radius: 10px;
+ vertical-align: middle;
+}
+
+.toolbar button.toolbar-item {
+ border: 0;
+ display: flex;
+ background: none;
+ border-radius: 10px;
+ padding: 8px;
+ cursor: pointer;
+ vertical-align: middle;
+}
+
+.toolbar button.toolbar-item:disabled {
+ cursor: not-allowed;
+}
+
+.toolbar button.toolbar-item.spaced {
+ margin-right: 2px;
+}
+
+.toolbar button.toolbar-item i.format {
+ background-size: contain;
+ display: inline-block;
+ height: 18px;
+ width: 18px;
+ margin-top: 2px;
+ vertical-align: -0.25em;
+ display: flex;
+ opacity: 0.6;
+}
+
+.toolbar button.toolbar-item:disabled i.format {
+ opacity: 0.2;
+}
+
+.toolbar button.toolbar-item.active {
+ background-color: rgba(223, 232, 250, 0.3);
+}
+
+.toolbar button.toolbar-item.active i {
+ opacity: 1;
+}
+
+.toolbar .toolbar-item:hover:not([disabled]) {
+ background-color: #eee;
+}
+
+.toolbar .divider {
+ width: 1px;
+ background-color: #eee;
+ margin: 0 4px;
+}
+
+.toolbar .toolbar-item .text {
+ display: flex;
+ line-height: 20px;
+ width: 200px;
+ vertical-align: middle;
+ font-size: 14px;
+ color: #777;
+ text-overflow: ellipsis;
+ width: 70px;
+ overflow: hidden;
+ height: 20px;
+ text-align: left;
+}
+
+.toolbar .toolbar-item .icon {
+ display: flex;
+ width: 20px;
+ height: 20px;
+ user-select: none;
+ margin-right: 8px;
+ line-height: 16px;
+ background-size: contain;
+}
+
+i.undo {
+ background-image: url(./icons/arrow-counterclockwise.svg);
+}
+
+i.redo {
+ background-image: url(./icons/arrow-clockwise.svg);
+}
+
+i.bold {
+ background-image: url(./icons/type-bold.svg);
+}
+
+i.italic {
+ background-image: url(./icons/type-italic.svg);
+}
+
+i.underline {
+ background-image: url(./icons/type-underline.svg);
+}
+
+i.strikethrough {
+ background-image: url(./icons/type-strikethrough.svg);
+}
+
+i.text-shadow::before {
+ content: '✨';
+ filter: contrast(0);
+}
+
+i.text-shadow.active::before {
+ filter: contrast(1);
+ text-shadow: 1px solid black;
+}
diff --git a/examples/dev-node-state-style/src/vite-env.d.ts b/examples/dev-node-state-style/src/vite-env.d.ts
new file mode 100644
index 00000000000..11f02fe2a00
--- /dev/null
+++ b/examples/dev-node-state-style/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/examples/dev-node-state-style/tsconfig.json b/examples/dev-node-state-style/tsconfig.json
new file mode 100644
index 00000000000..ccf1249ccd6
--- /dev/null
+++ b/examples/dev-node-state-style/tsconfig.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable", "ESNext.Disposable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ // "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "extends": ["../../tsconfig.json"],
+ "include": ["src", "../../libdefs/*.d.ts"],
+ "references": [{"path": "./tsconfig.node.json"}]
+}
diff --git a/examples/dev-node-state-style/tsconfig.node.json b/examples/dev-node-state-style/tsconfig.node.json
new file mode 100644
index 00000000000..97ede7ee6f2
--- /dev/null
+++ b/examples/dev-node-state-style/tsconfig.node.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "strict": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/examples/dev-node-state-style/vite.config.monorepo.ts b/examples/dev-node-state-style/vite.config.monorepo.ts
new file mode 100644
index 00000000000..140511d5b57
--- /dev/null
+++ b/examples/dev-node-state-style/vite.config.monorepo.ts
@@ -0,0 +1,15 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import {mergeConfig} from 'vite';
+
+import lexicalMonorepoPlugin from '../../packages/shared/lexicalMonorepoPlugin';
+import config from './vite.config';
+
+export default mergeConfig(config, {
+ plugins: [lexicalMonorepoPlugin()],
+});
diff --git a/examples/dev-node-state-style/vite.config.ts b/examples/dev-node-state-style/vite.config.ts
new file mode 100644
index 00000000000..2294526fc4f
--- /dev/null
+++ b/examples/dev-node-state-style/vite.config.ts
@@ -0,0 +1,14 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import react from '@vitejs/plugin-react';
+import {defineConfig} from 'vite';
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+});
diff --git a/examples/extension-vanilla-tailwind/package-lock.json b/examples/extension-vanilla-tailwind/package-lock.json
index e77cb559719..cf2452e5c6d 100644
--- a/examples/extension-vanilla-tailwind/package-lock.json
+++ b/examples/extension-vanilla-tailwind/package-lock.json
@@ -824,6 +824,19 @@
"node": ">=8.6"
}
},
+ "node_modules/micromatch/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/minimatch": {
"version": "3.1.2",
"dev": true,
@@ -928,11 +941,13 @@
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "2.3.1",
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=8.6"
+ "node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
@@ -1153,17 +1168,6 @@
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
- "node_modules/tinyglobby/node_modules/picomatch": {
- "version": "4.0.3",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
"node_modules/to-regex-range": {
"version": "5.0.1",
"dev": true,
@@ -1310,17 +1314,6 @@
}
}
},
- "node_modules/vite/node_modules/picomatch": {
- "version": "4.0.3",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
"node_modules/which": {
"version": "2.0.2",
"dev": true,
diff --git a/package-lock.json b/package-lock.json
index 2eb81a7b2b5..aa0dd4b15a6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,8 @@
"version": "0.37.0",
"license": "MIT",
"workspaces": [
- "packages/*"
+ "packages/*",
+ "examples/dev-*"
],
"dependencies": {
"semver": "^7.7.2",
@@ -111,6 +112,45 @@
"eslint": "^7.31.0 || ^8.0.0"
}
},
+ "examples/dev-node-state-style": {
+ "name": "@lexical/dev-node-state-style-example",
+ "version": "0.37.0",
+ "dependencies": {
+ "@ark-ui/react": "^5.6.0",
+ "@lexical/clipboard": "0.37.0",
+ "@lexical/extension": "0.37.0",
+ "@lexical/history": "0.37.0",
+ "@lexical/html": "0.37.0",
+ "@lexical/react": "0.37.0",
+ "@lexical/rich-text": "0.37.0",
+ "@lexical/selection": "0.37.0",
+ "@lexical/utils": "0.37.0",
+ "@shikijs/langs": "^3.3.0",
+ "@shikijs/themes": "^3.3.0",
+ "inline-style-parser": "^0.2.4",
+ "lexical": "0.37.0",
+ "lucide-react": "^0.503.0",
+ "prettier": "^3.5.3",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0",
+ "shiki": "^3.3.0"
+ },
+ "devDependencies": {
+ "@types/react": "^19.1.2",
+ "@types/react-dom": "^19.1.2",
+ "@vitejs/plugin-react": "^5.0.2",
+ "cross-env": "^7.0.3",
+ "csstype": "^3.1.3",
+ "typescript": "^5.9.2",
+ "vite": "^7.1.4"
+ }
+ },
+ "examples/dev-node-state-style/node_modules/inline-style-parser": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.6.tgz",
+ "integrity": "sha512-gtGXVaBdl5mAes3rPcMedEBm12ibjt1kDMFfheul1wUAOVEJW60voNdMVzVkfLN06O7ZaD/rxhfKgtlgtTbMjg==",
+ "license": "MIT"
+ },
"node_modules/@1natsu/wait-element": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/@1natsu/wait-element/-/wait-element-4.1.2.tgz",
@@ -531,6 +571,88 @@
"url": "https://github.com/sponsors/antfu"
}
},
+ "node_modules/@ark-ui/react": {
+ "version": "5.26.0",
+ "resolved": "https://registry.npmjs.org/@ark-ui/react/-/react-5.26.0.tgz",
+ "integrity": "sha512-SxuGfRNEu+Y9A8ixR8RJevS0RAg0hInMkhFD47X/8pFjYCdajSm6C+Pv23eDLpldV7SNFXEDUfU6wEkont/NGw==",
+ "license": "MIT",
+ "dependencies": {
+ "@internationalized/date": "3.10.0",
+ "@zag-js/accordion": "1.26.1",
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/angle-slider": "1.26.1",
+ "@zag-js/async-list": "1.26.1",
+ "@zag-js/auto-resize": "1.26.1",
+ "@zag-js/avatar": "1.26.1",
+ "@zag-js/bottom-sheet": "1.26.1",
+ "@zag-js/carousel": "1.26.1",
+ "@zag-js/checkbox": "1.26.1",
+ "@zag-js/clipboard": "1.26.1",
+ "@zag-js/collapsible": "1.26.1",
+ "@zag-js/collection": "1.26.1",
+ "@zag-js/color-picker": "1.26.1",
+ "@zag-js/color-utils": "1.26.1",
+ "@zag-js/combobox": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/date-picker": "1.26.1",
+ "@zag-js/date-utils": "1.26.1",
+ "@zag-js/dialog": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/editable": "1.26.1",
+ "@zag-js/file-upload": "1.26.1",
+ "@zag-js/file-utils": "1.26.1",
+ "@zag-js/floating-panel": "1.26.1",
+ "@zag-js/focus-trap": "1.26.1",
+ "@zag-js/highlight-word": "1.26.1",
+ "@zag-js/hover-card": "1.26.1",
+ "@zag-js/i18n-utils": "1.26.1",
+ "@zag-js/json-tree-utils": "1.26.1",
+ "@zag-js/listbox": "1.26.1",
+ "@zag-js/menu": "1.26.1",
+ "@zag-js/number-input": "1.26.1",
+ "@zag-js/pagination": "1.26.1",
+ "@zag-js/password-input": "1.26.1",
+ "@zag-js/pin-input": "1.26.1",
+ "@zag-js/popover": "1.26.1",
+ "@zag-js/presence": "1.26.1",
+ "@zag-js/progress": "1.26.1",
+ "@zag-js/qr-code": "1.26.1",
+ "@zag-js/radio-group": "1.26.1",
+ "@zag-js/rating-group": "1.26.1",
+ "@zag-js/react": "1.26.1",
+ "@zag-js/scroll-area": "1.26.1",
+ "@zag-js/select": "1.26.1",
+ "@zag-js/signature-pad": "1.26.1",
+ "@zag-js/slider": "1.26.1",
+ "@zag-js/splitter": "1.26.1",
+ "@zag-js/steps": "1.26.1",
+ "@zag-js/switch": "1.26.1",
+ "@zag-js/tabs": "1.26.1",
+ "@zag-js/tags-input": "1.26.1",
+ "@zag-js/timer": "1.26.1",
+ "@zag-js/toast": "1.26.1",
+ "@zag-js/toggle": "1.26.1",
+ "@zag-js/toggle-group": "1.26.1",
+ "@zag-js/tooltip": "1.26.1",
+ "@zag-js/tour": "1.26.1",
+ "@zag-js/tree-view": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "peerDependencies": {
+ "react": ">=18.0.0",
+ "react-dom": ">=18.0.0"
+ }
+ },
+ "node_modules/@ark-ui/react/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
"node_modules/@babel/code-frame": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
@@ -7601,48 +7723,6 @@
"@shikijs/vscode-textmate": "^10.0.2"
}
},
- "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/engine-oniguruma": {
- "version": "3.12.2",
- "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.12.2.tgz",
- "integrity": "sha512-hozwnFHsLvujK4/CPVHNo3Bcg2EsnG8krI/ZQ2FlBlCRpPZW4XAEQmEwqegJsypsTAN9ehu2tEYe30lYKSZW/w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@shikijs/types": "3.12.2",
- "@shikijs/vscode-textmate": "^10.0.2"
- }
- },
- "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/langs": {
- "version": "3.12.2",
- "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.12.2.tgz",
- "integrity": "sha512-bVx5PfuZHDSHoBal+KzJZGheFuyH4qwwcwG/n+MsWno5cTlKmaNtTsGzJpHYQ8YPbB5BdEdKU1rga5/6JGY8ww==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@shikijs/types": "3.12.2"
- }
- },
- "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/themes": {
- "version": "3.12.2",
- "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.12.2.tgz",
- "integrity": "sha512-fTR3QAgnwYpfGczpIbzPjlRnxyONJOerguQv1iwpyQZ9QXX4qy/XFQqXlf17XTsorxnHoJGbH/LXBvwtqDsF5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@shikijs/types": "3.12.2"
- }
- },
- "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/types": {
- "version": "3.12.2",
- "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.12.2.tgz",
- "integrity": "sha512-K5UIBzxCyv0YoxN3LMrKB9zuhp1bV+LgewxuVwHdl4Gz5oePoUFrr9EfgJlGlDeXCU1b/yhdnXeuRvAnz8HN8Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@shikijs/vscode-textmate": "^10.0.2",
- "@types/hast": "^3.0.4"
- }
- },
"node_modules/@hapi/hoek": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
@@ -7732,6 +7812,24 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
+ "node_modules/@internationalized/date": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.10.0.tgz",
+ "integrity": "sha512-oxDR/NTEJ1k+UFVQElaNIk65E/Z83HK1z1WI3lQyhTtnNg4R5oVXaPzK3jcpKG8UHKDVuDQHzn+wsxSz8RP3aw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ }
+ },
+ "node_modules/@internationalized/number": {
+ "version": "3.6.5",
+ "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.5.tgz",
+ "integrity": "sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ }
+ },
"node_modules/@isaacs/balanced-match": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
@@ -8740,6 +8838,10 @@
"resolved": "packages/lexical-code-shiki",
"link": true
},
+ "node_modules/@lexical/dev-node-state-style-example": {
+ "resolved": "examples/dev-node-state-style",
+ "link": true
+ },
"node_modules/@lexical/devtools": {
"resolved": "packages/lexical-devtools",
"link": true
@@ -11700,55 +11802,61 @@
}
},
"node_modules/@shikijs/core": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.7.0.tgz",
- "integrity": "sha512-yilc0S9HvTPyahHpcum8eonYrQtmGTU0lbtwxhA6jHv4Bm1cAdlPFRCJX4AHebkCm75aKTjjRAW+DezqD1b/cg==",
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.13.0.tgz",
+ "integrity": "sha512-3P8rGsg2Eh2qIHekwuQjzWhKI4jV97PhvYjYUzGqjvJfqdQPz+nMlfWahU24GZAyW1FxFI1sYjyhfh5CoLmIUA==",
+ "license": "MIT",
"dependencies": {
- "@shikijs/types": "3.7.0",
+ "@shikijs/types": "3.13.0",
"@shikijs/vscode-textmate": "^10.0.2",
"@types/hast": "^3.0.4",
"hast-util-to-html": "^9.0.5"
}
},
"node_modules/@shikijs/engine-javascript": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.7.0.tgz",
- "integrity": "sha512-0t17s03Cbv+ZcUvv+y33GtX75WBLQELgNdVghnsdhTgU3hVcWcMsoP6Lb0nDTl95ZJfbP1mVMO0p3byVh3uuzA==",
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.13.0.tgz",
+ "integrity": "sha512-Ty7xv32XCp8u0eQt8rItpMs6rU9Ki6LJ1dQOW3V/56PKDcpvfHPnYFbsx5FFUP2Yim34m/UkazidamMNVR4vKg==",
+ "license": "MIT",
"dependencies": {
- "@shikijs/types": "3.7.0",
+ "@shikijs/types": "3.13.0",
"@shikijs/vscode-textmate": "^10.0.2",
"oniguruma-to-es": "^4.3.3"
}
},
"node_modules/@shikijs/engine-oniguruma": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.7.0.tgz",
- "integrity": "sha512-5BxcD6LjVWsGu4xyaBC5bu8LdNgPCVBnAkWTtOCs/CZxcB22L8rcoWfv7Hh/3WooVjBZmFtyxhgvkQFedPGnFw==",
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.13.0.tgz",
+ "integrity": "sha512-O42rBGr4UDSlhT2ZFMxqM7QzIU+IcpoTMzb3W7AlziI1ZF7R8eS2M0yt5Ry35nnnTX/LTLXFPUjRFCIW+Operg==",
+ "license": "MIT",
"dependencies": {
- "@shikijs/types": "3.7.0",
+ "@shikijs/types": "3.13.0",
"@shikijs/vscode-textmate": "^10.0.2"
}
},
"node_modules/@shikijs/langs": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.7.0.tgz",
- "integrity": "sha512-1zYtdfXLr9xDKLTGy5kb7O0zDQsxXiIsw1iIBcNOO8Yi5/Y1qDbJ+0VsFoqTlzdmneO8Ij35g7QKF8kcLyznCQ==",
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.13.0.tgz",
+ "integrity": "sha512-672c3WAETDYHwrRP0yLy3W1QYB89Hbpj+pO4KhxK6FzIrDI2FoEXNiNCut6BQmEApYLfuYfpgOZaqbY+E9b8wQ==",
+ "license": "MIT",
"dependencies": {
- "@shikijs/types": "3.7.0"
+ "@shikijs/types": "3.13.0"
}
},
"node_modules/@shikijs/themes": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.7.0.tgz",
- "integrity": "sha512-VJx8497iZPy5zLiiCTSIaOChIcKQwR0FebwE9S3rcN0+J/GTWwQ1v/bqhTbpbY3zybPKeO8wdammqkpXc4NVjQ==",
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.13.0.tgz",
+ "integrity": "sha512-Vxw1Nm1/Od8jyA7QuAenaV78BG2nSr3/gCGdBkLpfLscddCkzkL36Q5b67SrLLfvAJTOUzW39x4FHVCFriPVgg==",
+ "license": "MIT",
"dependencies": {
- "@shikijs/types": "3.7.0"
+ "@shikijs/types": "3.13.0"
}
},
"node_modules/@shikijs/types": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.7.0.tgz",
- "integrity": "sha512-MGaLeaRlSWpnP0XSAum3kP3a8vtcTsITqoEPYdt3lQG3YCdQH4DnEhodkYcNMcU0uW0RffhoD1O3e0vG5eSBBg==",
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.13.0.tgz",
+ "integrity": "sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw==",
+ "license": "MIT",
"dependencies": {
"@shikijs/vscode-textmate": "^10.0.2",
"@types/hast": "^3.0.4"
@@ -12393,6 +12501,15 @@
"integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
"license": "Apache-2.0"
},
+ "node_modules/@swc/helpers": {
+ "version": "0.5.17",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz",
+ "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
"node_modules/@swc/html": {
"version": "1.13.20",
"resolved": "https://registry.npmjs.org/@swc/html/-/html-1.13.20.tgz",
@@ -15141,16 +15258,531 @@
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
"license": "Apache-2.0"
},
+ "node_modules/@zag-js/accordion": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/accordion/-/accordion-1.26.1.tgz",
+ "integrity": "sha512-Rqp5zPyWn7w1D2teZAlLytK7okRjfdU4qLuwO7SPdXgeqxr+bn7qP9Bxs4NU78nySA8ZbLZqPbmTA31m9Ya6lw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/accordion/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/anatomy": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/anatomy/-/anatomy-1.26.1.tgz",
+ "integrity": "sha512-1GVk5D/gFTvBd06w3MgDkSUGtUyU5n6XL8G6KsmuIh6dq16MgZ0TnDsUOkPVBQL3YEiHqlJfeCS6zkgcsu3q2g==",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/angle-slider": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/angle-slider/-/angle-slider-1.26.1.tgz",
+ "integrity": "sha512-fdT6caDvT8ECyszhV6NN9CfCK5OJNK/0/456nYRclHIzrrRZdQL1ZJhSGKrZhrFM2TbEQIf/qrgoPCK3J4/GCg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/rect-utils": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/angle-slider/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/aria-hidden": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/aria-hidden/-/aria-hidden-1.26.1.tgz",
+ "integrity": "sha512-8zZQDODCfXuJ0zfsx6+WVaYh+ScQoFG2ib2FvKr9sxztoJAn1hiLYFKzzlA1aWOxTAh+dFQC/jJI+C1nWbhBkQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/aria-hidden/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/async-list": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/async-list/-/async-list-1.26.1.tgz",
+ "integrity": "sha512-jzgypjD/2tx90EIhb8MnjXjd6A//Veiba5NJkAfxAYsr++tG1K/aTNARBPfTunRJq6ZjDoNSZWubjaNX+llD2g==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/core": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/auto-resize": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/auto-resize/-/auto-resize-1.26.1.tgz",
+ "integrity": "sha512-/t53ykgDOttYzroQQUgJqyOb+xlKClI5T1aJe/d7HOvGFqJtSSOYB9ZOJmywpkN9/11nYdH7HaZtSGmRjCQBzw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/auto-resize/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/avatar": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/avatar/-/avatar-1.26.1.tgz",
+ "integrity": "sha512-s34+KSqv/frY3W4Ng9uuuqQbVlgpeWG8b0CtGcELUw9VSldDSOE2ZMIZ1inFLoby9vOOovttHSd/QdGseXkFqQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/avatar/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/bottom-sheet": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/bottom-sheet/-/bottom-sheet-1.26.1.tgz",
+ "integrity": "sha512-Vroa6ivzSikSdYmX/Km88g/z7W7LNEBFnYAUMSCpRb/QFStRdbVPd7POzV27sCZfoKmUONYqGCBNs3g29DAGrQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/aria-hidden": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-trap": "1.26.1",
+ "@zag-js/remove-scroll": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/bottom-sheet/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/carousel": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/carousel/-/carousel-1.26.1.tgz",
+ "integrity": "sha512-hwxO1p+fsGpu+b8ufxdQAO2UhfP1jUugmBoYnaT3eQJ7Xl/E3MuJ3OMdxgeM9zbBRZuv7IWXVzfLQTNB1lz78g==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/scroll-snap": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/carousel/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/checkbox": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/checkbox/-/checkbox-1.26.1.tgz",
+ "integrity": "sha512-IESEO/WfQ6o45E8beCIOdg0u8tmgSF9gb2F0S1HNBSTmeTq5KSaz47Z8SDkci0g9cw2i+OZIX7BPZI4XpbT3tg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-visible": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/checkbox/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/checkbox/node_modules/@zag-js/focus-visible": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.26.1.tgz",
+ "integrity": "sha512-Hq57XwQWS0a5rjiZcgWhC8ca1e75VoqVLaSGn8XM29lv13423MPRtJ6b/zkEx5G4yZmddgA+wFh2/U2KPztcYA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/clipboard": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/clipboard/-/clipboard-1.26.1.tgz",
+ "integrity": "sha512-1yWTvFELfkRoM9GUjscU0Dl3CsLmXHzRyKttYY478xiL9jOKLaJfg6R0c42HJIXqfgIf7shG1aNOse4qmR266Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/clipboard/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/collapsible": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/collapsible/-/collapsible-1.26.1.tgz",
+ "integrity": "sha512-B8zMtX508R71mpOunB25DXFaeXJEX1n38eOq0kUuGyggmoJdOMwLPCuzo9L9ETROynOcPwJ5YzMnhAkw7kjaBg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/collapsible/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/collection": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/collection/-/collection-1.26.1.tgz",
+ "integrity": "sha512-b23L4urNhCCH89TRr5UIWZsCtV9eaBhgTPu91qO2CAgz0fbvmkZJ/E5yr7EI4KeNg0xExbiQrhinZQt2v0LjCA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/color-picker": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/color-picker/-/color-picker-1.26.1.tgz",
+ "integrity": "sha512-c3Y9RCBYqXb4HhzxZIhcNQkG4Vpr/gQa86lbxF7JnrGRCB0CyurRxhTSALZGAOKV7/VovnJEaJYDiYtQz5nGCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/color-utils": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/color-picker/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/color-utils": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/color-utils/-/color-utils-1.26.1.tgz",
+ "integrity": "sha512-umTm464gTqMRHm3OPNkGDlb65yRlF1Ka4HrMe8eGo3l1AbQipiYE0WJf/aupUuwzm+CXKi244F1lYVnHesXHPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/combobox": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/combobox/-/combobox-1.26.1.tgz",
+ "integrity": "sha512-VLTTLvzgurvYrsg7UEb11Ad0ZPxWp3ui9/+J3rzgrTMEuLWj8mPfWT0i0l3AG+ruyFlQv5aZNvA/pupk3UK1Tg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/aria-hidden": "1.26.1",
+ "@zag-js/collection": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/combobox/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/core": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/core/-/core-1.26.1.tgz",
+ "integrity": "sha512-JesW6C1dlrG36Aa+yteL0v5nt4Zqa9n9coqDJUQ9L1AYWzjz6NTHubsA7ysJlTKwl411gSsssmH9Ey5sRxFEWQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/core/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/date-picker": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/date-picker/-/date-picker-1.26.1.tgz",
+ "integrity": "sha512-dh105RY/SKXa0iPDmIH5qpXZ1W/Ls+AU0d2l5phcEsVItbgE+FBKYTSuC91w+LNv+MpGPH+PXvatt10tW6SYGA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/date-utils": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/live-region": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "peerDependencies": {
+ "@internationalized/date": ">=3.0.0"
+ }
+ },
+ "node_modules/@zag-js/date-picker/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/date-utils": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/date-utils/-/date-utils-1.26.1.tgz",
+ "integrity": "sha512-nMTSfIk0B7MfOIJ0EpFFrHHOGDEI/F0OCG9LVvkwlKZ3evKmgAT5Hw18h2FbQ8ovQ9gNbWoUGPPnrnZJtkzhNw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@internationalized/date": ">=3.0.0"
+ }
+ },
+ "node_modules/@zag-js/dialog": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dialog/-/dialog-1.26.1.tgz",
+ "integrity": "sha512-kbNzTIMUkn19RcqDKF+3kH5cGPW3bY2FKiw6qtPi072SshHQtuAeE4g5K3wGFdSTJXHBhXYSK04ZR+ok00YbGA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/aria-hidden": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-trap": "1.26.1",
+ "@zag-js/remove-scroll": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/dialog/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/dismissable": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dismissable/-/dismissable-1.26.1.tgz",
+ "integrity": "sha512-n7MdvInqfOh+UJ+VpeIovVU734vf8ekHhfhIugDt41xAzndZW8hdXcBsKnDFK0uY9OVk8cq5FRqpdzhoZuZSgw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/interact-outside": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/dismissable/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
"node_modules/@zag-js/dom-query": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-0.16.0.tgz",
"integrity": "sha512-Oqhd6+biWyKnhKwFFuZrrf6lxBz2tX2pRQe6grUnYwO6HJ8BcbqZomy2lpOdr+3itlaUqx+Ywj5E5ZZDr/LBfQ=="
},
+ "node_modules/@zag-js/editable": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/editable/-/editable-1.26.1.tgz",
+ "integrity": "sha512-/QBKunz9PJvd26b/ZfHSktrXWI2oHp8U9+MDVQasQnpEbG5HEGkXw6Ew3y4v/Rfq4Ih3iUSVdAMmyMU7XpYZ7g==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/interact-outside": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/editable/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
"node_modules/@zag-js/element-size": {
"version": "0.10.5",
"resolved": "https://registry.npmjs.org/@zag-js/element-size/-/element-size-0.10.5.tgz",
"integrity": "sha512-uQre5IidULANvVkNOBQ1tfgwTQcGl4hliPSe69Fct1VfYb2Fd0jdAcGzqQgPhfrXFpR62MxLPB7erxJ/ngtL8w=="
},
+ "node_modules/@zag-js/file-upload": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/file-upload/-/file-upload-1.26.1.tgz",
+ "integrity": "sha512-fu6UpK8+qj98g2h3XrFqWzaSD5JHNt71qEg6hlYCwsXdcpYhTObps9YsTKo4sd/XGVh0lriyzSIsjBUeoctR6A==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/file-utils": "1.26.1",
+ "@zag-js/i18n-utils": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/file-upload/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/file-utils": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/file-utils/-/file-utils-1.26.1.tgz",
+ "integrity": "sha512-JW0vr7fzDDi9GEQLmGWSiBbNlSK8FQ/W+tavk0E4LNVb2Hs28/4F1XQXYKNuzfN+CoBYI74EIasb7rublozJMA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/i18n-utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/floating-panel": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/floating-panel/-/floating-panel-1.26.1.tgz",
+ "integrity": "sha512-45fVFASBxM+Lj6nvq4LjlCSl/JuBwzPchv8LYfR4hRHFNUuoNpQ2MDQMFJuMzxCk50U2FAa2R0QXvi3aniEJwA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/rect-utils": "1.26.1",
+ "@zag-js/store": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/floating-panel/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/focus-trap": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/focus-trap/-/focus-trap-1.26.1.tgz",
+ "integrity": "sha512-88NvG1vxga/Umx54p9K6+nkrC5QLOA/hc5FV68eMKn83u1PCCH8U2+RV/vhMJ7IUTEwI0VTZLOmDfyfbkfomTQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/focus-trap/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
"node_modules/@zag-js/focus-visible": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-0.16.0.tgz",
@@ -15159,6 +15791,873 @@
"@zag-js/dom-query": "0.16.0"
}
},
+ "node_modules/@zag-js/highlight-word": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/highlight-word/-/highlight-word-1.26.1.tgz",
+ "integrity": "sha512-xHEeUX8Qhie+tYUBdiR2GllrVpR4gqPCOHoI8HmH/8dWgUqFScRk9BFpR2/HetV9CrURsdjT4Za0mbGaJOssag==",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/hover-card": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/hover-card/-/hover-card-1.26.1.tgz",
+ "integrity": "sha512-Qmd6FY51JsUAxLFQEkbeNCsvzLRL2YX75EupFqNdBPL509yEJkFa1ASry6usgUZgpgMlNP9PrjFIwywyDa8gFw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/hover-card/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/i18n-utils": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/i18n-utils/-/i18n-utils-1.26.1.tgz",
+ "integrity": "sha512-bvzfdsiY4taqZA/QfgqofsynlJGoJGmtmV5zKcVdyTJRVQz04vSEIJ+bzEDpiqK0FtrOI2mOq3Ixmv8fKNRxlQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/i18n-utils/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/interact-outside": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/interact-outside/-/interact-outside-1.26.1.tgz",
+ "integrity": "sha512-Kxyg8AuJq4WssVbFyCtY14O611DU7UEiKgDwiNBXdQ5V+XXd4BBBwrA5QK9pk/qjgxZawKOalwjcYsyWhFbwLQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/interact-outside/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/json-tree-utils": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/json-tree-utils/-/json-tree-utils-1.26.1.tgz",
+ "integrity": "sha512-E3IDz6DgSZPJ6rKWoOARqicF9PMK5avUoqcDsQTsAM/z1SqQT1/++dzYpJ8r9rBej5n5rH1mhr+e5PmbkI5b5A==",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/listbox": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/listbox/-/listbox-1.26.1.tgz",
+ "integrity": "sha512-Xqeb/PO4Yrj87RwP/X357ilLmrEgBIqHy/1lYnVwEVQI8l2TvElRe95oAXGORnqWRM1H0dtoNH6EjN+nm2g1WA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/collection": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-visible": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/listbox/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/listbox/node_modules/@zag-js/focus-visible": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.26.1.tgz",
+ "integrity": "sha512-Hq57XwQWS0a5rjiZcgWhC8ca1e75VoqVLaSGn8XM29lv13423MPRtJ6b/zkEx5G4yZmddgA+wFh2/U2KPztcYA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/live-region": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/live-region/-/live-region-1.26.1.tgz",
+ "integrity": "sha512-Z3c2/ssr5ERIVr0sLchua0e/JrPlbIN3suLZh4oYYPcxpKRjhwZQbN66xa5jm0LfIlW/Z21Obrb8X91GFwXR6w==",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/menu": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/menu/-/menu-1.26.1.tgz",
+ "integrity": "sha512-ElFlY9yqea14XUkRXL1WA3t3SGDh+4jBMXZLIG8GY14GOzoTvruATBg1+Sbd5VVpggAbrUui33F/umWgwh6X4w==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/rect-utils": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/menu/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/number-input": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/number-input/-/number-input-1.26.1.tgz",
+ "integrity": "sha512-T3QnhDqKjUNn3eIQvwfOk2AEmJo1q6CrvKl71BfqO9PLOo930RfSBg0SWU16dv6kqGrH5bleRigPEwR6gLkDZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@internationalized/number": "3.6.5",
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/number-input/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/pagination": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/pagination/-/pagination-1.26.1.tgz",
+ "integrity": "sha512-tInkqiMj1+VoFPSN80Y7lS1ABfxTA+xgyjMyx3Y09dgHNhiOKMOYva3eTGIJaEd6OskUayc3TFKqvfT5R43KlQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/pagination/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/password-input": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/password-input/-/password-input-1.26.1.tgz",
+ "integrity": "sha512-XI5M7uHWEX3K4uKYE5sCwm4gOCup5XHAYRO63ELFOZSKKRhPGl1IN8DeLNweDOtBJuab4ZHT2wLKgSxs/BoJLg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/password-input/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/pin-input": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/pin-input/-/pin-input-1.26.1.tgz",
+ "integrity": "sha512-M/vFnCVUQe13Thcz+bYmx3va8yD1kfCaNvMNBb7TzRVrEl/XF+nKdx1IjRi6HmCN/TkWOBCk0Lj/p/dqoALiGg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/pin-input/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/popover": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/popover/-/popover-1.26.1.tgz",
+ "integrity": "sha512-nwZfOa7W8NW7npZXqw898nGIBJ7/sk89jglO9Ealqgay5ypOSGBg4v3Afc188Q9c4jFLLqNLQ/LzUhox+h7oLA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/aria-hidden": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-trap": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/remove-scroll": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/popover/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/popper": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/popper/-/popper-1.26.1.tgz",
+ "integrity": "sha512-wY/YzdXT97gIw8wpPDyU+qf1nlnf6wYwVs3SGDCd6cbgU7iy2jo3Pn6bMJ2OrsFrLZqFVZp6lF2zQtBTNJMZtg==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "1.7.4",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/popper/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/presence": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/presence/-/presence-1.26.1.tgz",
+ "integrity": "sha512-qcbdmwVQdrc4nbHsGTTRBT9UI6lJTmT2ZVv+QQW1ZeegiIEEg/IQAuMHVaPcGGnS2Kec2OJAA174+Br8rZCKtQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/presence/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/progress": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/progress/-/progress-1.26.1.tgz",
+ "integrity": "sha512-NEmLImi7ZvsTQ1B+AAZARsl3IwvdS4+qv9Wpgf+RIjJVCa0CbE3N7XS+sHuI5X4nWAKbP6Kpc3VKPwZ/9dZ7jQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/progress/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/qr-code": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/qr-code/-/qr-code-1.26.1.tgz",
+ "integrity": "sha512-UdFzV65pSVkgzdX6k/zbGwk35GDN3b/WmHVWmOaDgUE0ySyx+Mty97Ho+qomoNVRIoKQ0z5Oshz0qyrEvX131Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1",
+ "proxy-memoize": "3.0.1",
+ "uqr": "0.1.2"
+ }
+ },
+ "node_modules/@zag-js/qr-code/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/radio-group": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/radio-group/-/radio-group-1.26.1.tgz",
+ "integrity": "sha512-85BA4b4h6Dq3Qh9VhlRM49gJUk0NGnEqmd86LctNLXMTMeJQ9i40LMeRVlKJqeDDcXMPQDKsINCfATegq2mj2Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-visible": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/radio-group/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/radio-group/node_modules/@zag-js/focus-visible": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.26.1.tgz",
+ "integrity": "sha512-Hq57XwQWS0a5rjiZcgWhC8ca1e75VoqVLaSGn8XM29lv13423MPRtJ6b/zkEx5G4yZmddgA+wFh2/U2KPztcYA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/rating-group": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/rating-group/-/rating-group-1.26.1.tgz",
+ "integrity": "sha512-bhwqi7c9GtMC+ooO/BiP8NNY1RiMVYhkj6b18CCtkJHrkl+yOB3liqqE5sb7fuVe1A37S7JL+TmAySsRQLkC2g==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/rating-group/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/react": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/react/-/react-1.26.1.tgz",
+ "integrity": "sha512-O9Egcylyqfw1HNGBfBFtzV5MaEvlWCjbsmdPBKbN0oPOQhIGmjPSFgU+Zvyq3IwW4fHcyUJOVgjZy2EVwMDNfA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/core": "1.26.1",
+ "@zag-js/store": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "peerDependencies": {
+ "react": ">=18.0.0",
+ "react-dom": ">=18.0.0"
+ }
+ },
+ "node_modules/@zag-js/rect-utils": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/rect-utils/-/rect-utils-1.26.1.tgz",
+ "integrity": "sha512-ZvO4kyXXfSPrFmVKgHDTSlTagioU5KNE2VhN6tN/uJYVh2M1us2DBIWtZLGZeGSpdcCuHEpThUp1eES7ZVN8ng==",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/remove-scroll": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/remove-scroll/-/remove-scroll-1.26.1.tgz",
+ "integrity": "sha512-m1wVmykWfpvmp3Q3jLArCvojR8SM4/DTH6I5KIZAwgIp9QiI16K83ZTSS7TiVkhwt3SgH72F9oAaJT/HA9ZHnQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/remove-scroll/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/scroll-area": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/scroll-area/-/scroll-area-1.26.1.tgz",
+ "integrity": "sha512-+QzuY/zYzl0ZH5Xf7tLg2nTKt8h3B55lu8yvg7WavqT2nLTMcocK6Vr1r7b+9FpGyt3nMYuZ6iUUU1Rdkk2vwg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/scroll-area/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/scroll-snap": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/scroll-snap/-/scroll-snap-1.26.1.tgz",
+ "integrity": "sha512-fRRvXO0Yl9fMwrjN7zofVcFSQvHEKYRptq4W4lG2DXIKuUrmJwyTLKMREvLka6kRZ420hDfVlTj7PpSPp4OoGg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/scroll-snap/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/select": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/select/-/select-1.26.1.tgz",
+ "integrity": "sha512-posQbGiEXiLHoUeD2mGsuPPd/cSKat99h78krivAEJqFDijPSmX9l8A0o6sXXxWHFje50gqWxSH4p25IKBGQkA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/collection": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/select/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/signature-pad": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/signature-pad/-/signature-pad-1.26.1.tgz",
+ "integrity": "sha512-OCx0EJ9bZ3ePz5AmPxPvSq5nQWSVUQvI4vwRFHwZXULitIycwNm7avfCVSyvCCUj0f6IlgI6SiZDeU68lpNHnA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1",
+ "perfect-freehand": "^1.2.2"
+ }
+ },
+ "node_modules/@zag-js/signature-pad/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/signature-pad/node_modules/perfect-freehand": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/perfect-freehand/-/perfect-freehand-1.2.2.tgz",
+ "integrity": "sha512-eh31l019WICQ03pkF3FSzHxB8n07ItqIQ++G5UV8JX0zVOXzgTGCqnRR0jJ2h9U8/2uW4W4mtGJELt9kEV0CFQ==",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/slider": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/slider/-/slider-1.26.1.tgz",
+ "integrity": "sha512-iHFeugMk9pNZLoijEYeV49h7lLC+twxkpeiTc5KjFgKQB9n8a+H22fIVkl+B+dmIPcfr8tDpri1FfN4hh9kxpA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/slider/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/splitter": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/splitter/-/splitter-1.26.1.tgz",
+ "integrity": "sha512-QMwNOrBQ2FQU82aPkHtnfaHqI9wzJKJj2ZU0CHVRBgK9V9D77VJvtufFU0qP+6x/p5Ba26i2y9AGv2jpDGBs6w==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/splitter/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/steps": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/steps/-/steps-1.26.1.tgz",
+ "integrity": "sha512-EUVpGOdOd/bjG1PiJ0lRZmfdPt7YcqL3y87mS5HZ4ZSyPp8piUOMDy7ZhZvweJB3DScF7FMfmV7ygZTNcq4dLQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/steps/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/store": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/store/-/store-1.26.1.tgz",
+ "integrity": "sha512-0473Z38EVnl6RcjXecevzfxYbzZWEcCqsx+Q3Eti+5LKvSnl05SomiF5dYDd8qPQ167iWAQWhBYSTvasfjKa4w==",
+ "license": "MIT",
+ "dependencies": {
+ "proxy-compare": "3.0.1"
+ }
+ },
+ "node_modules/@zag-js/switch": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/switch/-/switch-1.26.1.tgz",
+ "integrity": "sha512-OfOF2BYBtEeoI4RU0eYTFH3QAORNQBuVtDrsERJuWldLk9p1sukETXooTFxqaQuLRx98J3Y7duryjvTvNyA8nA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-visible": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/switch/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/switch/node_modules/@zag-js/focus-visible": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.26.1.tgz",
+ "integrity": "sha512-Hq57XwQWS0a5rjiZcgWhC8ca1e75VoqVLaSGn8XM29lv13423MPRtJ6b/zkEx5G4yZmddgA+wFh2/U2KPztcYA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/tabs": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/tabs/-/tabs-1.26.1.tgz",
+ "integrity": "sha512-RI3Od0H6guYfflmCmpKO0hrh1FOjE/OduEEiD1XDn5foeD0uV/qhS8Wdh8R3ikgcaVjb5XrSOrCZXkuc732g8w==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/tabs/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/tags-input": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/tags-input/-/tags-input-1.26.1.tgz",
+ "integrity": "sha512-Gjjsq7CQolog1mEjU07hwnTPXQ9jjln35X52EjlsjOuohkzT0TFRDj5Nuf8fqu82k2OcSx8IX09wrdGgxMKklA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/auto-resize": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/interact-outside": "1.26.1",
+ "@zag-js/live-region": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/tags-input/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/timer": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/timer/-/timer-1.26.1.tgz",
+ "integrity": "sha512-+Xi7wtxCD9kjdHNeeNpCENMezWh2ZVO6KfRoLx31PTz1Dm6h457pofsAO0u8LZEpbI3IypTiTYFeaJn3qJtVrw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/timer/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/toast": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/toast/-/toast-1.26.1.tgz",
+ "integrity": "sha512-TLcN9Bd17fI0069VOV7Ug1kGk5feUK38YKJys8/1cujG+Cu4d5iUif/GUJDrRjcI/P6dPVTzrZ9ag+pCzxkWOA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/toast/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/toggle": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/toggle/-/toggle-1.26.1.tgz",
+ "integrity": "sha512-MrwXORUWpe5adyK9ieXt7KsxsBwdaFwUn42IoPLYnw61RS92qd4DPttxENXTpdL1RpqpO/G0piIzeAm7tVB/Yw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/toggle-group": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/toggle-group/-/toggle-group-1.26.1.tgz",
+ "integrity": "sha512-0YXWmK59E+PPxpxj/YYbRY/gP1rVRnJ/hR57XNQykLrl+uYWy16lM3CD9tke3mmLwevdMpC3JwpdPAF9AGVBVw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/toggle-group/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/toggle/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/tooltip": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/tooltip/-/tooltip-1.26.1.tgz",
+ "integrity": "sha512-ezBF4DZYo7E+AjVvpOoXnoPwhSnbS3y6Fp9BMvzQRSn5qElZbdQOEZSI9R6MZBTfEo6syXE68MYyCMzKFpkQFg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-visible": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/tooltip/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/tooltip/node_modules/@zag-js/focus-visible": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.26.1.tgz",
+ "integrity": "sha512-Hq57XwQWS0a5rjiZcgWhC8ca1e75VoqVLaSGn8XM29lv13423MPRtJ6b/zkEx5G4yZmddgA+wFh2/U2KPztcYA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/tour": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/tour/-/tour-1.26.1.tgz",
+ "integrity": "sha512-dNG8+fH6sVUjYsGQ8fO5gHvIZ1temhR3fe4H3lbSjqeb+8FHNXfkM1PbgNkUTmBar4JdEdWU60E/26cChDkxGQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-trap": "1.26.1",
+ "@zag-js/interact-outside": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/tour/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/tree-view": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/tree-view/-/tree-view-1.26.1.tgz",
+ "integrity": "sha512-t+vzJ8EsDO0hAAwYbwQmQqy2aoWRWdUHJKhYk9pU8+tEwU7shepX2kSP3xbxpsXcHih5TBAzSQhGcqXi8rfnlA==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/collection": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/tree-view/node_modules/@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "node_modules/@zag-js/types": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/types/-/types-1.26.1.tgz",
+ "integrity": "sha512-MXRn8x0af7ZVJ50cxCoJU7hLZ3FmPnD53UQnjkYSmOcwr1eE0Wyt7bjGUP1Zv+6hPMTlyZ18XR2rnUkKAtr7/w==",
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "3.1.3"
+ }
+ },
+ "node_modules/@zag-js/utils": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/utils/-/utils-1.26.1.tgz",
+ "integrity": "sha512-OeQia4UV/3osMdrhSa2NmhWvzlnlF1vxOBAdYP5R96ho0FpI15DvAaPQDvE94shzIMgzS4k0pqK5lZWK5FTmqw==",
+ "license": "MIT"
+ },
"node_modules/abab": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
@@ -30960,6 +32459,15 @@
"integrity": "sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA==",
"optional": true
},
+ "node_modules/lucide-react": {
+ "version": "0.503.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.503.0.tgz",
+ "integrity": "sha512-HGGkdlPWQ0vTF8jJ5TdIqhQXZi6uh3LnNgfZ8MHiuxFfX3RZeA79r2MW2tHAZKlAVfoNE8esm3p+O6VkIvpj6w==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/lunr": {
"version": "2.3.9",
"resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
@@ -37845,6 +39353,21 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-compare": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-3.0.1.tgz",
+ "integrity": "sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q==",
+ "license": "MIT"
+ },
+ "node_modules/proxy-memoize": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/proxy-memoize/-/proxy-memoize-3.0.1.tgz",
+ "integrity": "sha512-VDdG/VYtOgdGkWJx7y0o7p+zArSf2383Isci8C+BP3YXgMYDoPd3cCBjw0JdWb6YBb9sFiOPbAADDVTPJnh+9g==",
+ "license": "MIT",
+ "dependencies": {
+ "proxy-compare": "^3.0.0"
+ }
+ },
"node_modules/prr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
@@ -40846,6 +42369,22 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/shiki": {
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.13.0.tgz",
+ "integrity": "sha512-aZW4l8Og16CokuCLf8CF8kq+KK2yOygapU5m3+hoGw0Mdosc6fPitjM+ujYarppj5ZIKGyPDPP1vqmQhr+5/0g==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/core": "3.13.0",
+ "@shikijs/engine-javascript": "3.13.0",
+ "@shikijs/engine-oniguruma": "3.13.0",
+ "@shikijs/langs": "3.13.0",
+ "@shikijs/themes": "3.13.0",
+ "@shikijs/types": "3.13.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
"node_modules/side-channel": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
@@ -42665,9 +44204,9 @@
}
},
"node_modules/tslib": {
- "version": "2.6.3",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
- "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
"node_modules/tunnel-rat": {
@@ -43643,6 +45182,12 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
+ "node_modules/uqr": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/uqr/-/uqr-0.1.2.tgz",
+ "integrity": "sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==",
+ "license": "MIT"
+ },
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -46294,6 +47839,7 @@
"version": "0.37.0",
"license": "MIT",
"dependencies": {
+ "@lexical/extension": "0.37.0",
"@lexical/html": "0.37.0",
"@lexical/list": "0.37.0",
"@lexical/selection": "0.37.0",
@@ -46332,21 +47878,6 @@
"@shikijs/types": "^3.7.0"
}
},
- "packages/lexical-code-shiki/node_modules/shiki": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.7.0.tgz",
- "integrity": "sha512-ZcI4UT9n6N2pDuM2n3Jbk0sR4Swzq43nLPgS/4h0E3B/NrFn2HKElrDtceSf8Zx/OWYOo7G1SAtBLypCp+YXqg==",
- "dependencies": {
- "@shikijs/core": "3.7.0",
- "@shikijs/engine-javascript": "3.7.0",
- "@shikijs/engine-oniguruma": "3.7.0",
- "@shikijs/langs": "3.7.0",
- "@shikijs/themes": "3.7.0",
- "@shikijs/types": "3.7.0",
- "@shikijs/vscode-textmate": "^10.0.2",
- "@types/hast": "^3.0.4"
- }
- },
"packages/lexical-devtools": {
"name": "@lexical/devtools",
"version": "0.37.0",
@@ -46473,6 +48004,7 @@
"version": "0.37.0",
"license": "MIT",
"dependencies": {
+ "@lexical/extension": "0.37.0",
"@lexical/selection": "0.37.0",
"@lexical/utils": "0.37.0",
"lexical": "0.37.0"
@@ -47330,6 +48862,84 @@
"resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-8.1.1.tgz",
"integrity": "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ=="
},
+ "@ark-ui/react": {
+ "version": "5.26.0",
+ "resolved": "https://registry.npmjs.org/@ark-ui/react/-/react-5.26.0.tgz",
+ "integrity": "sha512-SxuGfRNEu+Y9A8ixR8RJevS0RAg0hInMkhFD47X/8pFjYCdajSm6C+Pv23eDLpldV7SNFXEDUfU6wEkont/NGw==",
+ "requires": {
+ "@internationalized/date": "3.10.0",
+ "@zag-js/accordion": "1.26.1",
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/angle-slider": "1.26.1",
+ "@zag-js/async-list": "1.26.1",
+ "@zag-js/auto-resize": "1.26.1",
+ "@zag-js/avatar": "1.26.1",
+ "@zag-js/bottom-sheet": "1.26.1",
+ "@zag-js/carousel": "1.26.1",
+ "@zag-js/checkbox": "1.26.1",
+ "@zag-js/clipboard": "1.26.1",
+ "@zag-js/collapsible": "1.26.1",
+ "@zag-js/collection": "1.26.1",
+ "@zag-js/color-picker": "1.26.1",
+ "@zag-js/color-utils": "1.26.1",
+ "@zag-js/combobox": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/date-picker": "1.26.1",
+ "@zag-js/date-utils": "1.26.1",
+ "@zag-js/dialog": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/editable": "1.26.1",
+ "@zag-js/file-upload": "1.26.1",
+ "@zag-js/file-utils": "1.26.1",
+ "@zag-js/floating-panel": "1.26.1",
+ "@zag-js/focus-trap": "1.26.1",
+ "@zag-js/highlight-word": "1.26.1",
+ "@zag-js/hover-card": "1.26.1",
+ "@zag-js/i18n-utils": "1.26.1",
+ "@zag-js/json-tree-utils": "1.26.1",
+ "@zag-js/listbox": "1.26.1",
+ "@zag-js/menu": "1.26.1",
+ "@zag-js/number-input": "1.26.1",
+ "@zag-js/pagination": "1.26.1",
+ "@zag-js/password-input": "1.26.1",
+ "@zag-js/pin-input": "1.26.1",
+ "@zag-js/popover": "1.26.1",
+ "@zag-js/presence": "1.26.1",
+ "@zag-js/progress": "1.26.1",
+ "@zag-js/qr-code": "1.26.1",
+ "@zag-js/radio-group": "1.26.1",
+ "@zag-js/rating-group": "1.26.1",
+ "@zag-js/react": "1.26.1",
+ "@zag-js/scroll-area": "1.26.1",
+ "@zag-js/select": "1.26.1",
+ "@zag-js/signature-pad": "1.26.1",
+ "@zag-js/slider": "1.26.1",
+ "@zag-js/splitter": "1.26.1",
+ "@zag-js/steps": "1.26.1",
+ "@zag-js/switch": "1.26.1",
+ "@zag-js/tabs": "1.26.1",
+ "@zag-js/tags-input": "1.26.1",
+ "@zag-js/timer": "1.26.1",
+ "@zag-js/toast": "1.26.1",
+ "@zag-js/toggle": "1.26.1",
+ "@zag-js/toggle-group": "1.26.1",
+ "@zag-js/tooltip": "1.26.1",
+ "@zag-js/tour": "1.26.1",
+ "@zag-js/tree-view": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
"@babel/code-frame": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
@@ -51736,46 +53346,6 @@
"@shikijs/themes": "^3.12.2",
"@shikijs/types": "^3.12.2",
"@shikijs/vscode-textmate": "^10.0.2"
- },
- "dependencies": {
- "@shikijs/engine-oniguruma": {
- "version": "3.12.2",
- "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.12.2.tgz",
- "integrity": "sha512-hozwnFHsLvujK4/CPVHNo3Bcg2EsnG8krI/ZQ2FlBlCRpPZW4XAEQmEwqegJsypsTAN9ehu2tEYe30lYKSZW/w==",
- "dev": true,
- "requires": {
- "@shikijs/types": "3.12.2",
- "@shikijs/vscode-textmate": "^10.0.2"
- }
- },
- "@shikijs/langs": {
- "version": "3.12.2",
- "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.12.2.tgz",
- "integrity": "sha512-bVx5PfuZHDSHoBal+KzJZGheFuyH4qwwcwG/n+MsWno5cTlKmaNtTsGzJpHYQ8YPbB5BdEdKU1rga5/6JGY8ww==",
- "dev": true,
- "requires": {
- "@shikijs/types": "3.12.2"
- }
- },
- "@shikijs/themes": {
- "version": "3.12.2",
- "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.12.2.tgz",
- "integrity": "sha512-fTR3QAgnwYpfGczpIbzPjlRnxyONJOerguQv1iwpyQZ9QXX4qy/XFQqXlf17XTsorxnHoJGbH/LXBvwtqDsF5A==",
- "dev": true,
- "requires": {
- "@shikijs/types": "3.12.2"
- }
- },
- "@shikijs/types": {
- "version": "3.12.2",
- "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.12.2.tgz",
- "integrity": "sha512-K5UIBzxCyv0YoxN3LMrKB9zuhp1bV+LgewxuVwHdl4Gz5oePoUFrr9EfgJlGlDeXCU1b/yhdnXeuRvAnz8HN8Q==",
- "dev": true,
- "requires": {
- "@shikijs/vscode-textmate": "^10.0.2",
- "@types/hast": "^3.0.4"
- }
- }
}
},
"@hapi/hoek": {
@@ -51849,6 +53419,22 @@
}
}
},
+ "@internationalized/date": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.10.0.tgz",
+ "integrity": "sha512-oxDR/NTEJ1k+UFVQElaNIk65E/Z83HK1z1WI3lQyhTtnNg4R5oVXaPzK3jcpKG8UHKDVuDQHzn+wsxSz8RP3aw==",
+ "requires": {
+ "@swc/helpers": "^0.5.0"
+ }
+ },
+ "@internationalized/number": {
+ "version": "3.6.5",
+ "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.5.tgz",
+ "integrity": "sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g==",
+ "requires": {
+ "@swc/helpers": "^0.5.0"
+ }
+ },
"@isaacs/balanced-match": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
@@ -52564,6 +54150,7 @@
"@lexical/clipboard": {
"version": "file:packages/lexical-clipboard",
"requires": {
+ "@lexical/extension": "0.37.0",
"@lexical/html": "0.37.0",
"@lexical/list": "0.37.0",
"@lexical/selection": "0.37.0",
@@ -52592,22 +54179,42 @@
"@shikijs/types": "^3.7.0",
"lexical": "0.37.0",
"shiki": "^3.7.0"
+ }
+ },
+ "@lexical/dev-node-state-style-example": {
+ "version": "file:examples/dev-node-state-style",
+ "requires": {
+ "@ark-ui/react": "^5.6.0",
+ "@lexical/clipboard": "0.37.0",
+ "@lexical/extension": "0.37.0",
+ "@lexical/history": "0.37.0",
+ "@lexical/html": "0.37.0",
+ "@lexical/react": "0.37.0",
+ "@lexical/rich-text": "0.37.0",
+ "@lexical/selection": "0.37.0",
+ "@lexical/utils": "0.37.0",
+ "@shikijs/langs": "^3.3.0",
+ "@shikijs/themes": "^3.3.0",
+ "@types/react": "^19.1.2",
+ "@types/react-dom": "^19.1.2",
+ "@vitejs/plugin-react": "^5.0.2",
+ "cross-env": "^7.0.3",
+ "csstype": "^3.1.3",
+ "inline-style-parser": "^0.2.4",
+ "lexical": "0.37.0",
+ "lucide-react": "^0.503.0",
+ "prettier": "^3.5.3",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0",
+ "shiki": "^3.3.0",
+ "typescript": "^5.9.2",
+ "vite": "^7.1.4"
},
"dependencies": {
- "shiki": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.7.0.tgz",
- "integrity": "sha512-ZcI4UT9n6N2pDuM2n3Jbk0sR4Swzq43nLPgS/4h0E3B/NrFn2HKElrDtceSf8Zx/OWYOo7G1SAtBLypCp+YXqg==",
- "requires": {
- "@shikijs/core": "3.7.0",
- "@shikijs/engine-javascript": "3.7.0",
- "@shikijs/engine-oniguruma": "3.7.0",
- "@shikijs/langs": "3.7.0",
- "@shikijs/themes": "3.7.0",
- "@shikijs/types": "3.7.0",
- "@shikijs/vscode-textmate": "^10.0.2",
- "@types/hast": "^3.0.4"
- }
+ "inline-style-parser": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.6.tgz",
+ "integrity": "sha512-gtGXVaBdl5mAes3rPcMedEBm12ibjt1kDMFfheul1wUAOVEJW60voNdMVzVkfLN06O7ZaD/rxhfKgtlgtTbMjg=="
}
}
},
@@ -52704,6 +54311,7 @@
"@lexical/html": {
"version": "file:packages/lexical-html",
"requires": {
+ "@lexical/extension": "0.37.0",
"@lexical/selection": "0.37.0",
"@lexical/utils": "0.37.0",
"lexical": "0.37.0"
@@ -54508,55 +56116,55 @@
"integrity": "sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w=="
},
"@shikijs/core": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.7.0.tgz",
- "integrity": "sha512-yilc0S9HvTPyahHpcum8eonYrQtmGTU0lbtwxhA6jHv4Bm1cAdlPFRCJX4AHebkCm75aKTjjRAW+DezqD1b/cg==",
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.13.0.tgz",
+ "integrity": "sha512-3P8rGsg2Eh2qIHekwuQjzWhKI4jV97PhvYjYUzGqjvJfqdQPz+nMlfWahU24GZAyW1FxFI1sYjyhfh5CoLmIUA==",
"requires": {
- "@shikijs/types": "3.7.0",
+ "@shikijs/types": "3.13.0",
"@shikijs/vscode-textmate": "^10.0.2",
"@types/hast": "^3.0.4",
"hast-util-to-html": "^9.0.5"
}
},
"@shikijs/engine-javascript": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.7.0.tgz",
- "integrity": "sha512-0t17s03Cbv+ZcUvv+y33GtX75WBLQELgNdVghnsdhTgU3hVcWcMsoP6Lb0nDTl95ZJfbP1mVMO0p3byVh3uuzA==",
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.13.0.tgz",
+ "integrity": "sha512-Ty7xv32XCp8u0eQt8rItpMs6rU9Ki6LJ1dQOW3V/56PKDcpvfHPnYFbsx5FFUP2Yim34m/UkazidamMNVR4vKg==",
"requires": {
- "@shikijs/types": "3.7.0",
+ "@shikijs/types": "3.13.0",
"@shikijs/vscode-textmate": "^10.0.2",
"oniguruma-to-es": "^4.3.3"
}
},
"@shikijs/engine-oniguruma": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.7.0.tgz",
- "integrity": "sha512-5BxcD6LjVWsGu4xyaBC5bu8LdNgPCVBnAkWTtOCs/CZxcB22L8rcoWfv7Hh/3WooVjBZmFtyxhgvkQFedPGnFw==",
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.13.0.tgz",
+ "integrity": "sha512-O42rBGr4UDSlhT2ZFMxqM7QzIU+IcpoTMzb3W7AlziI1ZF7R8eS2M0yt5Ry35nnnTX/LTLXFPUjRFCIW+Operg==",
"requires": {
- "@shikijs/types": "3.7.0",
+ "@shikijs/types": "3.13.0",
"@shikijs/vscode-textmate": "^10.0.2"
}
},
"@shikijs/langs": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.7.0.tgz",
- "integrity": "sha512-1zYtdfXLr9xDKLTGy5kb7O0zDQsxXiIsw1iIBcNOO8Yi5/Y1qDbJ+0VsFoqTlzdmneO8Ij35g7QKF8kcLyznCQ==",
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.13.0.tgz",
+ "integrity": "sha512-672c3WAETDYHwrRP0yLy3W1QYB89Hbpj+pO4KhxK6FzIrDI2FoEXNiNCut6BQmEApYLfuYfpgOZaqbY+E9b8wQ==",
"requires": {
- "@shikijs/types": "3.7.0"
+ "@shikijs/types": "3.13.0"
}
},
"@shikijs/themes": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.7.0.tgz",
- "integrity": "sha512-VJx8497iZPy5zLiiCTSIaOChIcKQwR0FebwE9S3rcN0+J/GTWwQ1v/bqhTbpbY3zybPKeO8wdammqkpXc4NVjQ==",
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.13.0.tgz",
+ "integrity": "sha512-Vxw1Nm1/Od8jyA7QuAenaV78BG2nSr3/gCGdBkLpfLscddCkzkL36Q5b67SrLLfvAJTOUzW39x4FHVCFriPVgg==",
"requires": {
- "@shikijs/types": "3.7.0"
+ "@shikijs/types": "3.13.0"
}
},
"@shikijs/types": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.7.0.tgz",
- "integrity": "sha512-MGaLeaRlSWpnP0XSAum3kP3a8vtcTsITqoEPYdt3lQG3YCdQH4DnEhodkYcNMcU0uW0RffhoD1O3e0vG5eSBBg==",
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.13.0.tgz",
+ "integrity": "sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw==",
"requires": {
"@shikijs/vscode-textmate": "^10.0.2",
"@types/hast": "^3.0.4"
@@ -54881,6 +56489,14 @@
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
"integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="
},
+ "@swc/helpers": {
+ "version": "0.5.17",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz",
+ "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==",
+ "requires": {
+ "tslib": "^2.8.0"
+ }
+ },
"@swc/html": {
"version": "1.13.20",
"resolved": "https://registry.npmjs.org/@swc/html/-/html-1.13.20.tgz",
@@ -56896,16 +58512,518 @@
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
},
+ "@zag-js/accordion": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/accordion/-/accordion-1.26.1.tgz",
+ "integrity": "sha512-Rqp5zPyWn7w1D2teZAlLytK7okRjfdU4qLuwO7SPdXgeqxr+bn7qP9Bxs4NU78nySA8ZbLZqPbmTA31m9Ya6lw==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/anatomy": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/anatomy/-/anatomy-1.26.1.tgz",
+ "integrity": "sha512-1GVk5D/gFTvBd06w3MgDkSUGtUyU5n6XL8G6KsmuIh6dq16MgZ0TnDsUOkPVBQL3YEiHqlJfeCS6zkgcsu3q2g=="
+ },
+ "@zag-js/angle-slider": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/angle-slider/-/angle-slider-1.26.1.tgz",
+ "integrity": "sha512-fdT6caDvT8ECyszhV6NN9CfCK5OJNK/0/456nYRclHIzrrRZdQL1ZJhSGKrZhrFM2TbEQIf/qrgoPCK3J4/GCg==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/rect-utils": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/aria-hidden": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/aria-hidden/-/aria-hidden-1.26.1.tgz",
+ "integrity": "sha512-8zZQDODCfXuJ0zfsx6+WVaYh+ScQoFG2ib2FvKr9sxztoJAn1hiLYFKzzlA1aWOxTAh+dFQC/jJI+C1nWbhBkQ==",
+ "requires": {
+ "@zag-js/dom-query": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/async-list": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/async-list/-/async-list-1.26.1.tgz",
+ "integrity": "sha512-jzgypjD/2tx90EIhb8MnjXjd6A//Veiba5NJkAfxAYsr++tG1K/aTNARBPfTunRJq6ZjDoNSZWubjaNX+llD2g==",
+ "requires": {
+ "@zag-js/core": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "@zag-js/auto-resize": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/auto-resize/-/auto-resize-1.26.1.tgz",
+ "integrity": "sha512-/t53ykgDOttYzroQQUgJqyOb+xlKClI5T1aJe/d7HOvGFqJtSSOYB9ZOJmywpkN9/11nYdH7HaZtSGmRjCQBzw==",
+ "requires": {
+ "@zag-js/dom-query": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/avatar": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/avatar/-/avatar-1.26.1.tgz",
+ "integrity": "sha512-s34+KSqv/frY3W4Ng9uuuqQbVlgpeWG8b0CtGcELUw9VSldDSOE2ZMIZ1inFLoby9vOOovttHSd/QdGseXkFqQ==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/bottom-sheet": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/bottom-sheet/-/bottom-sheet-1.26.1.tgz",
+ "integrity": "sha512-Vroa6ivzSikSdYmX/Km88g/z7W7LNEBFnYAUMSCpRb/QFStRdbVPd7POzV27sCZfoKmUONYqGCBNs3g29DAGrQ==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/aria-hidden": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-trap": "1.26.1",
+ "@zag-js/remove-scroll": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/carousel": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/carousel/-/carousel-1.26.1.tgz",
+ "integrity": "sha512-hwxO1p+fsGpu+b8ufxdQAO2UhfP1jUugmBoYnaT3eQJ7Xl/E3MuJ3OMdxgeM9zbBRZuv7IWXVzfLQTNB1lz78g==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/scroll-snap": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/checkbox": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/checkbox/-/checkbox-1.26.1.tgz",
+ "integrity": "sha512-IESEO/WfQ6o45E8beCIOdg0u8tmgSF9gb2F0S1HNBSTmeTq5KSaz47Z8SDkci0g9cw2i+OZIX7BPZI4XpbT3tg==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-visible": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "@zag-js/focus-visible": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.26.1.tgz",
+ "integrity": "sha512-Hq57XwQWS0a5rjiZcgWhC8ca1e75VoqVLaSGn8XM29lv13423MPRtJ6b/zkEx5G4yZmddgA+wFh2/U2KPztcYA==",
+ "requires": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/clipboard": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/clipboard/-/clipboard-1.26.1.tgz",
+ "integrity": "sha512-1yWTvFELfkRoM9GUjscU0Dl3CsLmXHzRyKttYY478xiL9jOKLaJfg6R0c42HJIXqfgIf7shG1aNOse4qmR266Q==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/collapsible": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/collapsible/-/collapsible-1.26.1.tgz",
+ "integrity": "sha512-B8zMtX508R71mpOunB25DXFaeXJEX1n38eOq0kUuGyggmoJdOMwLPCuzo9L9ETROynOcPwJ5YzMnhAkw7kjaBg==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/collection": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/collection/-/collection-1.26.1.tgz",
+ "integrity": "sha512-b23L4urNhCCH89TRr5UIWZsCtV9eaBhgTPu91qO2CAgz0fbvmkZJ/E5yr7EI4KeNg0xExbiQrhinZQt2v0LjCA==",
+ "requires": {
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "@zag-js/color-picker": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/color-picker/-/color-picker-1.26.1.tgz",
+ "integrity": "sha512-c3Y9RCBYqXb4HhzxZIhcNQkG4Vpr/gQa86lbxF7JnrGRCB0CyurRxhTSALZGAOKV7/VovnJEaJYDiYtQz5nGCQ==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/color-utils": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/color-utils": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/color-utils/-/color-utils-1.26.1.tgz",
+ "integrity": "sha512-umTm464gTqMRHm3OPNkGDlb65yRlF1Ka4HrMe8eGo3l1AbQipiYE0WJf/aupUuwzm+CXKi244F1lYVnHesXHPQ==",
+ "requires": {
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "@zag-js/combobox": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/combobox/-/combobox-1.26.1.tgz",
+ "integrity": "sha512-VLTTLvzgurvYrsg7UEb11Ad0ZPxWp3ui9/+J3rzgrTMEuLWj8mPfWT0i0l3AG+ruyFlQv5aZNvA/pupk3UK1Tg==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/aria-hidden": "1.26.1",
+ "@zag-js/collection": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/core": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/core/-/core-1.26.1.tgz",
+ "integrity": "sha512-JesW6C1dlrG36Aa+yteL0v5nt4Zqa9n9coqDJUQ9L1AYWzjz6NTHubsA7ysJlTKwl411gSsssmH9Ey5sRxFEWQ==",
+ "requires": {
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/date-picker": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/date-picker/-/date-picker-1.26.1.tgz",
+ "integrity": "sha512-dh105RY/SKXa0iPDmIH5qpXZ1W/Ls+AU0d2l5phcEsVItbgE+FBKYTSuC91w+LNv+MpGPH+PXvatt10tW6SYGA==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/date-utils": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/live-region": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/date-utils": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/date-utils/-/date-utils-1.26.1.tgz",
+ "integrity": "sha512-nMTSfIk0B7MfOIJ0EpFFrHHOGDEI/F0OCG9LVvkwlKZ3evKmgAT5Hw18h2FbQ8ovQ9gNbWoUGPPnrnZJtkzhNw=="
+ },
+ "@zag-js/dialog": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dialog/-/dialog-1.26.1.tgz",
+ "integrity": "sha512-kbNzTIMUkn19RcqDKF+3kH5cGPW3bY2FKiw6qtPi072SshHQtuAeE4g5K3wGFdSTJXHBhXYSK04ZR+ok00YbGA==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/aria-hidden": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-trap": "1.26.1",
+ "@zag-js/remove-scroll": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/dismissable": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dismissable/-/dismissable-1.26.1.tgz",
+ "integrity": "sha512-n7MdvInqfOh+UJ+VpeIovVU734vf8ekHhfhIugDt41xAzndZW8hdXcBsKnDFK0uY9OVk8cq5FRqpdzhoZuZSgw==",
+ "requires": {
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/interact-outside": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
"@zag-js/dom-query": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-0.16.0.tgz",
"integrity": "sha512-Oqhd6+biWyKnhKwFFuZrrf6lxBz2tX2pRQe6grUnYwO6HJ8BcbqZomy2lpOdr+3itlaUqx+Ywj5E5ZZDr/LBfQ=="
},
+ "@zag-js/editable": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/editable/-/editable-1.26.1.tgz",
+ "integrity": "sha512-/QBKunz9PJvd26b/ZfHSktrXWI2oHp8U9+MDVQasQnpEbG5HEGkXw6Ew3y4v/Rfq4Ih3iUSVdAMmyMU7XpYZ7g==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/interact-outside": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
"@zag-js/element-size": {
"version": "0.10.5",
"resolved": "https://registry.npmjs.org/@zag-js/element-size/-/element-size-0.10.5.tgz",
"integrity": "sha512-uQre5IidULANvVkNOBQ1tfgwTQcGl4hliPSe69Fct1VfYb2Fd0jdAcGzqQgPhfrXFpR62MxLPB7erxJ/ngtL8w=="
},
+ "@zag-js/file-upload": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/file-upload/-/file-upload-1.26.1.tgz",
+ "integrity": "sha512-fu6UpK8+qj98g2h3XrFqWzaSD5JHNt71qEg6hlYCwsXdcpYhTObps9YsTKo4sd/XGVh0lriyzSIsjBUeoctR6A==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/file-utils": "1.26.1",
+ "@zag-js/i18n-utils": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/file-utils": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/file-utils/-/file-utils-1.26.1.tgz",
+ "integrity": "sha512-JW0vr7fzDDi9GEQLmGWSiBbNlSK8FQ/W+tavk0E4LNVb2Hs28/4F1XQXYKNuzfN+CoBYI74EIasb7rublozJMA==",
+ "requires": {
+ "@zag-js/i18n-utils": "1.26.1"
+ }
+ },
+ "@zag-js/floating-panel": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/floating-panel/-/floating-panel-1.26.1.tgz",
+ "integrity": "sha512-45fVFASBxM+Lj6nvq4LjlCSl/JuBwzPchv8LYfR4hRHFNUuoNpQ2MDQMFJuMzxCk50U2FAa2R0QXvi3aniEJwA==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/rect-utils": "1.26.1",
+ "@zag-js/store": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/focus-trap": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/focus-trap/-/focus-trap-1.26.1.tgz",
+ "integrity": "sha512-88NvG1vxga/Umx54p9K6+nkrC5QLOA/hc5FV68eMKn83u1PCCH8U2+RV/vhMJ7IUTEwI0VTZLOmDfyfbkfomTQ==",
+ "requires": {
+ "@zag-js/dom-query": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
"@zag-js/focus-visible": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-0.16.0.tgz",
@@ -56914,6 +59032,856 @@
"@zag-js/dom-query": "0.16.0"
}
},
+ "@zag-js/highlight-word": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/highlight-word/-/highlight-word-1.26.1.tgz",
+ "integrity": "sha512-xHEeUX8Qhie+tYUBdiR2GllrVpR4gqPCOHoI8HmH/8dWgUqFScRk9BFpR2/HetV9CrURsdjT4Za0mbGaJOssag=="
+ },
+ "@zag-js/hover-card": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/hover-card/-/hover-card-1.26.1.tgz",
+ "integrity": "sha512-Qmd6FY51JsUAxLFQEkbeNCsvzLRL2YX75EupFqNdBPL509yEJkFa1ASry6usgUZgpgMlNP9PrjFIwywyDa8gFw==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/i18n-utils": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/i18n-utils/-/i18n-utils-1.26.1.tgz",
+ "integrity": "sha512-bvzfdsiY4taqZA/QfgqofsynlJGoJGmtmV5zKcVdyTJRVQz04vSEIJ+bzEDpiqK0FtrOI2mOq3Ixmv8fKNRxlQ==",
+ "requires": {
+ "@zag-js/dom-query": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/interact-outside": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/interact-outside/-/interact-outside-1.26.1.tgz",
+ "integrity": "sha512-Kxyg8AuJq4WssVbFyCtY14O611DU7UEiKgDwiNBXdQ5V+XXd4BBBwrA5QK9pk/qjgxZawKOalwjcYsyWhFbwLQ==",
+ "requires": {
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/json-tree-utils": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/json-tree-utils/-/json-tree-utils-1.26.1.tgz",
+ "integrity": "sha512-E3IDz6DgSZPJ6rKWoOARqicF9PMK5avUoqcDsQTsAM/z1SqQT1/++dzYpJ8r9rBej5n5rH1mhr+e5PmbkI5b5A=="
+ },
+ "@zag-js/listbox": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/listbox/-/listbox-1.26.1.tgz",
+ "integrity": "sha512-Xqeb/PO4Yrj87RwP/X357ilLmrEgBIqHy/1lYnVwEVQI8l2TvElRe95oAXGORnqWRM1H0dtoNH6EjN+nm2g1WA==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/collection": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-visible": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "@zag-js/focus-visible": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.26.1.tgz",
+ "integrity": "sha512-Hq57XwQWS0a5rjiZcgWhC8ca1e75VoqVLaSGn8XM29lv13423MPRtJ6b/zkEx5G4yZmddgA+wFh2/U2KPztcYA==",
+ "requires": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/live-region": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/live-region/-/live-region-1.26.1.tgz",
+ "integrity": "sha512-Z3c2/ssr5ERIVr0sLchua0e/JrPlbIN3suLZh4oYYPcxpKRjhwZQbN66xa5jm0LfIlW/Z21Obrb8X91GFwXR6w=="
+ },
+ "@zag-js/menu": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/menu/-/menu-1.26.1.tgz",
+ "integrity": "sha512-ElFlY9yqea14XUkRXL1WA3t3SGDh+4jBMXZLIG8GY14GOzoTvruATBg1+Sbd5VVpggAbrUui33F/umWgwh6X4w==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/rect-utils": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/number-input": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/number-input/-/number-input-1.26.1.tgz",
+ "integrity": "sha512-T3QnhDqKjUNn3eIQvwfOk2AEmJo1q6CrvKl71BfqO9PLOo930RfSBg0SWU16dv6kqGrH5bleRigPEwR6gLkDZQ==",
+ "requires": {
+ "@internationalized/number": "3.6.5",
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/pagination": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/pagination/-/pagination-1.26.1.tgz",
+ "integrity": "sha512-tInkqiMj1+VoFPSN80Y7lS1ABfxTA+xgyjMyx3Y09dgHNhiOKMOYva3eTGIJaEd6OskUayc3TFKqvfT5R43KlQ==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/password-input": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/password-input/-/password-input-1.26.1.tgz",
+ "integrity": "sha512-XI5M7uHWEX3K4uKYE5sCwm4gOCup5XHAYRO63ELFOZSKKRhPGl1IN8DeLNweDOtBJuab4ZHT2wLKgSxs/BoJLg==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/pin-input": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/pin-input/-/pin-input-1.26.1.tgz",
+ "integrity": "sha512-M/vFnCVUQe13Thcz+bYmx3va8yD1kfCaNvMNBb7TzRVrEl/XF+nKdx1IjRi6HmCN/TkWOBCk0Lj/p/dqoALiGg==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/popover": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/popover/-/popover-1.26.1.tgz",
+ "integrity": "sha512-nwZfOa7W8NW7npZXqw898nGIBJ7/sk89jglO9Ealqgay5ypOSGBg4v3Afc188Q9c4jFLLqNLQ/LzUhox+h7oLA==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/aria-hidden": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-trap": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/remove-scroll": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/popper": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/popper/-/popper-1.26.1.tgz",
+ "integrity": "sha512-wY/YzdXT97gIw8wpPDyU+qf1nlnf6wYwVs3SGDCd6cbgU7iy2jo3Pn6bMJ2OrsFrLZqFVZp6lF2zQtBTNJMZtg==",
+ "requires": {
+ "@floating-ui/dom": "1.7.4",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/presence": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/presence/-/presence-1.26.1.tgz",
+ "integrity": "sha512-qcbdmwVQdrc4nbHsGTTRBT9UI6lJTmT2ZVv+QQW1ZeegiIEEg/IQAuMHVaPcGGnS2Kec2OJAA174+Br8rZCKtQ==",
+ "requires": {
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/progress": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/progress/-/progress-1.26.1.tgz",
+ "integrity": "sha512-NEmLImi7ZvsTQ1B+AAZARsl3IwvdS4+qv9Wpgf+RIjJVCa0CbE3N7XS+sHuI5X4nWAKbP6Kpc3VKPwZ/9dZ7jQ==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/qr-code": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/qr-code/-/qr-code-1.26.1.tgz",
+ "integrity": "sha512-UdFzV65pSVkgzdX6k/zbGwk35GDN3b/WmHVWmOaDgUE0ySyx+Mty97Ho+qomoNVRIoKQ0z5Oshz0qyrEvX131Q==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1",
+ "proxy-memoize": "3.0.1",
+ "uqr": "0.1.2"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/radio-group": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/radio-group/-/radio-group-1.26.1.tgz",
+ "integrity": "sha512-85BA4b4h6Dq3Qh9VhlRM49gJUk0NGnEqmd86LctNLXMTMeJQ9i40LMeRVlKJqeDDcXMPQDKsINCfATegq2mj2Q==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-visible": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "@zag-js/focus-visible": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.26.1.tgz",
+ "integrity": "sha512-Hq57XwQWS0a5rjiZcgWhC8ca1e75VoqVLaSGn8XM29lv13423MPRtJ6b/zkEx5G4yZmddgA+wFh2/U2KPztcYA==",
+ "requires": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/rating-group": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/rating-group/-/rating-group-1.26.1.tgz",
+ "integrity": "sha512-bhwqi7c9GtMC+ooO/BiP8NNY1RiMVYhkj6b18CCtkJHrkl+yOB3liqqE5sb7fuVe1A37S7JL+TmAySsRQLkC2g==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/react": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/react/-/react-1.26.1.tgz",
+ "integrity": "sha512-O9Egcylyqfw1HNGBfBFtzV5MaEvlWCjbsmdPBKbN0oPOQhIGmjPSFgU+Zvyq3IwW4fHcyUJOVgjZy2EVwMDNfA==",
+ "requires": {
+ "@zag-js/core": "1.26.1",
+ "@zag-js/store": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ }
+ },
+ "@zag-js/rect-utils": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/rect-utils/-/rect-utils-1.26.1.tgz",
+ "integrity": "sha512-ZvO4kyXXfSPrFmVKgHDTSlTagioU5KNE2VhN6tN/uJYVh2M1us2DBIWtZLGZeGSpdcCuHEpThUp1eES7ZVN8ng=="
+ },
+ "@zag-js/remove-scroll": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/remove-scroll/-/remove-scroll-1.26.1.tgz",
+ "integrity": "sha512-m1wVmykWfpvmp3Q3jLArCvojR8SM4/DTH6I5KIZAwgIp9QiI16K83ZTSS7TiVkhwt3SgH72F9oAaJT/HA9ZHnQ==",
+ "requires": {
+ "@zag-js/dom-query": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/scroll-area": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/scroll-area/-/scroll-area-1.26.1.tgz",
+ "integrity": "sha512-+QzuY/zYzl0ZH5Xf7tLg2nTKt8h3B55lu8yvg7WavqT2nLTMcocK6Vr1r7b+9FpGyt3nMYuZ6iUUU1Rdkk2vwg==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/scroll-snap": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/scroll-snap/-/scroll-snap-1.26.1.tgz",
+ "integrity": "sha512-fRRvXO0Yl9fMwrjN7zofVcFSQvHEKYRptq4W4lG2DXIKuUrmJwyTLKMREvLka6kRZ420hDfVlTj7PpSPp4OoGg==",
+ "requires": {
+ "@zag-js/dom-query": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/select": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/select/-/select-1.26.1.tgz",
+ "integrity": "sha512-posQbGiEXiLHoUeD2mGsuPPd/cSKat99h78krivAEJqFDijPSmX9l8A0o6sXXxWHFje50gqWxSH4p25IKBGQkA==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/collection": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/signature-pad": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/signature-pad/-/signature-pad-1.26.1.tgz",
+ "integrity": "sha512-OCx0EJ9bZ3ePz5AmPxPvSq5nQWSVUQvI4vwRFHwZXULitIycwNm7avfCVSyvCCUj0f6IlgI6SiZDeU68lpNHnA==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1",
+ "perfect-freehand": "^1.2.2"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "perfect-freehand": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/perfect-freehand/-/perfect-freehand-1.2.2.tgz",
+ "integrity": "sha512-eh31l019WICQ03pkF3FSzHxB8n07ItqIQ++G5UV8JX0zVOXzgTGCqnRR0jJ2h9U8/2uW4W4mtGJELt9kEV0CFQ=="
+ }
+ }
+ },
+ "@zag-js/slider": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/slider/-/slider-1.26.1.tgz",
+ "integrity": "sha512-iHFeugMk9pNZLoijEYeV49h7lLC+twxkpeiTc5KjFgKQB9n8a+H22fIVkl+B+dmIPcfr8tDpri1FfN4hh9kxpA==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/splitter": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/splitter/-/splitter-1.26.1.tgz",
+ "integrity": "sha512-QMwNOrBQ2FQU82aPkHtnfaHqI9wzJKJj2ZU0CHVRBgK9V9D77VJvtufFU0qP+6x/p5Ba26i2y9AGv2jpDGBs6w==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/steps": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/steps/-/steps-1.26.1.tgz",
+ "integrity": "sha512-EUVpGOdOd/bjG1PiJ0lRZmfdPt7YcqL3y87mS5HZ4ZSyPp8piUOMDy7ZhZvweJB3DScF7FMfmV7ygZTNcq4dLQ==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/store": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/store/-/store-1.26.1.tgz",
+ "integrity": "sha512-0473Z38EVnl6RcjXecevzfxYbzZWEcCqsx+Q3Eti+5LKvSnl05SomiF5dYDd8qPQ167iWAQWhBYSTvasfjKa4w==",
+ "requires": {
+ "proxy-compare": "3.0.1"
+ }
+ },
+ "@zag-js/switch": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/switch/-/switch-1.26.1.tgz",
+ "integrity": "sha512-OfOF2BYBtEeoI4RU0eYTFH3QAORNQBuVtDrsERJuWldLk9p1sukETXooTFxqaQuLRx98J3Y7duryjvTvNyA8nA==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-visible": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "@zag-js/focus-visible": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.26.1.tgz",
+ "integrity": "sha512-Hq57XwQWS0a5rjiZcgWhC8ca1e75VoqVLaSGn8XM29lv13423MPRtJ6b/zkEx5G4yZmddgA+wFh2/U2KPztcYA==",
+ "requires": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/tabs": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/tabs/-/tabs-1.26.1.tgz",
+ "integrity": "sha512-RI3Od0H6guYfflmCmpKO0hrh1FOjE/OduEEiD1XDn5foeD0uV/qhS8Wdh8R3ikgcaVjb5XrSOrCZXkuc732g8w==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/tags-input": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/tags-input/-/tags-input-1.26.1.tgz",
+ "integrity": "sha512-Gjjsq7CQolog1mEjU07hwnTPXQ9jjln35X52EjlsjOuohkzT0TFRDj5Nuf8fqu82k2OcSx8IX09wrdGgxMKklA==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/auto-resize": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/interact-outside": "1.26.1",
+ "@zag-js/live-region": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/timer": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/timer/-/timer-1.26.1.tgz",
+ "integrity": "sha512-+Xi7wtxCD9kjdHNeeNpCENMezWh2ZVO6KfRoLx31PTz1Dm6h457pofsAO0u8LZEpbI3IypTiTYFeaJn3qJtVrw==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/toast": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/toast/-/toast-1.26.1.tgz",
+ "integrity": "sha512-TLcN9Bd17fI0069VOV7Ug1kGk5feUK38YKJys8/1cujG+Cu4d5iUif/GUJDrRjcI/P6dPVTzrZ9ag+pCzxkWOA==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/toggle": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/toggle/-/toggle-1.26.1.tgz",
+ "integrity": "sha512-MrwXORUWpe5adyK9ieXt7KsxsBwdaFwUn42IoPLYnw61RS92qd4DPttxENXTpdL1RpqpO/G0piIzeAm7tVB/Yw==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/toggle-group": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/toggle-group/-/toggle-group-1.26.1.tgz",
+ "integrity": "sha512-0YXWmK59E+PPxpxj/YYbRY/gP1rVRnJ/hR57XNQykLrl+uYWy16lM3CD9tke3mmLwevdMpC3JwpdPAF9AGVBVw==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/tooltip": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/tooltip/-/tooltip-1.26.1.tgz",
+ "integrity": "sha512-ezBF4DZYo7E+AjVvpOoXnoPwhSnbS3y6Fp9BMvzQRSn5qElZbdQOEZSI9R6MZBTfEo6syXE68MYyCMzKFpkQFg==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-visible": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ },
+ "@zag-js/focus-visible": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.26.1.tgz",
+ "integrity": "sha512-Hq57XwQWS0a5rjiZcgWhC8ca1e75VoqVLaSGn8XM29lv13423MPRtJ6b/zkEx5G4yZmddgA+wFh2/U2KPztcYA==",
+ "requires": {
+ "@zag-js/dom-query": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/tour": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/tour/-/tour-1.26.1.tgz",
+ "integrity": "sha512-dNG8+fH6sVUjYsGQ8fO5gHvIZ1temhR3fe4H3lbSjqeb+8FHNXfkM1PbgNkUTmBar4JdEdWU60E/26cChDkxGQ==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dismissable": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/focus-trap": "1.26.1",
+ "@zag-js/interact-outside": "1.26.1",
+ "@zag-js/popper": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/tree-view": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/tree-view/-/tree-view-1.26.1.tgz",
+ "integrity": "sha512-t+vzJ8EsDO0hAAwYbwQmQqy2aoWRWdUHJKhYk9pU8+tEwU7shepX2kSP3xbxpsXcHih5TBAzSQhGcqXi8rfnlA==",
+ "requires": {
+ "@zag-js/anatomy": "1.26.1",
+ "@zag-js/collection": "1.26.1",
+ "@zag-js/core": "1.26.1",
+ "@zag-js/dom-query": "1.26.1",
+ "@zag-js/types": "1.26.1",
+ "@zag-js/utils": "1.26.1"
+ },
+ "dependencies": {
+ "@zag-js/dom-query": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.26.1.tgz",
+ "integrity": "sha512-AcdNV+Zn+Mrz6jq6IpgBJmiooFCuGBzhbbjjU6Drh3TfNDL7q2YXinrZydoD4EGDaFOQ1h71iChTtCZSHw/yNw==",
+ "requires": {
+ "@zag-js/types": "1.26.1"
+ }
+ }
+ }
+ },
+ "@zag-js/types": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/types/-/types-1.26.1.tgz",
+ "integrity": "sha512-MXRn8x0af7ZVJ50cxCoJU7hLZ3FmPnD53UQnjkYSmOcwr1eE0Wyt7bjGUP1Zv+6hPMTlyZ18XR2rnUkKAtr7/w==",
+ "requires": {
+ "csstype": "3.1.3"
+ }
+ },
+ "@zag-js/utils": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/utils/-/utils-1.26.1.tgz",
+ "integrity": "sha512-OeQia4UV/3osMdrhSa2NmhWvzlnlF1vxOBAdYP5R96ho0FpI15DvAaPQDvE94shzIMgzS4k0pqK5lZWK5FTmqw=="
+ },
"abab": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
@@ -67756,6 +70724,11 @@
"integrity": "sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA==",
"optional": true
},
+ "lucide-react": {
+ "version": "0.503.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.503.0.tgz",
+ "integrity": "sha512-HGGkdlPWQ0vTF8jJ5TdIqhQXZi6uh3LnNgfZ8MHiuxFfX3RZeA79r2MW2tHAZKlAVfoNE8esm3p+O6VkIvpj6w=="
+ },
"lunr": {
"version": "2.3.9",
"resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
@@ -71806,6 +74779,19 @@
}
}
},
+ "proxy-compare": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-3.0.1.tgz",
+ "integrity": "sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q=="
+ },
+ "proxy-memoize": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/proxy-memoize/-/proxy-memoize-3.0.1.tgz",
+ "integrity": "sha512-VDdG/VYtOgdGkWJx7y0o7p+zArSf2383Isci8C+BP3YXgMYDoPd3cCBjw0JdWb6YBb9sFiOPbAADDVTPJnh+9g==",
+ "requires": {
+ "proxy-compare": "^3.0.0"
+ }
+ },
"prr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
@@ -73892,6 +76878,21 @@
"integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
"dev": true
},
+ "shiki": {
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.13.0.tgz",
+ "integrity": "sha512-aZW4l8Og16CokuCLf8CF8kq+KK2yOygapU5m3+hoGw0Mdosc6fPitjM+ujYarppj5ZIKGyPDPP1vqmQhr+5/0g==",
+ "requires": {
+ "@shikijs/core": "3.13.0",
+ "@shikijs/engine-javascript": "3.13.0",
+ "@shikijs/engine-oniguruma": "3.13.0",
+ "@shikijs/langs": "3.13.0",
+ "@shikijs/themes": "3.13.0",
+ "@shikijs/types": "3.13.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
"side-channel": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
@@ -75186,9 +78187,9 @@
}
},
"tslib": {
- "version": "2.6.3",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
- "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"tunnel-rat": {
"version": "0.1.2",
@@ -75837,6 +78838,11 @@
}
}
},
+ "uqr": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/uqr/-/uqr-0.1.2.tgz",
+ "integrity": "sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA=="
+ },
"uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
diff --git a/package.json b/package.json
index f7c35d86f60..9102bd81d4f 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,8 @@
"license": "MIT",
"private": true,
"workspaces": [
- "packages/*"
+ "packages/*",
+ "examples/dev-*"
],
"engines": {
"npm": ">=8.2.3",
diff --git a/packages/lexical-clipboard/package.json b/packages/lexical-clipboard/package.json
index 6d323b42937..d46c3859d9d 100644
--- a/packages/lexical-clipboard/package.json
+++ b/packages/lexical-clipboard/package.json
@@ -13,6 +13,7 @@
"main": "LexicalClipboard.js",
"types": "index.d.ts",
"dependencies": {
+ "@lexical/extension": "0.37.0",
"@lexical/html": "0.37.0",
"@lexical/list": "0.37.0",
"@lexical/selection": "0.37.0",
diff --git a/packages/lexical-clipboard/src/clipboard.ts b/packages/lexical-clipboard/src/clipboard.ts
index 3693b5bc08d..aae79fe26a5 100644
--- a/packages/lexical-clipboard/src/clipboard.ts
+++ b/packages/lexical-clipboard/src/clipboard.ts
@@ -6,6 +6,10 @@
*
*/
+import {
+ getExtensionDependencyFromEditor,
+ LexicalBuilder,
+} from '@lexical/extension';
import {$generateHtmlFromNodes, $generateNodesFromDOM} from '@lexical/html';
import {$addNodeStyle, $sliceSelectedTextNodeContent} from '@lexical/selection';
import {objectKlassEquals} from '@lexical/utils';
@@ -25,12 +29,15 @@ import {
BaseSelection,
COMMAND_PRIORITY_CRITICAL,
COPY_COMMAND,
+ defineExtension,
getDOMSelection,
isSelectionWithinEditor,
LexicalEditor,
LexicalNode,
+ safeCast,
SELECTION_INSERT_CLIPBOARD_NODES_COMMAND,
SerializedElementNode,
+ shallowMergeConfig,
} from 'lexical';
import invariant from 'shared/invariant';
@@ -38,6 +45,7 @@ export interface LexicalClipboardData {
'text/html'?: string | undefined;
'application/x-lexical-editor'?: string | undefined;
'text/plain': string;
+ [mimeType: string]: string | undefined;
}
/**
@@ -537,32 +545,6 @@ const clipboardDataFunctions = [
['application/x-lexical-editor', $getLexicalContent],
] as const;
-/**
- * Serialize the content of the current selection to strings in
- * text/plain, text/html, and application/x-lexical-editor (Lexical JSON)
- * formats (as available).
- *
- * @param selection the selection to serialize (defaults to $getSelection())
- * @returns LexicalClipboardData
- */
-export function $getClipboardDataFromSelection(
- selection: BaseSelection | null = $getSelection(),
-): LexicalClipboardData {
- const clipboardData: LexicalClipboardData = {
- 'text/plain': selection ? selection.getTextContent() : '',
- };
- if (selection) {
- const editor = $getEditor();
- for (const [mimeType, $editorFn] of clipboardDataFunctions) {
- const v = $editorFn(editor, selection);
- if (v !== null) {
- clipboardData[mimeType] = v;
- }
- }
- }
- return clipboardData;
-}
-
/**
* Call setData on the given clipboardData for each MIME type present
* in the given data (from {@link $getClipboardDataFromSelection})
@@ -586,3 +568,108 @@ export function setLexicalClipboardDataTransfer(
}
}
}
+
+/**
+ * Serialize the content of the current selection to strings in
+ * text/plain, text/html, and application/x-lexical-editor (Lexical JSON)
+ * formats (as available).
+ *
+ * @param selection the selection to serialize (defaults to $getSelection())
+ * @returns LexicalClipboardData
+ */
+export function $getClipboardDataFromSelection(
+ selection: BaseSelection | null = $getSelection(),
+): LexicalClipboardData {
+ return $getClipboardDataWithConfigFromSelection(
+ $getExportConfig(),
+ selection,
+ );
+}
+
+export type ExportMimeTypeFunction = (
+ selection: null | BaseSelection,
+ next: () => null | string,
+) => null | string;
+
+export interface GetClipboardDataConfig {
+ $exportMimeType: ExportMimeTypeConfig;
+}
+
+export type ExportMimeTypeConfig = Record<
+ keyof LexicalClipboardData | (string & {}),
+ ExportMimeTypeFunction[]
+>;
+
+function $getExportConfig() {
+ const editor = $getEditor();
+ const builder = LexicalBuilder.maybeFromEditor(editor);
+ if (builder && builder.hasExtensionByName(GetClipboardDataExtension.name)) {
+ return getExtensionDependencyFromEditor(editor, GetClipboardDataExtension)
+ .output;
+ }
+ return DEFAULT_EXPORT_MIME_TYPE;
+}
+
+const DEFAULT_EXPORT_MIME_TYPE: ExportMimeTypeConfig = {
+ 'application/x-lexical-editor': [
+ (sel, next) => (sel ? $getLexicalContent($getEditor(), sel) : next()),
+ ],
+ 'text/html': [
+ (sel, next) => (sel ? $getHtmlContent($getEditor(), sel) : next()),
+ ],
+ 'text/plain': [(sel, next) => (sel ? sel.getTextContent() : next())],
+};
+
+function $getClipboardDataWithConfigFromSelection(
+ $exportMimeType: ExportMimeTypeConfig,
+ selection: null | BaseSelection,
+): LexicalClipboardData {
+ const clipboardData: LexicalClipboardData = {'text/plain': ''};
+ for (const [k, fns] of Object.entries($exportMimeType)) {
+ const v = callExportMimeTypeFunctionStack(fns, selection);
+ if (v !== null) {
+ clipboardData[k] = v;
+ }
+ }
+ return clipboardData;
+}
+
+function callExportMimeTypeFunctionStack(
+ fns: ExportMimeTypeFunction[],
+ selection: null | BaseSelection,
+) {
+ const callAt = (i: number): string | null =>
+ fns[i] ? fns[i](selection, callAt.bind(null, i - 1)) : null;
+ return callAt(fns.length - 1);
+}
+
+export function $exportMimeTypeFromSelection(
+ mimeType: keyof ExportMimeTypeConfig,
+ selection: null | BaseSelection = $getSelection(),
+): string | null {
+ return callExportMimeTypeFunctionStack(
+ $getExportConfig()[mimeType] || [],
+ selection,
+ );
+}
+
+export const GetClipboardDataExtension = defineExtension({
+ build(editor, config, state) {
+ return config.$exportMimeType;
+ },
+ config: safeCast({
+ $exportMimeType: DEFAULT_EXPORT_MIME_TYPE,
+ }),
+ mergeConfig(config, partial) {
+ const merged = shallowMergeConfig(config, partial);
+ if (partial.$exportMimeType) {
+ const $exportMimeType = {...config.$exportMimeType};
+ for (const [k, v] of Object.entries(partial.$exportMimeType)) {
+ $exportMimeType[k] = [...$exportMimeType[k], ...v];
+ }
+ merged.$exportMimeType = $exportMimeType;
+ }
+ return merged;
+ },
+ name: '@lexical/clipboard/GetClipboardData',
+});
diff --git a/packages/lexical-extension/src/config.ts b/packages/lexical-extension/src/config.ts
index 28e45e684ea..e8df5c7e6b4 100644
--- a/packages/lexical-extension/src/config.ts
+++ b/packages/lexical-extension/src/config.ts
@@ -5,11 +5,12 @@
* LICENSE file in the root directory of this source tree.
*
*/
-import type {
- CreateEditorArgs,
- InitialEditorConfig,
- KlassConstructor,
- LexicalNode,
+import {
+ type CreateEditorArgs,
+ getStaticNodeConfig,
+ type InitialEditorConfig,
+ type KlassConstructor,
+ type LexicalNode,
} from 'lexical';
export interface KnownTypesAndNodes {
@@ -25,7 +26,9 @@ export interface KnownTypesAndNodes {
* @param config The InitialEditorConfig (accessible from an extension's init)
* @returns The known types and nodes as Sets
*/
-export function getKnownTypesAndNodes(config: InitialEditorConfig) {
+export function getKnownTypesAndNodes(
+ config: Pick,
+): KnownTypesAndNodes {
const types: KnownTypesAndNodes['types'] = new Set();
const nodes: KnownTypesAndNodes['nodes'] = new Set();
for (const klassOrReplacement of getNodeConfig(config)) {
@@ -33,6 +36,8 @@ export function getKnownTypesAndNodes(config: InitialEditorConfig) {
typeof klassOrReplacement === 'function'
? klassOrReplacement
: klassOrReplacement.replace;
+ // For the side-effect of filling in the static methods
+ void getStaticNodeConfig(klass);
types.add(klass.getType());
nodes.add(klass);
}
@@ -40,7 +45,7 @@ export function getKnownTypesAndNodes(config: InitialEditorConfig) {
}
export function getNodeConfig(
- config: InitialEditorConfig,
+ config: Pick,
): NonNullable {
return (
(typeof config.nodes === 'function' ? config.nodes() : config.nodes) || []
diff --git a/packages/lexical-html/package.json b/packages/lexical-html/package.json
index 6fe47c8ee71..4f3c021f29f 100644
--- a/packages/lexical-html/package.json
+++ b/packages/lexical-html/package.json
@@ -17,6 +17,7 @@
"directory": "packages/lexical-html"
},
"dependencies": {
+ "@lexical/extension": "0.37.0",
"@lexical/selection": "0.37.0",
"@lexical/utils": "0.37.0",
"lexical": "0.37.0"
diff --git a/packages/lexical-html/src/$generateDOMFromNodes.ts b/packages/lexical-html/src/$generateDOMFromNodes.ts
new file mode 100644
index 00000000000..df7a4a1c3ce
--- /dev/null
+++ b/packages/lexical-html/src/$generateDOMFromNodes.ts
@@ -0,0 +1,175 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import {$sliceSelectedTextNodeContent} from '@lexical/selection';
+import {
+ $getEditor,
+ $getEditorDOMRenderConfig,
+ $getRoot,
+ $isElementNode,
+ $isTextNode,
+ type BaseSelection,
+ type EditorDOMRenderConfig,
+ isDocumentFragment,
+ isHTMLElement,
+ type LexicalEditor,
+ type LexicalNode,
+} from 'lexical';
+import invariant from 'shared/invariant';
+
+import {contextValue} from './ContextRecord';
+import {
+ $withRenderContext,
+ RenderContextExport,
+ RenderContextRoot,
+} from './RenderContext';
+
+export function $generateDOMFromNodes(
+ container: T,
+ selection: null | BaseSelection = null,
+ editor: LexicalEditor = $getEditor(),
+): T {
+ return $withRenderContext(
+ [contextValue(RenderContextExport, true)],
+ editor,
+ )(() => {
+ const root = $getRoot();
+ const domConfig = $getEditorDOMRenderConfig(editor);
+
+ const parentElementAppend = container.append.bind(container);
+ for (const topLevelNode of root.getChildren()) {
+ $appendNodesToHTML(
+ editor,
+ topLevelNode,
+ parentElementAppend,
+ selection,
+ domConfig,
+ );
+ }
+ return container;
+ });
+}
+
+export function $generateDOMFromRoot(
+ container: T,
+ root: LexicalNode = $getRoot(),
+): T {
+ const editor = $getEditor();
+ return $withRenderContext(
+ [
+ contextValue(RenderContextExport, true),
+ contextValue(RenderContextRoot, true),
+ ],
+ editor,
+ )(() => {
+ const selection = null;
+ const domConfig = $getEditorDOMRenderConfig(editor);
+ const parentElementAppend = container.append.bind(container);
+ $appendNodesToHTML(editor, root, parentElementAppend, selection, domConfig);
+ return container;
+ });
+}
+function $appendNodesToHTML(
+ editor: LexicalEditor,
+ currentNode: LexicalNode,
+ parentElementAppend: (element: Node) => void,
+ selection: BaseSelection | null = null,
+ domConfig: EditorDOMRenderConfig = $getEditorDOMRenderConfig(editor),
+): boolean {
+ let shouldInclude = domConfig.$shouldInclude(currentNode, selection, editor);
+ const shouldExclude = domConfig.$shouldExclude(
+ currentNode,
+ selection,
+ editor,
+ );
+ let target = currentNode;
+
+ if (selection !== null && $isTextNode(currentNode)) {
+ target = $sliceSelectedTextNodeContent(selection, currentNode, 'clone');
+ }
+ const exportProps = domConfig.$exportDOM(target, editor);
+ const {element, after, append, $getChildNodes} = exportProps;
+
+ if (!element) {
+ return false;
+ }
+
+ const fragment = document.createDocumentFragment();
+ const children = $getChildNodes
+ ? $getChildNodes()
+ : $isElementNode(target)
+ ? target.getChildren()
+ : [];
+
+ const fragmentAppend = fragment.append.bind(fragment);
+ for (const childNode of children) {
+ const shouldIncludeChild = $appendNodesToHTML(
+ editor,
+ childNode,
+ fragmentAppend,
+ selection,
+ domConfig,
+ );
+
+ if (
+ !shouldInclude &&
+ shouldIncludeChild &&
+ domConfig.$extractWithChild(
+ currentNode,
+ childNode,
+ selection,
+ 'html',
+ editor,
+ )
+ ) {
+ shouldInclude = true;
+ }
+ }
+
+ if (shouldInclude && !shouldExclude) {
+ if (isHTMLElement(element) || isDocumentFragment(element)) {
+ if (append) {
+ append(fragment);
+ } else {
+ element.append(fragment);
+ }
+ }
+ parentElementAppend(element);
+
+ if (after) {
+ const newElement = after.call(target, element);
+ if (newElement) {
+ if (isDocumentFragment(element)) {
+ element.replaceChildren(newElement);
+ } else {
+ element.replaceWith(newElement);
+ }
+ }
+ }
+ } else {
+ parentElementAppend(fragment);
+ }
+
+ return shouldInclude;
+}
+
+export function $generateHtmlFromNodes(
+ editor: LexicalEditor,
+ selection: BaseSelection | null = null,
+): string {
+ if (
+ typeof document === 'undefined' ||
+ (typeof window === 'undefined' && typeof global.window === 'undefined')
+ ) {
+ invariant(
+ false,
+ 'To use $generateHtmlFromNodes in headless mode please initialize a headless browser implementation such as JSDom or use withDOM from @lexical/headless/dom before calling this function.',
+ );
+ }
+ return $generateDOMFromNodes(document.createElement('div'), selection, editor)
+ .innerHTML;
+}
diff --git a/packages/lexical-html/src/$generateNodesFromDOM.ts b/packages/lexical-html/src/$generateNodesFromDOM.ts
new file mode 100644
index 00000000000..cce30ed827c
--- /dev/null
+++ b/packages/lexical-html/src/$generateNodesFromDOM.ts
@@ -0,0 +1,219 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import {
+ $createLineBreakNode,
+ $createParagraphNode,
+ $isBlockElementNode,
+ $isElementNode,
+ $isRootOrShadowRoot,
+ ArtificialNode__DO_NOT_USE,
+ type DOMChildConversion,
+ type ElementFormatType,
+ type ElementNode,
+ isBlockDomNode,
+ isDOMDocumentNode,
+ type LexicalEditor,
+ type LexicalNode,
+} from 'lexical';
+
+import {$unwrapArtificialNodes} from './$unwrapArtificialNodes';
+import {IGNORE_TAGS} from './constants';
+import {getConversionFunction} from './getConversionFunction';
+import {isDomNodeBetweenTwoInlineNodes} from './isDomNodeBetweenTwoInlineNodes';
+
+function $wrapContinuousInlines(
+ domNode: Node,
+ nodes: Array,
+ $createWrapperFn: () => ElementNode,
+): Array {
+ const textAlign = (domNode as HTMLElement).style
+ .textAlign as ElementFormatType;
+ const out: Array = [];
+ let continuousInlines: Array = [];
+ // wrap contiguous inline child nodes in para
+ for (let i = 0; i < nodes.length; i++) {
+ const node = nodes[i];
+ if ($isBlockElementNode(node)) {
+ if (textAlign && !node.getFormat()) {
+ node.setFormat(textAlign);
+ }
+ out.push(node);
+ } else {
+ continuousInlines.push(node);
+ if (
+ i === nodes.length - 1 ||
+ (i < nodes.length - 1 && $isBlockElementNode(nodes[i + 1]))
+ ) {
+ const wrapper = $createWrapperFn();
+ wrapper.setFormat(textAlign);
+ wrapper.append(...continuousInlines);
+ out.push(wrapper);
+ continuousInlines = [];
+ }
+ }
+ }
+ return out;
+}
+
+/**
+ * How you parse your html string to get a document is left up to you. In the browser you can use the native
+ * DOMParser API to generate a document (see clipboard.ts), but to use in a headless environment you can use JSDom
+ * or an equivalent library and pass in the document here.
+ */
+
+export function $generateNodesFromDOM(
+ editor: LexicalEditor,
+ dom: Document | ParentNode,
+): Array {
+ const elements = isDOMDocumentNode(dom)
+ ? dom.body.childNodes
+ : dom.childNodes;
+ let lexicalNodes: Array = [];
+ const allArtificialNodes: Array = [];
+ for (const element of elements) {
+ if (!IGNORE_TAGS.has(element.nodeName)) {
+ const lexicalNode = $createNodesFromDOM(
+ element,
+ editor,
+ allArtificialNodes,
+ false,
+ );
+ if (lexicalNode !== null) {
+ lexicalNodes = lexicalNodes.concat(lexicalNode);
+ }
+ }
+ }
+ $unwrapArtificialNodes(allArtificialNodes);
+
+ return lexicalNodes;
+}
+
+export function $createNodesFromDOM(
+ node: Node,
+ editor: LexicalEditor,
+ allArtificialNodes: Array,
+ hasBlockAncestorLexicalNode: boolean,
+ forChildMap: Map = new Map(),
+ parentLexicalNode?: LexicalNode | null | undefined,
+): Array {
+ let lexicalNodes: Array = [];
+
+ if (IGNORE_TAGS.has(node.nodeName)) {
+ return lexicalNodes;
+ }
+
+ let currentLexicalNode = null;
+ const transformFunction = getConversionFunction(node, editor);
+ const transformOutput = transformFunction
+ ? transformFunction(node as HTMLElement)
+ : null;
+ let postTransform = null;
+
+ if (transformOutput !== null) {
+ postTransform = transformOutput.after;
+ const transformNodes = transformOutput.node;
+ currentLexicalNode = Array.isArray(transformNodes)
+ ? transformNodes[transformNodes.length - 1]
+ : transformNodes;
+
+ if (currentLexicalNode !== null) {
+ for (const [, forChildFunction] of forChildMap) {
+ currentLexicalNode = forChildFunction(
+ currentLexicalNode,
+ parentLexicalNode,
+ );
+
+ if (!currentLexicalNode) {
+ break;
+ }
+ }
+
+ if (currentLexicalNode) {
+ lexicalNodes.push(
+ ...(Array.isArray(transformNodes)
+ ? transformNodes
+ : [currentLexicalNode]),
+ );
+ }
+ }
+
+ if (transformOutput.forChild != null) {
+ forChildMap.set(node.nodeName, transformOutput.forChild);
+ }
+ }
+
+ // If the DOM node doesn't have a transformer, we don't know what
+ // to do with it but we still need to process any childNodes.
+ const children = node.childNodes;
+ let childLexicalNodes = [];
+
+ const hasBlockAncestorLexicalNodeForChildren =
+ currentLexicalNode != null && $isRootOrShadowRoot(currentLexicalNode)
+ ? false
+ : (currentLexicalNode != null &&
+ $isBlockElementNode(currentLexicalNode)) ||
+ hasBlockAncestorLexicalNode;
+
+ for (let i = 0; i < children.length; i++) {
+ childLexicalNodes.push(
+ ...$createNodesFromDOM(
+ children[i],
+ editor,
+ allArtificialNodes,
+ hasBlockAncestorLexicalNodeForChildren,
+ new Map(forChildMap),
+ currentLexicalNode,
+ ),
+ );
+ }
+
+ if (postTransform != null) {
+ childLexicalNodes = postTransform(childLexicalNodes);
+ }
+
+ if (isBlockDomNode(node)) {
+ if (!hasBlockAncestorLexicalNodeForChildren) {
+ childLexicalNodes = $wrapContinuousInlines(
+ node,
+ childLexicalNodes,
+ $createParagraphNode,
+ );
+ } else {
+ childLexicalNodes = $wrapContinuousInlines(
+ node,
+ childLexicalNodes,
+ () => {
+ const artificialNode = new ArtificialNode__DO_NOT_USE();
+ allArtificialNodes.push(artificialNode);
+ return artificialNode;
+ },
+ );
+ }
+ }
+
+ if (currentLexicalNode == null) {
+ if (childLexicalNodes.length > 0) {
+ // If it hasn't been converted to a LexicalNode, we hoist its children
+ // up to the same level as it.
+ lexicalNodes = lexicalNodes.concat(childLexicalNodes);
+ } else {
+ if (isBlockDomNode(node) && isDomNodeBetweenTwoInlineNodes(node)) {
+ // Empty block dom node that hasnt been converted, we replace it with a linebreak if its between inline nodes
+ lexicalNodes = lexicalNodes.concat($createLineBreakNode());
+ }
+ }
+ } else {
+ if ($isElementNode(currentLexicalNode)) {
+ // If the current node is a ElementNode after conversion,
+ // we can append all the children to it.
+ currentLexicalNode.append(...childLexicalNodes);
+ }
+ }
+
+ return lexicalNodes;
+}
diff --git a/packages/lexical-html/src/$unwrapArtificialNodes.ts b/packages/lexical-html/src/$unwrapArtificialNodes.ts
new file mode 100644
index 00000000000..08c9d1f1488
--- /dev/null
+++ b/packages/lexical-html/src/$unwrapArtificialNodes.ts
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import {$createLineBreakNode, ArtificialNode__DO_NOT_USE} from 'lexical';
+
+export function $unwrapArtificialNodes(
+ allArtificialNodes: Array,
+) {
+ // Replace artificial node with its children, inserting a linebreak
+ // between adjacent artificial nodes
+ for (const node of allArtificialNodes) {
+ if (
+ node.getParent() &&
+ node.getNextSibling() instanceof ArtificialNode__DO_NOT_USE
+ ) {
+ node.insertAfter($createLineBreakNode());
+ }
+ }
+ for (const node of allArtificialNodes) {
+ const parent = node.getParent();
+ if (parent) {
+ parent.splice(node.getIndexWithinParent(), 1, node.getChildren());
+ }
+ }
+}
diff --git a/packages/lexical-html/src/$wrapContinuousInlinesInPlace.ts b/packages/lexical-html/src/$wrapContinuousInlinesInPlace.ts
new file mode 100644
index 00000000000..4315ae44c8e
--- /dev/null
+++ b/packages/lexical-html/src/$wrapContinuousInlinesInPlace.ts
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import {
+ $isBlockElementNode,
+ type ElementFormatType,
+ type ElementNode,
+ type LexicalNode,
+} from 'lexical';
+
+export function $wrapContinuousInlinesInPlace(
+ domNode: Node,
+ nodes: LexicalNode[],
+ $createWrapperFn: () => ElementNode,
+): void {
+ const textAlign = (domNode as HTMLElement).style
+ .textAlign as ElementFormatType;
+ // wrap contiguous inline child nodes in para
+ let j = 0;
+ for (let i = 0, wrapper: undefined | ElementNode; i < nodes.length; i++) {
+ const node = nodes[i];
+ if ($isBlockElementNode(node)) {
+ if (textAlign && !node.getFormat()) {
+ node.setFormat(textAlign);
+ }
+ wrapper = undefined;
+ nodes[j++] = node;
+ } else {
+ if (!wrapper) {
+ nodes[j++] = wrapper = $createWrapperFn().setFormat(textAlign);
+ }
+ wrapper.append(node);
+ }
+ }
+ nodes.length = j;
+}
diff --git a/packages/lexical-html/src/ContextRecord.ts b/packages/lexical-html/src/ContextRecord.ts
new file mode 100644
index 00000000000..e553ddf5826
--- /dev/null
+++ b/packages/lexical-html/src/ContextRecord.ts
@@ -0,0 +1,216 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import type {
+ AnyContextConfigPairOrUpdater,
+ AnyContextSymbol,
+ ContextConfig,
+ ContextConfigPair,
+ ContextConfigUpdater,
+ ContextRecord,
+} from './types';
+
+import {$getEditor, createState, type LexicalEditor} from 'lexical';
+
+let activeContext: undefined | EditorContext;
+
+type WithContext = {
+ [K in Ctx]?: undefined | ContextRecord;
+};
+
+export type EditorContext = {
+ editor: LexicalEditor;
+} & WithContext;
+
+export function getContextValue(
+ contextRecord: undefined | ContextRecord,
+ cfg: ContextConfig,
+): V {
+ const {key} = cfg;
+ return contextRecord && key in contextRecord
+ ? (contextRecord[key] as V)
+ : cfg.defaultValue;
+}
+
+export function popOwnContextValue(
+ contextRecord: ContextRecord,
+ cfg: ContextConfig,
+): undefined | V {
+ const rval = getOwnContextValue(contextRecord, cfg);
+ delete contextRecord[cfg.key];
+ return rval;
+}
+
+export function getOwnContextValue(
+ contextRecord: ContextRecord,
+ cfg: ContextConfig,
+): undefined | V {
+ const {key} = cfg;
+ return key in contextRecord ? (contextRecord[key] as V) : undefined;
+}
+
+function getEditorContext(editor: LexicalEditor): undefined | EditorContext {
+ return activeContext && activeContext.editor === editor
+ ? activeContext
+ : undefined;
+}
+
+export function getContextRecord(
+ sym: Ctx,
+ editor: LexicalEditor,
+): undefined | ContextRecord {
+ const editorContext = getEditorContext(editor);
+ return editorContext && editorContext[sym];
+}
+
+function toPair(
+ contextRecord: undefined | ContextRecord,
+ pairOrUpdater: ContextConfigPair | ContextConfigUpdater,
+): ContextConfigPair {
+ if ('cfg' in pairOrUpdater) {
+ const {cfg, updater} = pairOrUpdater;
+ return [cfg, updater(getContextValue(contextRecord, cfg))];
+ }
+ return pairOrUpdater;
+}
+
+export function contextFromPairs(
+ pairs: readonly AnyContextConfigPairOrUpdater[],
+ parent: undefined | ContextRecord,
+): undefined | ContextRecord {
+ let rval = parent;
+ for (const pairOrUpdater of pairs) {
+ const [k, v] = toPair(rval, pairOrUpdater);
+ const key = k.key;
+ if (rval === parent && getContextValue(rval, k) === v) {
+ continue;
+ }
+ const ctx = rval || createChildContext(parent);
+ ctx[key] = v;
+ rval = ctx;
+ }
+ return rval;
+}
+
+export function createChildContext(
+ parent: undefined | ContextRecord,
+): ContextRecord {
+ return Object.create(parent || null);
+}
+
+export function setContextValue(
+ contextRecord: ContextRecord,
+ cfg: ContextConfig,
+ value: V,
+): V {
+ contextRecord[cfg.key] = value;
+ return value;
+}
+
+export function contextValue(
+ cfg: ContextConfig,
+ value: V,
+): ContextConfigPair {
+ return [cfg, value];
+}
+
+export function contextUpdater(
+ cfg: ContextConfig,
+ updater: (prev: V) => V,
+): ContextConfigUpdater {
+ return {cfg, updater};
+}
+
+export function updateContextValue(
+ contextRecord: ContextRecord,
+ cfg: ContextConfig,
+ updater: (prev: V) => V,
+): V {
+ const value = updater(getContextValue(contextRecord, cfg));
+ return setContextValue(contextRecord, cfg, value);
+}
+
+export function updateContextFromPairs(
+ contextRecord: ContextRecord,
+ pairs: undefined | readonly AnyContextConfigPairOrUpdater[],
+): ContextRecord {
+ if (pairs) {
+ for (const pairOrUpdater of pairs) {
+ const [cfg, value] = toPair(contextRecord, pairOrUpdater);
+ setContextValue(contextRecord, cfg, value);
+ }
+ }
+ return contextRecord;
+}
+
+/**
+ * @__NO_SIDE_EFFECTS__
+ */
+export function $withFullContext(
+ sym: Ctx,
+ contextRecord: ContextRecord,
+ f: () => T,
+ editor: LexicalEditor = $getEditor(),
+): T {
+ const prevDOMContext = activeContext;
+ const parentEditorContext = getEditorContext(editor);
+ try {
+ activeContext = {...parentEditorContext, editor, [sym]: contextRecord};
+ return f();
+ } finally {
+ activeContext = prevDOMContext;
+ }
+}
+
+/**
+ * @__NO_SIDE_EFFECTS__
+ */
+export function $withContext(
+ sym: Ctx,
+ $defaults: (editor: LexicalEditor) => undefined | ContextRecord = () =>
+ undefined,
+) {
+ return (
+ cfg: readonly AnyContextConfigPairOrUpdater[],
+ editor = $getEditor(),
+ ): ((f: () => T) => T) => {
+ return (f) => {
+ const prevDOMContext = activeContext;
+ const parentEditorContext = getEditorContext(editor);
+ const parentContextRecord =
+ parentEditorContext && parentEditorContext[sym];
+ const contextRecord = contextFromPairs(
+ cfg,
+ parentContextRecord || $defaults(editor),
+ );
+ if (!contextRecord || contextRecord === parentContextRecord) {
+ return f();
+ }
+ try {
+ activeContext = {...parentEditorContext, editor, [sym]: contextRecord};
+ return f();
+ } finally {
+ activeContext = prevDOMContext;
+ }
+ };
+ };
+}
+
+/**
+ * @__NO_SIDE_EFFECTS__
+ */
+export function createContextState(
+ tag: Tag,
+ name: string,
+ getDefaultValue: () => V,
+ isEqual?: (a: V, b: V) => boolean,
+): ContextConfig {
+ return Object.assign(
+ createState(Symbol(name), {isEqual, parse: getDefaultValue}),
+ {[tag]: true} as const,
+ );
+}
diff --git a/packages/lexical-html/src/DOMImportExtension.ts b/packages/lexical-html/src/DOMImportExtension.ts
new file mode 100644
index 00000000000..e2d19a6b7cb
--- /dev/null
+++ b/packages/lexical-html/src/DOMImportExtension.ts
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import type {DOMImportConfig, DOMImportExtensionOutput} from './types';
+
+import {defineExtension, shallowMergeConfig} from 'lexical';
+
+import {compileDOMImportOverrides} from './compileDOMImportOverrides';
+import {compileLegacyImportDOM} from './compileLegacyImportDOM';
+import {DOMImportExtensionName} from './constants';
+
+/** @internal @experimental */
+export const DOMImportExtension = defineExtension<
+ DOMImportConfig,
+ typeof DOMImportExtensionName,
+ DOMImportExtensionOutput,
+ null
+>({
+ build: compileDOMImportOverrides,
+ config: {compileLegacyImportNode: compileLegacyImportDOM, overrides: []},
+ mergeConfig(config, partial) {
+ const merged = shallowMergeConfig(config, partial);
+ for (const k of ['overrides'] as const) {
+ if (partial[k]) {
+ (merged[k] as unknown[]) = [...config[k], ...partial[k]];
+ }
+ }
+ return merged;
+ },
+ name: DOMImportExtensionName,
+});
diff --git a/packages/lexical-html/src/DOMRenderExtension.ts b/packages/lexical-html/src/DOMRenderExtension.ts
new file mode 100644
index 00000000000..6e845b2f1cb
--- /dev/null
+++ b/packages/lexical-html/src/DOMRenderExtension.ts
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import type {DOMRenderConfig, DOMRenderExtensionOutput} from './types';
+
+import {defineExtension, RootNode, shallowMergeConfig} from 'lexical';
+
+import {compileDOMRenderConfigOverrides} from './compileDOMRenderConfigOverrides';
+import {DOMRenderExtensionName} from './constants';
+import {contextFromPairs} from './ContextRecord';
+
+/** @internal @experimental */
+
+export const DOMRenderExtension = defineExtension<
+ DOMRenderConfig,
+ typeof DOMRenderExtensionName,
+ DOMRenderExtensionOutput,
+ void
+>({
+ build(editor, config, state) {
+ return {
+ defaults: contextFromPairs(config.contextDefaults, undefined),
+ };
+ },
+ config: {
+ contextDefaults: [],
+ overrides: [],
+ },
+ html: {
+ // Define a RootNode export for $generateDOMFromRoot
+ export: new Map([
+ [
+ RootNode,
+ () => {
+ const element = document.createElement('div');
+ element.role = 'textbox';
+ return {element};
+ },
+ ],
+ ]),
+ },
+ init(editorConfig, config) {
+ editorConfig.dom = compileDOMRenderConfigOverrides(editorConfig, config);
+ },
+ mergeConfig(config, partial) {
+ const merged = shallowMergeConfig(config, partial);
+ for (const k of ['overrides', 'contextDefaults'] as const) {
+ if (partial[k]) {
+ (merged[k] as unknown[]) = [...config[k], ...partial[k]];
+ }
+ }
+ return merged;
+ },
+ name: DOMRenderExtensionName,
+});
diff --git a/packages/lexical-html/src/ImportContext.ts b/packages/lexical-html/src/ImportContext.ts
new file mode 100644
index 00000000000..f4f1678ce33
--- /dev/null
+++ b/packages/lexical-html/src/ImportContext.ts
@@ -0,0 +1,188 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+
+import type {
+ AnyImportStateConfigPairOrUpdater,
+ ContextPairOrUpdater,
+ ContextRecord,
+ DOMImportContextFinalizer,
+ DOMTextWrapMode,
+ DOMWhiteSpaceCollapse,
+ ImportStateConfig,
+} from './types';
+
+import {
+ $getEditor,
+ type ArtificialNode__DO_NOT_USE,
+ type DOMChildConversion,
+ type ElementFormatType,
+ type ElementNode,
+ type LexicalEditor,
+ type LexicalNode,
+ type TextFormatType,
+ type TextNode,
+} from 'lexical';
+import invariant from 'shared/invariant';
+
+import {DOMImportContextSymbol} from './constants';
+import {
+ createContextState,
+ getContextRecord,
+ getContextValue,
+ getOwnContextValue,
+ setContextValue,
+ updateContextValue,
+} from './ContextRecord';
+
+/**
+ * Create a context state to be used during import.
+ *
+ * Note that to support the ValueOrUpdater pattern you can not use a
+ * function for V (but you may wrap it in an array or object).
+ *
+ * @__NO_SIDE_EFFECTS__
+ */
+export function createImportState(
+ name: string,
+ getDefaultValue: () => V,
+ isEqual?: (a: V, b: V) => boolean,
+): ImportStateConfig {
+ return createContextState(
+ DOMImportContextSymbol,
+ name,
+ getDefaultValue,
+ isEqual,
+ );
+}
+
+export function $getImportContextValue(
+ cfg: ImportStateConfig,
+ editor: LexicalEditor = $getEditor(),
+): V {
+ return getContextValue(getContextRecord(DOMImportContextSymbol, editor), cfg);
+}
+
+function getImportContextOrThrow(
+ editor: LexicalEditor,
+): ContextRecord {
+ const ctx = getContextRecord(DOMImportContextSymbol, editor);
+ invariant(
+ ctx !== undefined,
+ 'getImportContextOrThrow: Import context used outside of DOM import',
+ );
+ return ctx;
+}
+
+export function $setImportContextValue(
+ cfg: ImportStateConfig,
+ value: V,
+ editor: LexicalEditor = $getEditor(),
+): V {
+ return setContextValue(getImportContextOrThrow(editor), cfg, value);
+}
+
+export function $updateImportContextValue(
+ cfg: ImportStateConfig,
+ updater: (prev: V) => V,
+ editor: LexicalEditor = $getEditor(),
+): V {
+ return updateContextValue(getImportContextOrThrow(editor), cfg, updater);
+}
+
+export const ImportContextDOMNode = createImportState(
+ 'domNode',
+ (): null | Node => null,
+);
+
+const NO_FORMATS: {readonly [K in TextFormatType]?: undefined | boolean} =
+ Object.create(null);
+
+export const ImportContextTextAlign = createImportState(
+ 'textAlign',
+ (): undefined | ElementFormatType => undefined,
+);
+
+export function $applyTextAlignToElement(node: T): T {
+ const align = $getImportContextValue(ImportContextTextAlign);
+ return align ? node.setFormat(align) : node;
+}
+
+export const ImportContextTextFormats = createImportState(
+ 'textFormats',
+ () => NO_FORMATS,
+);
+
+export function $applyTextFormatsFromContext(node: T): T {
+ const fmt = $getImportContextValue(ImportContextTextFormats);
+ for (const k in fmt) {
+ const textFormat = k as keyof typeof fmt;
+ if (fmt[textFormat]) {
+ node = node.toggleFormat(textFormat);
+ }
+ }
+ return node;
+}
+
+export const ImportChildContext = createImportState(
+ 'childContext',
+ (): undefined | AnyImportStateConfigPairOrUpdater[] => undefined,
+);
+
+export function $addImportChildContext(
+ pairOrUpdater: ContextPairOrUpdater,
+ editor: LexicalEditor = $getEditor(),
+): void {
+ const ctx = getImportContextOrThrow(editor);
+ const childPairs = getOwnContextValue(ctx, ImportChildContext) || [];
+ childPairs.push(pairOrUpdater);
+ setContextValue(ctx, ImportChildContext, childPairs);
+}
+
+export const ImportContextFinalizers = createImportState(
+ 'finalizers',
+ (): undefined | DOMImportContextFinalizer[] => undefined,
+);
+
+export function $addImportContextFinalizer(
+ finalizer: DOMImportContextFinalizer,
+ editor: LexicalEditor = $getEditor(),
+): void {
+ const ctx = getImportContextOrThrow(editor);
+ const finalizers = getOwnContextValue(ctx, ImportContextFinalizers) || [];
+ finalizers.push(finalizer);
+ setContextValue(ctx, ImportContextFinalizers, finalizers);
+}
+
+export const ImportContextWhiteSpaceCollapse = createImportState(
+ 'whiteSpaceCollapse',
+ (): DOMWhiteSpaceCollapse => 'collapse',
+);
+
+export const ImportContextTextWrapMode = createImportState(
+ 'textWrapMode',
+ (): DOMTextWrapMode => 'wrap',
+);
+
+export const ImportContextParentLexicalNode = createImportState(
+ 'parentLexicalNode',
+ (): null | LexicalNode => null,
+);
+export const ImportContextHasBlockAncestorLexicalNode = createImportState(
+ 'hasBlockAncestorLexicalNode',
+ Boolean,
+);
+
+export const ImportContextForChildMap = createImportState(
+ 'forChildMap',
+ (): null | Map => null,
+);
+
+export const ImportContextArtificialNodes = createImportState(
+ 'ArtificialNodes',
+ (): null | ArtificialNode__DO_NOT_USE[] => null,
+);
diff --git a/packages/lexical-html/src/RenderContext.ts b/packages/lexical-html/src/RenderContext.ts
new file mode 100644
index 00000000000..bdf7f9a65d7
--- /dev/null
+++ b/packages/lexical-html/src/RenderContext.ts
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import {
+ getExtensionDependencyFromEditor,
+ LexicalBuilder,
+} from '@lexical/extension';
+import {$getEditor, LexicalEditor} from 'lexical';
+
+import {DOMRenderContextSymbol, DOMRenderExtensionName} from './constants';
+import {
+ $withContext,
+ createContextState,
+ getContextRecord,
+ getContextValue,
+} from './ContextRecord';
+import {DOMRenderExtension} from './DOMRenderExtension';
+import {
+ AnyRenderStateConfigPairOrUpdater,
+ ContextRecord,
+ RenderStateConfig,
+} from './types';
+
+/**
+ * Create a context state to be used during render.
+ *
+ * Note that to support the ValueOrUpdater pattern you can not use a
+ * function for V (but you may wrap it in an array or object).
+ *
+ * @__NO_SIDE_EFFECTS__
+ */
+export function createRenderState(
+ name: string,
+ getDefaultValue: () => V,
+ isEqual?: (a: V, b: V) => boolean,
+): RenderStateConfig {
+ return createContextState(
+ DOMRenderContextSymbol,
+ name,
+ getDefaultValue,
+ isEqual,
+ );
+}
+
+/**
+ * true if the export was initiated from the root of the document
+ */
+export const RenderContextRoot = createRenderState('root', Boolean);
+
+/**
+ * true if this is an export operation ($generateHtmlFromNodes)
+ */
+export const RenderContextExport = createRenderState('isExport', Boolean);
+
+function getDefaultRenderContext(
+ editor: LexicalEditor,
+): undefined | ContextRecord {
+ const builder = LexicalBuilder.maybeFromEditor(editor);
+ return builder && builder.hasExtensionByName(DOMRenderExtensionName)
+ ? getExtensionDependencyFromEditor(editor, DOMRenderExtension).output
+ .defaults
+ : undefined;
+}
+
+function getRenderContext(
+ editor: LexicalEditor,
+): undefined | ContextRecord {
+ return (
+ getContextRecord(DOMRenderContextSymbol, editor) ||
+ getDefaultRenderContext(editor)
+ );
+}
+
+export function $getRenderContextValue(
+ cfg: RenderStateConfig,
+ editor: LexicalEditor = $getEditor(),
+): V {
+ return getContextValue(getRenderContext(editor), cfg);
+}
+
+export const $withRenderContext: (
+ cfg: readonly AnyRenderStateConfigPairOrUpdater[],
+ editor?: LexicalEditor,
+) => (f: () => T) => T = $withContext(
+ DOMRenderContextSymbol,
+ getDefaultRenderContext,
+);
diff --git a/packages/lexical-html/src/__tests__/unit/DOMImportExtension.test.ts b/packages/lexical-html/src/__tests__/unit/DOMImportExtension.test.ts
new file mode 100644
index 00000000000..e167c5058b7
--- /dev/null
+++ b/packages/lexical-html/src/__tests__/unit/DOMImportExtension.test.ts
@@ -0,0 +1,361 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+
+import {$insertGeneratedNodes} from '@lexical/clipboard';
+import {
+ buildEditorFromExtensions,
+ getExtensionDependencyFromEditor,
+} from '@lexical/extension';
+import {
+ $generateNodesFromDOM,
+ DOMImportConfig,
+ DOMImportExtension,
+ DOMRenderConfig,
+ DOMRenderExtension,
+} from '@lexical/html';
+import {CheckListExtension, ListExtension} from '@lexical/list';
+import {
+ $getEditor,
+ $getSelection,
+ $isElementNode,
+ $isRangeSelection,
+ $selectAll,
+ $setSelection,
+ configExtension,
+ defineExtension,
+ LexicalNode,
+} from 'lexical';
+import {
+ expectHtmlToBeEqual,
+ html,
+ // prettifyHtml,
+} from 'lexical/src/__tests__/utils';
+import {assert, describe, expect, test} from 'vitest';
+
+interface ImportTestCase {
+ name: string;
+ pastedHTML: string;
+ expectedHTML: string;
+ plainTextInsert?: string;
+ importConfig?: Partial;
+ exportConfig?: Partial;
+}
+
+function importCase(
+ name: string,
+ pastedHTML: string,
+ expectedHTML: string,
+): ImportTestCase {
+ return {expectedHTML, name, pastedHTML};
+}
+
+describe('DOMImportExtension', () => {
+ test.each([
+ importCase(
+ 'center aligned',
+ html`
+
+ `,
+ html`
+
+ Hello world!
+
+ `,
+ ),
+ importCase(
+ 'reduced ul>li>p',
+ ``,
+ html`
+
+ `,
+ ),
+ {
+ expectedHTML: html`
+ Hello!
+ `,
+ name: 'plain DOM text node',
+ pastedHTML: html`
+ Hello!
+ `,
+ },
+ {
+ expectedHTML: html`
+ Hello!
+
+ `,
+ name: 'a paragraph element',
+ pastedHTML: html`
+ Hello!
+
+ `,
+ },
+ {
+ expectedHTML: html`
+ 123
+ 456
+ `,
+ name: 'a single div',
+ pastedHTML: html`
+ 123
+ 456
+ `,
+ },
+ {
+ expectedHTML: html`
+ a b c d e
+ f g h
+ `,
+ name: 'multiple nested spans and divs',
+ pastedHTML: html`
+
+ a b
+
+ c d
+ e
+
+
+ f
+ g h
+
+
+ `,
+ },
+ {
+ expectedHTML: html`
+ 123
+ 456
+ `,
+ name: 'nested span in a div',
+ pastedHTML: html`
+
+ `,
+ },
+ {
+ expectedHTML: html`
+ 123
+ 456
+ `,
+ name: 'nested div in a span',
+ pastedHTML: html`
+
+ 123
+ 456
+
+ `,
+ },
+ {
+ expectedHTML: html`
+
+
+ done
+
+
+ todo
+
+
+
+
+
+ todo
+
+
+ `,
+ name: 'google doc checklist',
+ // We can't use the HTML template literal formatter here because it's white-space:pre
+ pastedHTML: ` `,
+ },
+ {
+ expectedHTML: html`
+
+ checklist
+
+
+ `,
+ name: 'github checklist',
+ pastedHTML: html`
+
+
+ checklist
+
+
+ `,
+ },
+ {
+ expectedHTML: html`
+
+
+ hello world
+
+
+ `,
+ name: 'pasting inheritance',
+ pastedHTML: html`
+ hello
+ `,
+ plainTextInsert: ' world',
+ },
+ ])(
+ '$name',
+ ({
+ expectedHTML,
+ pastedHTML,
+ plainTextInsert,
+ importConfig = {},
+ exportConfig = {},
+ }: ImportTestCase) => {
+ const builtEditor = buildEditorFromExtensions(
+ defineExtension({
+ $initialEditorState: (editor) => {
+ const parser = new DOMParser();
+ const doc = parser.parseFromString(pastedHTML, 'text/html');
+ const nodes = getExtensionDependencyFromEditor(
+ $getEditor(),
+ DOMImportExtension,
+ ).output.$importNodes(doc);
+
+ // Compare legacy $generateNodesFromDOM to $generateNodes
+ const legacyNodes = $generateNodesFromDOM(editor, doc);
+ expect(nodes.length).toEqual(legacyNodes.length);
+ function compareJSON(a: LexicalNode, b: LexicalNode) {
+ expect(a.exportJSON()).toEqual(b.exportJSON());
+ if ($isElementNode(a) && $isElementNode(b)) {
+ const as = a.getChildren();
+ const bs = b.getChildren();
+ expect(as.length).toEqual(bs.length);
+ for (let i = 0; i < as.length; i++) {
+ compareJSON(as[i], bs[i]);
+ }
+ }
+ }
+ for (let i = 0; i < nodes.length; i++) {
+ compareJSON(nodes[i], legacyNodes[i]);
+ }
+
+ $insertGeneratedNodes(editor, nodes, $selectAll());
+ if (plainTextInsert) {
+ const newSelection = $getSelection();
+ assert(
+ $isRangeSelection(newSelection),
+ 'isRangeSelection(newSelection) for plainTextInsert',
+ );
+ newSelection.insertText(plainTextInsert);
+ }
+ $setSelection(null);
+ },
+ dependencies: [
+ configExtension(DOMImportExtension, importConfig),
+ configExtension(DOMRenderExtension, exportConfig),
+ ListExtension,
+ CheckListExtension,
+ ],
+ name: 'root',
+ theme: {
+ text: {
+ bold: 'editor-text-bold',
+ italic: 'editor-text-italic',
+ underline: 'editor-text-underline',
+ },
+ },
+ }),
+ );
+ const rootElement = document.createElement('div');
+ builtEditor.setRootElement(rootElement);
+ // try {
+ expectHtmlToBeEqual(rootElement.innerHTML, expectedHTML);
+ // } catch (err) {
+ // console.log(prettifyHtml(rootElement.innerHTML));
+ // console.log(prettifyHtml(expectedHTML));
+ // throw err;
+ // }
+ },
+ );
+});
diff --git a/packages/lexical-html/src/__tests__/unit/DOMImportExtensionNoLegacy.test.ts b/packages/lexical-html/src/__tests__/unit/DOMImportExtensionNoLegacy.test.ts
new file mode 100644
index 00000000000..58d065c24e7
--- /dev/null
+++ b/packages/lexical-html/src/__tests__/unit/DOMImportExtensionNoLegacy.test.ts
@@ -0,0 +1,771 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+
+import {$insertGeneratedNodes} from '@lexical/clipboard';
+import {
+ buildEditorFromExtensions,
+ getExtensionDependencyFromEditor,
+} from '@lexical/extension';
+import {
+ $applyTextAlignToElement,
+ $applyTextFormatsFromContext,
+ $generateNodesFromDOM,
+ $getImportContextValue,
+ $setImportContextValue,
+ $updateImportContextValue,
+ type DOMImportConfig,
+ DOMImportExtension,
+ type DOMImportOutput,
+ type DOMRenderConfig,
+ DOMRenderExtension,
+ ImportContextParentLexicalNode,
+ ImportContextTextAlign,
+ ImportContextTextFormats,
+ ImportContextWhiteSpaceCollapse,
+ importOverride,
+} from '@lexical/html';
+import {
+ $createListItemNode,
+ $createListNode,
+ $isListItemNode,
+ $isListNode,
+ CheckListExtension,
+ ListExtension,
+ ListType,
+} from '@lexical/list';
+import {
+ $copyNode,
+ $createLineBreakNode,
+ $createParagraphNode,
+ $createTabNode,
+ $createTextNode,
+ $getChildCaret,
+ $getEditor,
+ $getSelection,
+ $isElementNode,
+ $isRangeSelection,
+ $selectAll,
+ $setSelection,
+ CaretDirection,
+ configExtension,
+ defineExtension,
+ ElementNode,
+ isBlockDomNode,
+ isDOMTextNode,
+ isHTMLElement,
+ isInlineDomNode,
+ LexicalNode,
+ StateConfigValue,
+ TextFormatType,
+ TextNode,
+} from 'lexical';
+import {
+ expectHtmlToBeEqual,
+ html,
+ // prettifyHtml,
+} from 'lexical/src/__tests__/utils';
+import invariant from 'shared/invariant';
+import {assert, describe, expect, test} from 'vitest';
+
+import {$addImportContextFinalizer} from '../../ImportContext';
+
+interface ImportTestCase {
+ name: string;
+ pastedHTML: string;
+ expectedHTML: string;
+ plainTextInsert?: string;
+ importConfig?: Partial;
+ exportConfig?: Partial;
+}
+
+function importCase(
+ name: string,
+ pastedHTML: string,
+ expectedHTML: string,
+): ImportTestCase {
+ return {expectedHTML, name, pastedHTML};
+}
+
+function listTypeFromDOM(dom: HTMLUListElement | HTMLOListElement): ListType {
+ if (
+ // lexical html
+ dom.getAttribute('__lexicallisttype') === 'check' ||
+ // is github checklist
+ dom.classList.contains('contains-task-list') ||
+ // if children are checklist items, the node is a checklist ul. Applicable for googledoc checklist pasting.
+ dom.querySelector(':scope > li[aria-checked]')
+ ) {
+ return 'check';
+ }
+ return dom.tagName === 'OL' ? 'number' : 'bullet';
+}
+
+/*
+ * This function normalizes the children of a ListNode after the conversion from HTML,
+ * ensuring that they are all ListItemNodes
+ */
+function $normalizeListNode(
+ node: null | LexicalNode | LexicalNode[],
+): null | LexicalNode | LexicalNode[] {
+ if (Array.isArray(node) || !$isListNode(node)) {
+ return node;
+ }
+ for (const child of node.getChildren()) {
+ // Wrap all children in li elements
+ if (!$isListItemNode(child)) {
+ const li = $createListItemNode();
+ child.replace(li).append(child);
+ }
+ }
+ // Wrap self in a ListItem if it's directly in a ListNode
+ return $isListNode($getImportContextValue(ImportContextParentLexicalNode))
+ ? $createListItemNode().append(node)
+ : node;
+}
+
+function $isOnlyChild(node: LexicalNode): boolean {
+ return !!(node.getPreviousSibling() || node.getNextSibling());
+}
+
+function $normalizeListItemNode(
+ node: null | LexicalNode | LexicalNode[],
+): null | LexicalNode | LexicalNode[] {
+ if (Array.isArray(node) || !$isListItemNode(node)) {
+ return node;
+ }
+ return $unwrapBlockDOM(
+ node,
+ (el) => !el.isInline() || ($isListNode(el) && !$isOnlyChild(el)),
+ );
+}
+
+function $importListNode(
+ dom: HTMLUListElement | HTMLOListElement,
+): DOMImportOutput {
+ const listNode = $createListNode().setListType(listTypeFromDOM(dom));
+ $addImportContextFinalizer($normalizeListNode);
+ return {node: listNode};
+}
+
+const listOverrides = (['ul', 'ol'] as const).map((tag) =>
+ importOverride(tag, $importListNode),
+);
+
+// https://drafts.csswg.org/css-text-4/#line-break-transform
+// const collapsePreserve = (s: string): string => s;
+// const collapseFunctions: Record string> =
+// {
+// 'break-spaces': collapsePreserve,
+// collapse: (s) => s.replace(/\s+/g, ' '),
+// discard: (s) => s.replace(/\s+/g, ''),
+// preserve: collapsePreserve,
+// 'preserve-breaks': (s) => s.replace(/[ \t]+/g, ' '),
+// 'preserve-spaces': (s) => s.replace(/(?:\r?\n|\t)/g, ' '),
+// };
+
+function $addTextFormatContinue(format: TextFormatType): () => undefined {
+ return () => {
+ $updateImportContextValue(ImportContextTextFormats, (prev) => ({
+ ...prev,
+ [format]: true,
+ }));
+ };
+}
+
+function findTextInLine(text: Text, direction: CaretDirection): null | Text {
+ let node: Node = text;
+ const siblingProp = `${direction}Sibling` as const;
+ const childProp = `${direction === 'next' ? 'first' : 'last'}Child` as const;
+ // eslint-disable-next-line no-constant-condition
+ while (true) {
+ let sibling: null | Node;
+ while ((sibling = node[siblingProp]) === null) {
+ const parentElement = node.parentElement;
+ if (parentElement === null) {
+ return null;
+ }
+ node = parentElement;
+ }
+ node = sibling;
+ if (isHTMLElement(node)) {
+ const display = node.style.display;
+ if (!(display ? display.startsWith('inline') : isInlineDomNode(node))) {
+ return null;
+ }
+ }
+ let descendant: null | Node = node;
+ while ((descendant = node[childProp]) !== null) {
+ node = descendant;
+ }
+ if (isDOMTextNode(node)) {
+ return node;
+ } else if (node.nodeName === 'BR') {
+ return null;
+ }
+ }
+}
+
+function $createTextNodeWithCurrentFormat(text: string = ''): TextNode {
+ return $applyTextFormatsFromContext($createTextNode(text));
+}
+
+function $convertTextDOMNode(domNode: Text): DOMImportOutput {
+ const domNode_ = domNode as Text;
+ const parentDom = domNode.parentElement;
+ invariant(
+ parentDom !== null,
+ 'Expected parentElement of Text not to be null',
+ );
+ let textContent = domNode_.textContent || '';
+ // No collapse and preserve segment break for pre, pre-wrap and pre-line
+ if (
+ $getImportContextValue(ImportContextWhiteSpaceCollapse).startsWith('pre')
+ ) {
+ const parts = textContent.split(/(\r?\n|\t)/);
+ const nodes: Array = [];
+ const length = parts.length;
+ for (let i = 0; i < length; i++) {
+ const part = parts[i];
+ if (part === '\n' || part === '\r\n') {
+ nodes.push($createLineBreakNode());
+ } else if (part === '\t') {
+ nodes.push($createTabNode());
+ } else if (part !== '') {
+ nodes.push($createTextNodeWithCurrentFormat(part));
+ }
+ }
+ return {node: nodes};
+ }
+ textContent = textContent.replace(/\r/g, '').replace(/[ \t\n]+/g, ' ');
+ if (textContent === '') {
+ return {node: null};
+ }
+ if (textContent[0] === ' ') {
+ // Traverse backward while in the same line. If content contains new line or tab -> potential
+ // delete, other elements can borrow from this one. Deletion depends on whether it's also the
+ // last space (see next condition: textContent[textContent.length - 1] === ' '))
+ let previousText: null | Text = domNode_;
+ let isStartOfLine = true;
+ while (
+ previousText !== null &&
+ (previousText = findTextInLine(previousText, 'previous')) !== null
+ ) {
+ const previousTextContent = previousText.textContent || '';
+ if (previousTextContent.length > 0) {
+ if (/[ \t\n]$/.test(previousTextContent)) {
+ textContent = textContent.slice(1);
+ }
+ isStartOfLine = false;
+ break;
+ }
+ }
+ if (isStartOfLine) {
+ textContent = textContent.slice(1);
+ }
+ }
+ if (textContent[textContent.length - 1] === ' ') {
+ // Traverse forward while in the same line, preserve if next inline will require a space
+ let nextText: null | Text = domNode_;
+ let isEndOfLine = true;
+ while (
+ nextText !== null &&
+ (nextText = findTextInLine(nextText, 'next')) !== null
+ ) {
+ const nextTextContent = (nextText.textContent || '').replace(
+ /^( |\t|\r?\n)+/,
+ '',
+ );
+ if (nextTextContent.length > 0) {
+ isEndOfLine = false;
+ break;
+ }
+ }
+ if (isEndOfLine) {
+ textContent = textContent.slice(0, textContent.length - 1);
+ }
+ }
+ if (textContent === '') {
+ return {node: null};
+ }
+ return {node: $createTextNodeWithCurrentFormat(textContent)};
+}
+
+const TO_FORMAT = {
+ code: 'code',
+ em: 'italic',
+ i: 'italic',
+ mark: 'highlight',
+ s: 'strikethrough',
+ strong: 'bold',
+ sub: 'subscript',
+ sup: 'superscript',
+ u: 'underline',
+} as const;
+const formatOverrides = Object.entries(TO_FORMAT).map(([tag, format]) =>
+ importOverride(tag as keyof typeof TO_FORMAT, $addTextFormatContinue(format)),
+);
+
+function $unwrapBlockDOM(
+ node: LexicalNode | LexicalNode[] | null,
+ $splitPredicate: (el: ElementNode) => boolean = (el) => !el.isInline(),
+ $createNextElement: (el: ElementNode) => ElementNode = $copyNode,
+): null | LexicalNode | LexicalNode[] {
+ if (Array.isArray(node) || !$isElementNode(node)) {
+ return node;
+ }
+ let adjacentNodes: undefined | ElementNode[];
+ let lastParent: undefined | ElementNode;
+ for (const {origin} of $getChildCaret(node, 'next')) {
+ if ($isElementNode(origin) && $splitPredicate(origin)) {
+ lastParent = undefined;
+ adjacentNodes = adjacentNodes || [];
+ origin.remove();
+ adjacentNodes.push(origin);
+ } else if (adjacentNodes) {
+ lastParent = lastParent || $createNextElement(node);
+ origin.remove();
+ lastParent.append(origin);
+ }
+ }
+ if (adjacentNodes) {
+ if (node.isEmpty()) {
+ node.remove();
+ } else {
+ adjacentNodes.unshift(node);
+ }
+ }
+ return adjacentNodes || node;
+}
+
+type Writable = {-readonly [K in keyof T]: T[K]};
+
+function $updateFormatContextFromDOM(dom: HTMLElement) {
+ const {fontWeight, fontStyle, textDecoration, verticalAlign} = dom.style;
+ let formats:
+ | undefined
+ | Writable>;
+ const setFormat = (k: TextFormatType, v: boolean) => {
+ const fmt = formats || {};
+ fmt[k] = v;
+ formats = fmt;
+ };
+ switch (fontWeight) {
+ case '400':
+ case 'normal':
+ setFormat('bold', false);
+ break;
+ case '700':
+ case 'bold':
+ setFormat('bold', true);
+ break;
+ default:
+ break;
+ }
+ const italic = 'italic';
+ if (fontStyle === 'normal') {
+ setFormat(italic, false);
+ } else if (fontStyle === italic) {
+ setFormat(italic, true);
+ }
+ const underline = 'underline';
+ const strikethrough = 'strikethrough';
+ for (const dec of textDecoration.split(' ')) {
+ if (dec === 'none') {
+ setFormat(underline, false);
+ setFormat(strikethrough, false);
+ } else if (dec === underline) {
+ setFormat(underline, true);
+ } else if (dec === 'line-through') {
+ setFormat('strikethrough', true);
+ }
+ }
+ if (verticalAlign === 'sub') {
+ setFormat('subscript', true);
+ } else if (verticalAlign === 'super') {
+ setFormat('superscript', true);
+ }
+ if (formats) {
+ $updateImportContextValue(ImportContextTextFormats, (v) => ({
+ ...v,
+ ...formats,
+ }));
+ }
+}
+
+function $updateTextAlignmentContextFromDOM(dom: HTMLElement): void {
+ const {textAlign} = dom.style;
+ switch (textAlign) {
+ case 'center':
+ case 'end':
+ case 'justify':
+ case 'left':
+ case 'right':
+ case 'start':
+ $setImportContextValue(ImportContextTextAlign, textAlign);
+ break;
+ default:
+ break;
+ }
+}
+
+const NO_LEGACY_CONFIG: Partial = {
+ compileLegacyImportNode: () => () => null,
+ overrides: [
+ importOverride('#text', $convertTextDOMNode),
+ importOverride('br', () => ({node: $createLineBreakNode()})),
+ importOverride('*', function $overrideCreateParagraphFromBlock(dom) {
+ if (isBlockDomNode(dom)) {
+ $addImportContextFinalizer($unwrapBlockDOM);
+ return {
+ node: $applyTextAlignToElement($createParagraphNode()),
+ };
+ }
+ }),
+ ...formatOverrides,
+ ...listOverrides,
+ importOverride('li', (dom) => {
+ const node = $applyTextAlignToElement($createListItemNode());
+ let ariaChecked: boolean | undefined;
+ if (dom.ariaChecked === 'true') {
+ ariaChecked = true;
+ } else if (dom.ariaChecked === 'false') {
+ ariaChecked = false;
+ } else {
+ const input: null | HTMLInputElement = dom.querySelector(
+ 'input[type=checkbox]',
+ );
+ if (input) {
+ ariaChecked = input.checked;
+ }
+ }
+ if (ariaChecked !== undefined) {
+ node.setChecked(ariaChecked);
+ }
+ $addImportContextFinalizer($normalizeListItemNode);
+ return {node};
+ }),
+ importOverride(
+ '*',
+ function $overrideBlockFormatAndAlignment(dom): undefined {
+ if (isHTMLElement(dom)) {
+ if (isBlockDomNode(dom)) {
+ $updateTextAlignmentContextFromDOM(dom);
+ }
+ $updateFormatContextFromDOM(dom);
+ }
+ },
+ {priority: 1},
+ ),
+ ],
+};
+
+describe('DOMImportExtension (no legacy)', () => {
+ test.each([
+ importCase(
+ 'center aligned',
+ html`
+
+ `,
+ html`
+
+ Hello world!
+
+ `,
+ ),
+ importCase(
+ 'reduced ul>li>p',
+ ``,
+ html`
+
+ `,
+ ),
+ {
+ expectedHTML: html`
+ Hello!
+ `,
+ name: 'plain DOM text node',
+ pastedHTML: html`
+ Hello!
+ `,
+ },
+ {
+ expectedHTML: html`
+ Hello!
+
+ `,
+ name: 'a paragraph element',
+ pastedHTML: html`
+ Hello!
+
+ `,
+ },
+ {
+ expectedHTML: html`
+ 123
+ 456
+ `,
+ name: 'a single div',
+ pastedHTML: html`
+ 123
+ 456
+ `,
+ },
+ {
+ expectedHTML: html`
+ a b c d e
+ f g h
+ `,
+ name: 'multiple nested spans and divs',
+ pastedHTML: html`
+
+ a b
+
+ c d
+ e
+
+
+ f
+ g h
+
+
+ `,
+ },
+ {
+ expectedHTML: html`
+ 123
+ 456
+ `,
+ name: 'nested span in a div',
+ pastedHTML: html`
+
+ `,
+ },
+ {
+ expectedHTML: html`
+ 123
+ 456
+ `,
+ name: 'nested div in a span',
+ pastedHTML: html`
+
+ 123
+ 456
+
+ `,
+ },
+ {
+ expectedHTML: html`
+
+
+ done
+
+
+ todo
+
+
+
+
+
+ todo
+
+
+ `,
+ name: 'google doc checklist',
+ // We can't use the HTML template literal formatter here because it's white-space:pre
+ pastedHTML: ` `,
+ },
+ {
+ expectedHTML: html`
+
+ checklist
+
+
+ `,
+ name: 'github checklist',
+ pastedHTML: html`
+
+
+ checklist
+
+
+ `,
+ },
+ {
+ expectedHTML: html`
+
+
+ hello world
+
+
+ `,
+ name: 'pasting inheritance',
+ pastedHTML: html`
+ hello
+ `,
+ plainTextInsert: ' world',
+ },
+ ])(
+ '$name',
+ ({
+ expectedHTML,
+ pastedHTML,
+ plainTextInsert,
+ importConfig = {},
+ exportConfig = {},
+ }: ImportTestCase) => {
+ const builtEditor = buildEditorFromExtensions(
+ defineExtension({
+ $initialEditorState: (editor) => {
+ const parser = new DOMParser();
+ const doc = parser.parseFromString(pastedHTML, 'text/html');
+ const nodes = getExtensionDependencyFromEditor(
+ $getEditor(),
+ DOMImportExtension,
+ ).output.$importNodes(doc);
+
+ // Compare legacy $generateNodesFromDOM to $generateNodes
+ const legacyNodes = $generateNodesFromDOM(editor, doc);
+ expect(nodes.length).toEqual(legacyNodes.length);
+ function compareJSON(a: LexicalNode, b: LexicalNode) {
+ expect(a.exportJSON()).toEqual(b.exportJSON());
+ if ($isElementNode(a) && $isElementNode(b)) {
+ const as = a.getChildren();
+ const bs = b.getChildren();
+ expect(as.length).toEqual(bs.length);
+ for (let i = 0; i < as.length; i++) {
+ compareJSON(as[i], bs[i]);
+ }
+ }
+ }
+ for (let i = 0; i < nodes.length; i++) {
+ compareJSON(nodes[i], legacyNodes[i]);
+ }
+
+ $insertGeneratedNodes(editor, nodes, $selectAll());
+ if (plainTextInsert) {
+ const newSelection = $getSelection();
+ assert(
+ $isRangeSelection(newSelection),
+ 'isRangeSelection(newSelection) for plainTextInsert',
+ );
+ newSelection.insertText(plainTextInsert);
+ }
+ $setSelection(null);
+ },
+ dependencies: [
+ configExtension(DOMImportExtension, NO_LEGACY_CONFIG, importConfig),
+ configExtension(DOMRenderExtension, exportConfig),
+ ListExtension,
+ CheckListExtension,
+ ],
+ name: 'root',
+ theme: {
+ text: {
+ bold: 'editor-text-bold',
+ italic: 'editor-text-italic',
+ underline: 'editor-text-underline',
+ },
+ },
+ }),
+ );
+ const rootElement = document.createElement('div');
+ builtEditor.setRootElement(rootElement);
+ // try {
+ expectHtmlToBeEqual(rootElement.innerHTML, expectedHTML);
+ // } catch (err) {
+ // console.log(prettifyHtml(rootElement.innerHTML));
+ // console.log(prettifyHtml(expectedHTML));
+ // throw err;
+ // }
+ },
+ );
+});
diff --git a/packages/lexical-html/src/__tests__/unit/DOMRenderExtension.test.ts b/packages/lexical-html/src/__tests__/unit/DOMRenderExtension.test.ts
new file mode 100644
index 00000000000..d4ce0c3a5ab
--- /dev/null
+++ b/packages/lexical-html/src/__tests__/unit/DOMRenderExtension.test.ts
@@ -0,0 +1,277 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+
+import {buildEditorFromExtensions} from '@lexical/extension';
+import {
+ $generateDOMFromRoot,
+ $getRenderContextValue,
+ domOverride,
+ DOMRenderExtension,
+ RenderContextRoot,
+} from '@lexical/html';
+import {
+ $create,
+ $createLineBreakNode,
+ $createParagraphNode,
+ $createTextNode,
+ $getRoot,
+ $getState,
+ $getStateChange,
+ $setState,
+ configExtension,
+ createState,
+ defineExtension,
+ isHTMLElement,
+ TextNode,
+} from 'lexical';
+import {expectHtmlToBeEqual, html} from 'lexical/src/__tests__/utils';
+import {describe, expect, test} from 'vitest';
+
+const idState = createState('id', {
+ parse: (v) => (typeof v === 'string' ? v : null),
+});
+
+describe('DOMRenderExtension', () => {
+ test('can override DOM create + update', () => {
+ const editor = buildEditorFromExtensions(
+ defineExtension({
+ $initialEditorState: () => {
+ const root = $getRoot();
+ $setState(root, idState, 'root').append(
+ $setState($createParagraphNode(), idState, 'paragraph').append(
+ $setState($createTextNode('text!'), idState, 'text'),
+ ),
+ );
+ },
+ dependencies: [
+ configExtension(DOMRenderExtension, {
+ overrides: [
+ domOverride('*', {
+ $createDOM(node, $next) {
+ const result = $next();
+ const id = $getState(node, idState);
+ if (id) {
+ result.setAttribute('id', id);
+ }
+ return result;
+ },
+ $updateDOM(nextNode, prevNode, dom, $next) {
+ if ($next()) {
+ return true;
+ }
+ const change = $getStateChange(nextNode, prevNode, idState);
+ if (change) {
+ const [id] = change;
+ if (id) {
+ dom.setAttribute('id', id);
+ } else {
+ dom.removeAttribute('id');
+ }
+ }
+ return false;
+ },
+ }),
+ ],
+ }),
+ ],
+ name: 'root',
+ }),
+ );
+ const root = document.createElement('div');
+ editor.setRootElement(root);
+ expect(
+ editor.read(() => {
+ expectHtmlToBeEqual(
+ root.innerHTML,
+ html`
+
+ text!
+
+ `,
+ );
+ }),
+ );
+ editor.update(
+ () =>
+ $getRoot()
+ .getAllTextNodes()
+ .forEach((node) =>
+ $setState(node, idState, (prev) => `${prev}-updated`),
+ ),
+ {discrete: true},
+ );
+ // Update works too
+ expect(
+ editor.read(() => {
+ expectHtmlToBeEqual(
+ root.innerHTML,
+ html`
+
+ text!
+
+ `,
+ );
+ }),
+ );
+ editor.update(
+ () =>
+ $getRoot()
+ .getAllTextNodes()
+ .forEach((node) => $setState(node, idState, null)),
+ {discrete: true},
+ );
+ expect(
+ editor.read(() => {
+ expectHtmlToBeEqual(
+ root.innerHTML,
+ html`
+
+ text!
+
+ `,
+ );
+ }),
+ );
+ });
+ test('can override DOM export', () => {
+ const editor = buildEditorFromExtensions(
+ defineExtension({
+ $initialEditorState: () => {
+ const root = $getRoot();
+ $setState(root, idState, 'root').append(
+ $setState($createParagraphNode(), idState, 'paragraph').append(
+ $setState($createTextNode('text!'), idState, 'text'),
+ ),
+ );
+ },
+ dependencies: [
+ configExtension(DOMRenderExtension, {
+ overrides: [
+ domOverride('*', {
+ $exportDOM(node, $next) {
+ const result = $next();
+ const id = $getState(node, idState);
+ if (id && isHTMLElement(result.element)) {
+ result.element.setAttribute('id', id);
+ }
+ return result;
+ },
+ }),
+ domOverride([TextNode], {
+ $exportDOM(node, $next) {
+ const result = $next();
+ if (
+ $getRenderContextValue(RenderContextRoot) &&
+ isHTMLElement(result.element) &&
+ result.element.style.getPropertyValue('white-space') ===
+ 'pre-wrap' &&
+ // we know there aren't tabs or newlines but if there are
+ // leading, trailing, or adjacent spaces then we need the
+ // pre-wrap to preserve the content
+ !/^\s|\s$|\s\s/.test(result.element.textContent)
+ ) {
+ result.element.style.setProperty('white-space', null);
+ if (result.element.style.cssText === '') {
+ result.element.removeAttribute('style');
+ }
+ }
+ return result;
+ },
+ }),
+ ],
+ }),
+ ],
+ name: 'root',
+ }),
+ );
+ expect(
+ editor.read(() => {
+ expectHtmlToBeEqual(
+ $generateDOMFromRoot(document.createElement('div')).innerHTML,
+ html`
+
+ `,
+ );
+ }),
+ );
+ });
+ test('type merge', () => {
+ class TextNodeA extends TextNode {
+ $config() {
+ return this.config('text-a', {extends: TextNode});
+ }
+ }
+ const editor = buildEditorFromExtensions(
+ defineExtension({
+ $initialEditorState: () => {
+ $getRoot().append(
+ $createParagraphNode().append(
+ $create(TextNodeA).setTextContent('text a'),
+ $createLineBreakNode(),
+ $createTextNode().setTextContent('plain text'),
+ ),
+ );
+ },
+ dependencies: [
+ configExtension(DOMRenderExtension, {
+ overrides: [
+ domOverride([TextNode], {
+ $exportDOM(node) {
+ const span = document.createElement('span');
+ span.append(node.getTextContent());
+ return {element: span};
+ },
+ }),
+ domOverride([TextNodeA], {
+ $exportDOM(node) {
+ const span = document.createElement('span');
+ span.append(node.getTextContent());
+ span.dataset.lexicalType = node.getType();
+ return {element: span};
+ },
+ }),
+ domOverride([TextNode], {
+ $exportDOM(node, $next) {
+ const r = $next();
+ if (isHTMLElement(r.element)) {
+ r.element.dataset.didOverride = 'true';
+ }
+ return r;
+ },
+ }),
+ ],
+ }),
+ ],
+ name: 'root',
+ nodes: [TextNodeA],
+ }),
+ );
+ expect(
+ editor.read(() => {
+ expectHtmlToBeEqual(
+ $generateDOMFromRoot(document.createElement('div')).innerHTML,
+ html`
+
+
+
+ text a
+
+
+ plain text
+
+
+ `,
+ );
+ }),
+ );
+ });
+});
diff --git a/packages/lexical-html/src/__tests__/unit/compileDOMRenderConfigOverrides.test.ts b/packages/lexical-html/src/__tests__/unit/compileDOMRenderConfigOverrides.test.ts
new file mode 100644
index 00000000000..ebceebf0768
--- /dev/null
+++ b/packages/lexical-html/src/__tests__/unit/compileDOMRenderConfigOverrides.test.ts
@@ -0,0 +1,182 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+
+import {buildEditorFromExtensions} from '@lexical/extension';
+import {domOverride} from '@lexical/html';
+import {
+ $isLineBreakNode,
+ isHTMLElement,
+ LineBreakNode,
+ ParagraphNode,
+ TabNode,
+ TextNode,
+} from 'lexical';
+import {describe, expect, test} from 'vitest';
+
+import {
+ buildTypeTree,
+ precompileDOMRenderConfigOverrides,
+} from '../../compileDOMRenderConfigOverrides';
+import {ALWAYS_TRUE} from '../../constants';
+
+describe('buildTypeTree', () => {
+ test('includes basic types', () => {
+ const editor = buildEditorFromExtensions();
+ expect(buildTypeTree(editor._createEditorArgs!)).toMatchObject({
+ linebreak: {
+ klass: LineBreakNode,
+ types: {
+ linebreak: true,
+ },
+ },
+ paragraph: {
+ klass: ParagraphNode,
+ types: {paragraph: true},
+ },
+ tab: {klass: TabNode, types: {tab: true}},
+ text: {klass: TextNode, types: {tab: true, text: true}},
+ });
+ });
+});
+
+describe('precompileDOMRenderConfigOverrides', () => {
+ test('precompiles with only type overrides', () => {
+ class TextNodeA extends TextNode {
+ $config() {
+ return this.config('text-a', {extends: TextNode});
+ }
+ }
+ const overrides = [
+ domOverride([TextNode], {
+ $exportDOM(node) {
+ const span = document.createElement('span');
+ span.append(node.getTextContent());
+ return {element: span};
+ },
+ }),
+ domOverride([TextNodeA], {
+ $exportDOM(node) {
+ const span = document.createElement('span');
+ span.append(node.getTextContent());
+ span.dataset.lexicalType = node.getType();
+ return {element: span};
+ },
+ }),
+ domOverride([TextNode], {
+ $exportDOM(node, $next) {
+ const r = $next();
+ if (isHTMLElement(r.element)) {
+ r.element.dataset.didOverride = 'true';
+ }
+ return r;
+ },
+ }),
+ ];
+ const prerender = precompileDOMRenderConfigOverrides(
+ {nodes: [TextNode, TextNodeA]},
+ overrides,
+ );
+ expect(prerender).toEqual({
+ $createDOM: [],
+ $exportDOM: [
+ [
+ 'types',
+ {
+ text: [overrides[0].$exportDOM, overrides[2].$exportDOM],
+ 'text-a': [
+ overrides[0].$exportDOM,
+ overrides[1].$exportDOM,
+ overrides[2].$exportDOM,
+ ],
+ },
+ ],
+ ],
+ $extractWithChild: [],
+ $getDOMSlot: [],
+ $shouldExclude: [],
+ $shouldInclude: [],
+ $updateDOM: [],
+ });
+ });
+ test('precompiles with wildcards, predicates, and type overrides', () => {
+ class TextNodeA extends TextNode {
+ $config() {
+ return this.config('text-a', {extends: TextNode});
+ }
+ }
+ const overrides = [
+ domOverride([TextNode], {
+ $exportDOM(node) {
+ const span = document.createElement('span');
+ span.append(node.getTextContent());
+ return {element: span};
+ },
+ }),
+ domOverride('*', {
+ $createDOM(node, $next) {
+ return $next();
+ },
+ $exportDOM(node, $next) {
+ return $next();
+ },
+ }),
+ domOverride([TextNodeA], {
+ $exportDOM(node) {
+ const span = document.createElement('span');
+ span.append(node.getTextContent());
+ span.dataset.lexicalType = node.getType();
+ return {element: span};
+ },
+ }),
+ domOverride([TextNode], {
+ $exportDOM(node, $next) {
+ const r = $next();
+ if (isHTMLElement(r.element)) {
+ r.element.dataset.didOverride = 'true';
+ }
+ return r;
+ },
+ }),
+ domOverride([$isLineBreakNode], {
+ $exportDOM(node, $next) {
+ return $next();
+ },
+ }),
+ ];
+ const prerender = precompileDOMRenderConfigOverrides(
+ {nodes: [TextNode, TextNodeA]},
+ overrides,
+ );
+ expect(prerender).toEqual({
+ $createDOM: [[ALWAYS_TRUE, overrides[1].$createDOM]],
+ $exportDOM: [
+ [
+ 'types',
+ {
+ text: [overrides[0].$exportDOM],
+ 'text-a': [overrides[0].$exportDOM],
+ },
+ ],
+ [ALWAYS_TRUE, overrides[1].$exportDOM],
+ [
+ 'types',
+ {
+ text: [overrides[3].$exportDOM],
+ 'text-a': [overrides[2].$exportDOM, overrides[3].$exportDOM],
+ },
+ ],
+ [$isLineBreakNode, overrides[4].$exportDOM],
+ ],
+ $extractWithChild: [],
+ $getDOMSlot: [],
+ $shouldExclude: [],
+ $shouldInclude: [],
+ $updateDOM: [],
+ });
+ });
+});
diff --git a/packages/lexical-html/src/compileDOMImportOverrides.ts b/packages/lexical-html/src/compileDOMImportOverrides.ts
new file mode 100644
index 00000000000..c61a4496726
--- /dev/null
+++ b/packages/lexical-html/src/compileDOMImportOverrides.ts
@@ -0,0 +1,390 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import type {
+ AnyImportStateConfigPairOrUpdater,
+ ContextRecord,
+ DOMImportConfig,
+ DOMImportConfigMatch,
+ DOMImportContextFinalizer,
+ DOMImportExtensionOutput,
+ DOMImportOutput,
+ DOMTextWrapMode,
+ DOMWhiteSpaceCollapse,
+} from './types';
+
+import {
+ $isBlockElementNode,
+ $isElementNode,
+ $isRootOrShadowRoot,
+ ArtificialNode__DO_NOT_USE,
+ isDOMDocumentNode,
+ isHTMLElement,
+ type LexicalEditor,
+ type LexicalNode,
+} from 'lexical';
+import invariant from 'shared/invariant';
+
+import {$unwrapArtificialNodes} from './$unwrapArtificialNodes';
+import {
+ ALWAYS_NULL,
+ DOMImportContextSymbol,
+ DOMTextWrapModeKeys,
+ DOMWhiteSpaceCollapseKeys,
+ EMPTY_ARRAY,
+} from './constants';
+import {
+ $withFullContext,
+ contextValue,
+ createChildContext,
+ popOwnContextValue,
+ updateContextFromPairs,
+} from './ContextRecord';
+import {
+ $getImportContextValue,
+ ImportChildContext,
+ ImportContextArtificialNodes,
+ ImportContextDOMNode,
+ ImportContextFinalizers,
+ ImportContextHasBlockAncestorLexicalNode,
+ ImportContextParentLexicalNode,
+ ImportContextTextWrapMode,
+ ImportContextWhiteSpaceCollapse,
+} from './ImportContext';
+
+class MatchesImport {
+ tag: Tag;
+ matches: DOMImportConfigMatch[] = [];
+ constructor(tag: Tag) {
+ this.tag = tag;
+ }
+ push(match: DOMImportConfigMatch) {
+ invariant(
+ match.tag === this.tag,
+ 'MatchesImport.push: match tag %s !== this tag %s',
+ match.tag,
+ this.tag,
+ );
+ this.matches.push(match);
+ }
+ compile(
+ $nextImport: (node: Node) => null | undefined | DOMImportOutput,
+ editor: LexicalEditor,
+ ): (node: Node) => null | undefined | DOMImportOutput {
+ const {matches, tag} = this;
+ return (node) => {
+ const el = isHTMLElement(node) ? node : null;
+ const $importAt = (start: number): null | undefined | DOMImportOutput => {
+ let rval: undefined | null | DOMImportOutput;
+ let $importFallback = $nextImport;
+ for (
+ let i = start;
+ i >= 0 && !rval && $importFallback !== ALWAYS_NULL;
+ i--
+ ) {
+ const match = matches[i];
+ if (match) {
+ const {$import, selector} = matches[i];
+ if (!selector || (el && el.matches(selector))) {
+ rval = $import(
+ node,
+ () => {
+ $importFallback = ALWAYS_NULL;
+ return $importAt(i - 1);
+ },
+ editor,
+ );
+ }
+ }
+ }
+ return rval || $importFallback(node);
+ };
+
+ return $importAt(
+ (tag === node.nodeName.toLowerCase() || (el && tag === '*')
+ ? matches.length
+ : 0) - 1,
+ );
+ };
+ }
+}
+
+class TagImport {
+ tags: Map> = new Map();
+ push(match: DOMImportConfigMatch) {
+ invariant(
+ match.tag !== '*',
+ 'TagImport can not handle wildcard tag %s',
+ match.tag,
+ );
+ const matches = this.tags.get(match.tag) || new MatchesImport(match.tag);
+ this.tags.set(match.tag, matches);
+ matches.push(match);
+ }
+ compile(
+ $nextImport: (node: Node) => null | undefined | DOMImportOutput,
+ editor: LexicalEditor,
+ ): DOMImportExtensionOutput['$importNode'] {
+ const compiled = new Map();
+ for (const [tag, matches] of this.tags.entries()) {
+ compiled.set(tag, matches.compile($nextImport, editor));
+ }
+ return compiled.size === 0
+ ? $nextImport
+ : (node: Node) =>
+ (compiled.get(node.nodeName.toLowerCase()) || $nextImport)(node);
+ }
+}
+
+/**
+ * Sort matches by lowest priority first. This is to preserve the invariant
+ * that overrides added "later" (closer to the root of the extension tree,
+ * or later in a given array) should run at a higher priority.
+ *
+ * For example given the overrides `[a,b,c]` it is expected that the execution
+ * order is `c -> b -> a` assuming equal priorities. This is because the
+ * "least specific" behavior is going to be naturally "earlier" in the array
+ * (e.g. the initial implementation).
+ */
+function importOverrideSort(
+ a: DOMImportConfigMatch,
+ b: DOMImportConfigMatch,
+): number {
+ return (a.priority || 0) - (b.priority || 0);
+}
+
+type ImportStackEntry = [
+ dom: Node,
+ ctx: ContextRecord,
+ $importNode: DOMImportExtensionOutput['$importNode'],
+ $appendChild: NonNullable,
+];
+
+function parseDOMWhiteSpaceCollapseFromNode(
+ ctx: ContextRecord,
+ node: Node,
+): ContextRecord {
+ if (isHTMLElement(node)) {
+ const {style} = node;
+ let textWrapMode: undefined | DOMTextWrapMode;
+ let whiteSpaceCollapse: undefined | DOMWhiteSpaceCollapse;
+ switch (style.whiteSpace) {
+ case 'normal':
+ whiteSpaceCollapse = 'collapse';
+ textWrapMode = 'wrap';
+ break;
+ case 'pre':
+ whiteSpaceCollapse = 'preserve';
+ textWrapMode = 'nowrap';
+ break;
+ case 'pre-wrap':
+ whiteSpaceCollapse = 'preserve';
+ textWrapMode = 'wrap';
+ break;
+ case 'pre-line':
+ whiteSpaceCollapse = 'preserve-breaks';
+ textWrapMode = 'nowrap';
+ break;
+ default:
+ break;
+ }
+ whiteSpaceCollapse =
+ (
+ DOMWhiteSpaceCollapseKeys as Record<
+ string,
+ undefined | DOMWhiteSpaceCollapse
+ >
+ )[style.whiteSpaceCollapse] || whiteSpaceCollapse;
+ textWrapMode =
+ (DOMTextWrapModeKeys as Record)[
+ style.textWrapMode
+ ] || textWrapMode;
+ if (textWrapMode) {
+ ctx[ImportContextTextWrapMode.key] = textWrapMode;
+ }
+ if (whiteSpaceCollapse) {
+ ctx[ImportContextWhiteSpaceCollapse.key] = whiteSpaceCollapse;
+ }
+ }
+ return ctx;
+}
+
+function makeFinalizer(
+ outputNode: null | LexicalNode | LexicalNode[],
+ finalizers: DOMImportContextFinalizer[],
+): () => DOMImportOutput {
+ return () => {
+ let node = outputNode;
+ for (
+ let finalizer = finalizers.pop();
+ finalizer;
+ finalizer = finalizers.pop()
+ ) {
+ node = finalizer(node);
+ }
+ return {childNodes: EMPTY_ARRAY, node};
+ };
+}
+
+function compileImportNodes(
+ editor: LexicalEditor,
+ $importNode: DOMImportExtensionOutput['$importNode'],
+) {
+ return function $importNodes(
+ rootOrDocument: ParentNode | Document,
+ ): LexicalNode[] {
+ const artificialNodes: ArtificialNode__DO_NOT_USE[] = [];
+ const nodes: LexicalNode[] = [];
+ const rootNode = isDOMDocumentNode(rootOrDocument)
+ ? rootOrDocument.body
+ : rootOrDocument;
+ const stack: ImportStackEntry[] = [
+ [
+ rootNode,
+ updateContextFromPairs(createChildContext(undefined), [
+ contextValue(ImportContextArtificialNodes, artificialNodes),
+ ]),
+ () => ({node: null}),
+ (node) => {
+ nodes.push(node);
+ },
+ ],
+ ];
+ for (let entry = stack.pop(); entry; entry = stack.pop()) {
+ const [node, ctx, fn, $parentAppendChild] = entry;
+ ctx[ImportContextDOMNode.key] = node;
+ parseDOMWhiteSpaceCollapseFromNode(ctx, node);
+ let childContext:
+ | undefined
+ | ContextRecord;
+ const updateChildContext = (
+ pairs: undefined | readonly AnyImportStateConfigPairOrUpdater[],
+ ) => {
+ if (pairs) {
+ childContext = updateContextFromPairs(
+ childContext || createChildContext(ctx),
+ pairs,
+ );
+ }
+ };
+ const output = $withFullContext(
+ DOMImportContextSymbol,
+ ctx,
+ fn.bind(null, node),
+ editor,
+ );
+ let children: NodeListOf | readonly ChildNode[] =
+ isHTMLElement(node) ? node.childNodes : EMPTY_ARRAY;
+ let $appendChild = $parentAppendChild;
+ updateChildContext(popOwnContextValue(ctx, ImportChildContext));
+ delete ctx[ImportChildContext.key];
+ if (output) {
+ const outputNode = output.node;
+ if (output.$appendChild) {
+ $appendChild = output.$appendChild;
+ } else if (Array.isArray(outputNode)) {
+ $appendChild = (childNode, _dom) => outputNode.push(childNode);
+ } else if ($isElementNode(outputNode)) {
+ $appendChild = (childNode, _dom) => outputNode.append(childNode);
+ }
+ children = output.childNodes || children;
+ const finalizers = popOwnContextValue(ctx, ImportContextFinalizers);
+ if (finalizers && finalizers.length > 0) {
+ stack.push([
+ node,
+ ctx,
+ makeFinalizer(outputNode, finalizers),
+ $parentAppendChild,
+ ]);
+ } else if (outputNode) {
+ for (const addNode of Array.isArray(outputNode)
+ ? outputNode
+ : [outputNode]) {
+ $parentAppendChild(addNode, node as ChildNode);
+ }
+ }
+
+ const currentLexicalNode = Array.isArray(outputNode)
+ ? outputNode[outputNode.length - 1] || null
+ : outputNode;
+ const hasBlockAncestorLexicalNode = $getImportContextValue(
+ ImportContextHasBlockAncestorLexicalNode,
+ );
+ const hasBlockAncestorLexicalNodeForChildren =
+ currentLexicalNode && $isRootOrShadowRoot(currentLexicalNode)
+ ? false
+ : (currentLexicalNode && $isBlockElementNode(currentLexicalNode)) ||
+ hasBlockAncestorLexicalNode;
+
+ if (
+ hasBlockAncestorLexicalNode !== hasBlockAncestorLexicalNodeForChildren
+ ) {
+ updateChildContext([
+ contextValue(
+ ImportContextHasBlockAncestorLexicalNode,
+ hasBlockAncestorLexicalNodeForChildren,
+ ),
+ ]);
+ }
+ if ($isElementNode(currentLexicalNode)) {
+ updateChildContext([
+ contextValue(ImportContextParentLexicalNode, currentLexicalNode),
+ ]);
+ }
+ }
+ // Push children in reverse so they are popped off the stack in-order
+ for (let i = children.length - 1; i >= 0; i--) {
+ const childDom = children[i];
+ stack.push([
+ childDom,
+ createChildContext(childContext || ctx),
+ $importNode,
+ $appendChild,
+ ]);
+ }
+ }
+ $unwrapArtificialNodes(artificialNodes);
+ return nodes;
+ };
+}
+
+function matchHasTag(
+ match: DOMImportConfigMatch,
+ tag: T,
+): match is DOMImportConfigMatch & {tag: T} {
+ return match.tag === tag;
+}
+
+function compileImportNode(editor: LexicalEditor, config: DOMImportConfig) {
+ let $importNode = config.compileLegacyImportNode(editor);
+ let importer: TagImport | MatchesImport<'*'> = new TagImport();
+ const sortedOverrides = config.overrides.sort(importOverrideSort);
+ for (const match of sortedOverrides) {
+ if (matchHasTag(match, '*')) {
+ if (importer instanceof TagImport) {
+ $importNode = importer.compile($importNode, editor);
+ importer = new MatchesImport(match.tag);
+ }
+ } else if (importer instanceof MatchesImport) {
+ $importNode = importer.compile($importNode, editor);
+ importer = new TagImport();
+ }
+ importer.push(match);
+ }
+ return importer.compile($importNode, editor);
+}
+
+export function compileDOMImportOverrides(
+ editor: LexicalEditor,
+ config: DOMImportConfig,
+): DOMImportExtensionOutput {
+ const $importNode = compileImportNode(editor, config);
+ return {
+ $importNode,
+ $importNodes: compileImportNodes(editor, $importNode),
+ };
+}
diff --git a/packages/lexical-html/src/compileDOMRenderConfigOverrides.ts b/packages/lexical-html/src/compileDOMRenderConfigOverrides.ts
new file mode 100644
index 00000000000..9417cb24021
--- /dev/null
+++ b/packages/lexical-html/src/compileDOMRenderConfigOverrides.ts
@@ -0,0 +1,318 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import {getKnownTypesAndNodes} from '@lexical/extension';
+import {
+ $isLexicalNode,
+ DEFAULT_EDITOR_DOM_CONFIG,
+ type EditorDOMRenderConfig,
+ getStaticNodeConfig,
+ InitialEditorConfig,
+ Klass,
+ LexicalEditor,
+ type LexicalNode,
+} from 'lexical';
+import invariant from 'shared/invariant';
+
+import {ALWAYS_TRUE} from './constants';
+import {AnyDOMRenderMatch, DOMRenderConfig, DOMRenderMatch} from './types';
+
+interface TypeRecord {
+ readonly klass: Klass;
+ readonly types: {[NodeAndSubclasses in string]?: boolean};
+}
+
+type TypeTree = {
+ [NodeType in string]?: TypeRecord;
+};
+
+export function buildTypeTree(
+ editorConfig: Pick,
+): TypeTree {
+ const t: TypeTree = {};
+ const {nodes} = getKnownTypesAndNodes(editorConfig);
+ for (const klass of nodes) {
+ const type = klass.getType();
+ t[type] = {klass, types: {}};
+ }
+ for (const baseRec of Object.values(t)) {
+ if (baseRec) {
+ const baseType = baseRec.klass.getType();
+ for (
+ let {klass} = baseRec;
+ $isLexicalNode(klass.prototype);
+ klass = Object.getPrototypeOf(klass)
+ ) {
+ const {ownNodeType} = getStaticNodeConfig(klass);
+ const superRec = ownNodeType && t[ownNodeType];
+ if (superRec) {
+ superRec.types[baseType] = true;
+ }
+ }
+ }
+ }
+ return t;
+}
+
+type PredicateOrTypes =
+ | ((node: LexicalNode) => boolean)
+ | {[NodeType in string]?: true};
+type TypeRender = {[NodeType in string]?: T[]};
+type AnyRender =
+ | readonly [(node: LexicalNode) => boolean, T]
+ | readonly ['types', TypeRender];
+
+type PreEditorDOMRenderConfig = {
+ [K in keyof EditorDOMRenderConfig]: AnyRender[];
+};
+
+function buildNodePredicate(klass: Klass) {
+ return (node: LexicalNode): node is T => node instanceof klass;
+}
+
+function getPredicate(
+ typeTree: TypeTree,
+ {nodes}: DOMRenderMatch,
+): {[NodeType in string]?: true} | ((node: LexicalNode) => boolean) {
+ if (nodes === '*') {
+ return ALWAYS_TRUE;
+ }
+ let types: undefined | {[NodeType in string]?: true} = {};
+ const predicates: ((node: LexicalNode) => boolean)[] = [];
+ for (const klassOrPredicate of nodes) {
+ if ('getType' in klassOrPredicate) {
+ const type = klassOrPredicate.getType();
+ if (types) {
+ const tree = typeTree[type];
+ invariant(
+ tree !== undefined,
+ 'Node class %s with type %s not registered in editor',
+ klassOrPredicate.name,
+ type,
+ );
+ types = Object.assign(types, tree.types);
+ }
+ predicates.push(buildNodePredicate(klassOrPredicate));
+ } else {
+ types = undefined;
+ predicates.push(klassOrPredicate);
+ }
+ }
+ if (types) {
+ return types;
+ } else if (predicates.length === 1) {
+ return predicates[0];
+ }
+ return (node: LexicalNode): boolean => {
+ for (const predicate of predicates) {
+ if (predicate(node)) {
+ return true;
+ }
+ }
+ return false;
+ };
+}
+
+function makePrerender(): PreEditorDOMRenderConfig {
+ return {
+ $createDOM: [],
+ $exportDOM: [],
+ $extractWithChild: [],
+ $getDOMSlot: [],
+ $shouldExclude: [],
+ $shouldInclude: [],
+ $updateDOM: [],
+ };
+}
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+type AccFn = (
+ node: N,
+ ...rest: [...Args, editor: LexicalEditor]
+) => T;
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+type GetOverrideFn = (
+ n: N,
+) => undefined | OverrideFn;
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+type OverrideFn = (
+ node: N,
+ ...rest: [...Args, $next: () => T, editor: LexicalEditor]
+) => T;
+
+function ignoreNext2(
+ acc: AccFn,
+): OverrideFn {
+ return (node: N, _$next: () => T, editor: LexicalEditor) => acc(node, editor);
+}
+function ignoreNext3(
+ acc: AccFn,
+): OverrideFn {
+ return (node: N, a: A, _$next: () => T, editor: LexicalEditor) =>
+ acc(node, a, editor);
+}
+function ignoreNext4(
+ acc: AccFn,
+): OverrideFn {
+ return (node: N, a: A, b: B, _$next: () => T, editor: LexicalEditor) =>
+ acc(node, a, b, editor);
+}
+function ignoreNext5(
+ acc: AccFn,
+): OverrideFn {
+ return (node: N, a: A, b: B, c: C, _$next: () => T, editor: LexicalEditor) =>
+ acc(node, a, b, c, editor);
+}
+
+function merge2(
+ $acc: AccFn,
+ $getOverride: GetOverrideFn,
+): typeof $acc {
+ return (node, editor) => {
+ const $next = () => $acc(node, editor);
+ const $override = $getOverride(node);
+ return $override ? $override(node, $next, editor) : $next();
+ };
+}
+
+function merge3(
+ acc: AccFn,
+ $getOverride: GetOverrideFn,
+): typeof acc {
+ return (node, a, editor) => {
+ const $next = () => acc(node, a, editor);
+ const $override = $getOverride(node);
+ return $override ? $override(node, a, $next, editor) : $next();
+ };
+}
+
+function merge4(
+ $acc: AccFn,
+ $getOverride: GetOverrideFn,
+): typeof $acc {
+ return (node, a, b, editor) => {
+ const $next = () => $acc(node, a, b, editor);
+ const $override = $getOverride(node);
+ return $override ? $override(node, a, b, $next, editor) : $next();
+ };
+}
+
+function merge5(
+ acc: AccFn,
+ $getOverride: GetOverrideFn,
+): typeof acc {
+ return (node, a, b, c, editor) => {
+ const $next = () => acc(node, a, b, c, editor);
+ const $override = $getOverride(node);
+ return $override ? $override(node, a, b, c, $next, editor) : $next();
+ };
+}
+
+function compilePrerenderKey(
+ prerender: PreEditorDOMRenderConfig,
+ k: K,
+ defaults: EditorDOMRenderConfig,
+ mergeFunction: (
+ $acc: EditorDOMRenderConfig[K],
+ $getOverride: (node: LexicalNode) => AnyDOMRenderMatch[K],
+ ) => typeof $acc,
+ ignoreNextFunction: (fn: EditorDOMRenderConfig[K]) => AnyDOMRenderMatch[K],
+): void {
+ let acc = defaults[k];
+ for (const pair of prerender[k]) {
+ if (typeof pair[0] === 'function') {
+ const [$predicate, $override] = pair;
+ acc = mergeFunction(
+ acc,
+ (node) => ($predicate(node) && $override) || undefined,
+ );
+ } else {
+ const typeOverrides = pair[1];
+ const compiled: Record = {};
+ for (const type in typeOverrides) {
+ const arr = typeOverrides[type];
+ if (arr) {
+ compiled[type] = arr.reduce(
+ ($acc, $override) => mergeFunction($acc, () => $override),
+ acc,
+ );
+ }
+ }
+ acc = mergeFunction(acc, (node) => {
+ const f = compiled[node.getType()];
+ return f && ignoreNextFunction(f);
+ });
+ }
+ }
+ defaults[k] = acc;
+}
+
+function addOverride(
+ prerender: PreEditorDOMRenderConfig,
+ k: K,
+ predicateOrTypes: PredicateOrTypes,
+ override: AnyDOMRenderMatch[K],
+): void {
+ if (!override) {
+ return;
+ }
+ const arr = prerender[k];
+ if (typeof predicateOrTypes === 'function') {
+ arr.push([predicateOrTypes, override]);
+ } else {
+ const last = arr[arr.length - 1];
+ let types: TypeRender;
+ if (last && last[0] === 'types') {
+ types = last[1];
+ } else {
+ types = {};
+ arr.push(['types', types]);
+ }
+ for (const type in predicateOrTypes) {
+ const typeArr = types[type] || [];
+ types[type] = typeArr;
+ typeArr.push(override);
+ }
+ }
+}
+
+export function precompileDOMRenderConfigOverrides(
+ editorConfig: Pick,
+ overrides: DOMRenderConfig['overrides'],
+): PreEditorDOMRenderConfig {
+ const typeTree = buildTypeTree(editorConfig);
+ const prerender = makePrerender();
+ for (const override of overrides) {
+ const predicateOrTypes = getPredicate(typeTree, override);
+ for (const k_ in prerender) {
+ const k = k_ as keyof typeof prerender;
+ addOverride(prerender, k, predicateOrTypes, override[k]);
+ }
+ }
+ return prerender;
+}
+
+export function compileDOMRenderConfigOverrides(
+ editorConfig: InitialEditorConfig,
+ {overrides}: DOMRenderConfig,
+): EditorDOMRenderConfig {
+ const prerender = precompileDOMRenderConfigOverrides(editorConfig, overrides);
+ const dom = {
+ ...DEFAULT_EDITOR_DOM_CONFIG,
+ ...editorConfig.dom,
+ };
+ compilePrerenderKey(prerender, '$createDOM', dom, merge2, ignoreNext2);
+ compilePrerenderKey(prerender, '$exportDOM', dom, merge2, ignoreNext2);
+ compilePrerenderKey(prerender, '$extractWithChild', dom, merge5, ignoreNext5);
+ compilePrerenderKey(prerender, '$getDOMSlot', dom, merge3, ignoreNext3);
+ compilePrerenderKey(prerender, '$shouldExclude', dom, merge3, ignoreNext3);
+ compilePrerenderKey(prerender, '$shouldInclude', dom, merge3, ignoreNext3);
+ compilePrerenderKey(prerender, '$updateDOM', dom, merge4, ignoreNext4);
+ return dom;
+}
diff --git a/packages/lexical-html/src/compileLegacyImportDOM.ts b/packages/lexical-html/src/compileLegacyImportDOM.ts
new file mode 100644
index 00000000000..7cd63f7fd47
--- /dev/null
+++ b/packages/lexical-html/src/compileLegacyImportDOM.ts
@@ -0,0 +1,171 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import type {DOMImportExtensionOutput, DOMImportOutput} from './types';
+
+import {
+ $createLineBreakNode,
+ $createParagraphNode,
+ $isBlockElementNode,
+ $isElementNode,
+ $isRootOrShadowRoot,
+ ArtificialNode__DO_NOT_USE,
+ type DOMConversionOutput,
+ isBlockDomNode,
+ type LexicalEditor,
+ type LexicalNode,
+} from 'lexical';
+import invariant from 'shared/invariant';
+
+import {$wrapContinuousInlinesInPlace} from './$wrapContinuousInlinesInPlace';
+import {EMPTY_ARRAY, IGNORE_TAGS} from './constants';
+import {contextUpdater} from './ContextRecord';
+import {getConversionFunction} from './getConversionFunction';
+import {
+ $addImportChildContext,
+ $addImportContextFinalizer,
+ $getImportContextValue,
+ ImportContextArtificialNodes,
+ ImportContextForChildMap,
+ ImportContextHasBlockAncestorLexicalNode,
+ ImportContextParentLexicalNode,
+} from './ImportContext';
+import {isDomNodeBetweenTwoInlineNodes} from './isDomNodeBetweenTwoInlineNodes';
+
+export function compileLegacyImportDOM(
+ editor: LexicalEditor,
+): DOMImportExtensionOutput['$importNode'] {
+ return (node) => {
+ if (IGNORE_TAGS.has(node.nodeName)) {
+ return {childNodes: EMPTY_ARRAY, node: null};
+ }
+ // If the DOM node doesn't have a transformer, we don't know what
+ // to do with it but we still need to process any childNodes.
+ let childLexicalNodes: LexicalNode[] = [];
+ let postTransform: DOMConversionOutput['after'];
+ const output: DOMImportOutput = {
+ $appendChild: (childNode) => childLexicalNodes.push(childNode),
+ node: null,
+ };
+ $addImportContextFinalizer((nodeOrNodes) => {
+ const finalLexicalNodes = Array.isArray(nodeOrNodes)
+ ? nodeOrNodes
+ : nodeOrNodes
+ ? [nodeOrNodes]
+ : [];
+ const finalLexicalNode: null | LexicalNode =
+ finalLexicalNodes[finalLexicalNodes.length - 1] || null;
+ if (postTransform) {
+ childLexicalNodes = postTransform(childLexicalNodes);
+ }
+ if (isBlockDomNode(node)) {
+ const hasBlockAncestorLexicalNodeForChildren =
+ finalLexicalNode && $isRootOrShadowRoot(finalLexicalNode)
+ ? false
+ : (finalLexicalNode && $isBlockElementNode(finalLexicalNode)) ||
+ $getImportContextValue(ImportContextHasBlockAncestorLexicalNode);
+
+ if (!hasBlockAncestorLexicalNodeForChildren) {
+ $wrapContinuousInlinesInPlace(
+ node,
+ childLexicalNodes,
+ $createParagraphNode,
+ );
+ } else {
+ const allArtificialNodes = $getImportContextValue(
+ ImportContextArtificialNodes,
+ );
+ invariant(
+ allArtificialNodes !== null,
+ 'Missing ImportContextArtificialNodes',
+ );
+ $wrapContinuousInlinesInPlace(node, childLexicalNodes, () => {
+ const artificialNode = new ArtificialNode__DO_NOT_USE();
+ allArtificialNodes.push(artificialNode);
+ return artificialNode;
+ });
+ }
+ }
+
+ if (finalLexicalNode == null) {
+ if (childLexicalNodes.length > 0) {
+ // If it hasn't been converted to a LexicalNode, we hoist its children
+ // up to the same level as it.
+ finalLexicalNodes.push(...childLexicalNodes);
+ } else {
+ if (isBlockDomNode(node) && isDomNodeBetweenTwoInlineNodes(node)) {
+ // Empty block dom node that hasnt been converted, we replace it with a linebreak if its between inline nodes
+ finalLexicalNodes.push($createLineBreakNode());
+ }
+ }
+ } else {
+ if ($isElementNode(finalLexicalNode)) {
+ // If the current node is a ElementNode after conversion,
+ // we can append all the children to it.
+ finalLexicalNode.append(...childLexicalNodes);
+ }
+ }
+
+ return finalLexicalNodes;
+ });
+ let currentLexicalNode: null | LexicalNode = null;
+ const transformFunction = getConversionFunction(node, editor);
+ const transformOutput = transformFunction
+ ? transformFunction(node as HTMLElement)
+ : null;
+
+ if (transformOutput !== null) {
+ const forChildMap = $getImportContextValue(
+ ImportContextForChildMap,
+ editor,
+ );
+ const parentLexicalNode = $getImportContextValue(
+ ImportContextParentLexicalNode,
+ editor,
+ );
+ postTransform = transformOutput.after;
+ let transformNodeArray = Array.isArray(transformOutput.node)
+ ? transformOutput.node
+ : transformOutput.node
+ ? [transformOutput.node]
+ : [];
+
+ if (transformNodeArray.length > 0 && forChildMap) {
+ const transformWithForChild = (initial: LexicalNode) => {
+ let current: null | undefined | LexicalNode = initial;
+ for (const forChildFunction of forChildMap.values()) {
+ current = forChildFunction(current, parentLexicalNode);
+
+ if (!current) {
+ return [];
+ }
+ }
+ return [current];
+ };
+ transformNodeArray = transformNodeArray.flatMap(transformWithForChild);
+ }
+ currentLexicalNode =
+ transformNodeArray[transformNodeArray.length - 1] || null;
+ output.node =
+ transformNodeArray.length > 1 ? transformNodeArray : currentLexicalNode;
+
+ if (transformOutput.forChild) {
+ const {forChild} = transformOutput;
+ $addImportChildContext(
+ contextUpdater(ImportContextForChildMap, (prev) => {
+ return new Map(prev || forChildMap || []).set(
+ node.nodeName,
+ forChild,
+ );
+ }),
+ );
+ }
+ }
+
+ return output;
+ };
+}
diff --git a/packages/lexical-html/src/constants.ts b/packages/lexical-html/src/constants.ts
new file mode 100644
index 00000000000..954c990a064
--- /dev/null
+++ b/packages/lexical-html/src/constants.ts
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+export const DOMRenderExtensionName = '@lexical/html/DOM';
+export const DOMImportExtensionName = '@lexical/html/DOMImport';
+export const IGNORE_TAGS = new Set(['STYLE', 'SCRIPT']);
+export const DOMImportContextSymbol = Symbol.for(
+ '@lexical/html/DOMImportContext',
+);
+export const DOMRenderContextSymbol = Symbol.for(
+ '@lexical/html/DOMExportContext',
+);
+
+// https://drafts.csswg.org/css-text-4/#white-space-collapsing
+export const DOMWhiteSpaceCollapseKeys = {
+ 'break-spaces': 'break-spaces',
+ collapse: 'collapse',
+ discard: 'discard',
+ preserve: 'preserve',
+ 'preserve-breaks': 'preserve-breaks',
+ 'preserve-spaces': 'preserve-spaces',
+} as const;
+
+export const DOMTextWrapModeKeys = {
+ nowrap: 'nowrap',
+ wrap: 'wrap',
+} as const;
+
+export const EMPTY_ARRAY = [] as const;
+
+export const ALWAYS_TRUE = () => true as const;
+
+export const ALWAYS_NULL = () => null;
diff --git a/packages/lexical-html/src/domOverride.ts b/packages/lexical-html/src/domOverride.ts
new file mode 100644
index 00000000000..d73a599f951
--- /dev/null
+++ b/packages/lexical-html/src/domOverride.ts
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import type {AnyDOMRenderMatch, DOMRenderMatch, NodeMatch} from './types';
+import type {LexicalNode} from 'lexical';
+
+/**
+ * A convenience function for type inference when constructing DOM overrides for
+ * use with {@link DOMRenderExtension}.
+ *
+ * @__NO_SIDE_EFFECTS__
+ */
+
+export function domOverride(
+ nodes: '*',
+ config: Omit, 'nodes'>,
+): DOMRenderMatch;
+export function domOverride(
+ nodes: readonly NodeMatch[],
+ config: Omit, 'nodes'>,
+): DOMRenderMatch;
+export function domOverride(
+ nodes: AnyDOMRenderMatch['nodes'],
+ config: Omit,
+): AnyDOMRenderMatch {
+ return {...config, nodes};
+}
diff --git a/packages/lexical-html/src/getConversionFunction.ts b/packages/lexical-html/src/getConversionFunction.ts
new file mode 100644
index 00000000000..ef889b416f8
--- /dev/null
+++ b/packages/lexical-html/src/getConversionFunction.ts
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import type {DOMConversion, DOMConversionFn, LexicalEditor} from 'lexical';
+
+export function getConversionFunction(
+ domNode: Node,
+ editor: LexicalEditor,
+): DOMConversionFn | null {
+ const {nodeName} = domNode;
+
+ const cachedConversions = editor._htmlConversions.get(nodeName.toLowerCase());
+
+ let currentConversion: DOMConversion | null = null;
+
+ if (cachedConversions !== undefined) {
+ for (const cachedConversion of cachedConversions) {
+ const domConversion = cachedConversion(domNode);
+ if (
+ domConversion !== null &&
+ (currentConversion === null ||
+ // Given equal priority, prefer the last registered importer
+ // which is typically an application custom node or HTMLConfig['import']
+ (currentConversion.priority || 0) <= (domConversion.priority || 0))
+ ) {
+ currentConversion = domConversion;
+ }
+ }
+ }
+
+ return currentConversion !== null ? currentConversion.conversion : null;
+}
diff --git a/packages/lexical-html/src/importOverride.ts b/packages/lexical-html/src/importOverride.ts
new file mode 100644
index 00000000000..f7bcc5d6379
--- /dev/null
+++ b/packages/lexical-html/src/importOverride.ts
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import type {
+ DOMImportConfigMatch,
+ DOMImportFunction,
+ NodeNameToType,
+} from './types';
+
+/**
+ * A convenience function for type inference when constructing DOM overrides for
+ * use with {@link DOMImportExtension}.
+ *
+ * @__NO_SIDE_EFFECTS__
+ */
+
+export function importOverride(
+ tag: T,
+ $import: DOMImportFunction>,
+ options: Omit = {},
+): DOMImportConfigMatch {
+ return {
+ ...options,
+ $import: $import as DOMImportFunction,
+ tag: tag.toLowerCase(),
+ };
+}
diff --git a/packages/lexical-html/src/index.ts b/packages/lexical-html/src/index.ts
index fc31fbb8021..4857502c12d 100644
--- a/packages/lexical-html/src/index.ts
+++ b/packages/lexical-html/src/index.ts
@@ -5,376 +5,54 @@
* LICENSE file in the root directory of this source tree.
*
*/
-
-import type {
- BaseSelection,
- DOMChildConversion,
- DOMConversion,
- DOMConversionFn,
- ElementFormatType,
- LexicalEditor,
- LexicalNode,
-} from 'lexical';
-
-import {$sliceSelectedTextNodeContent} from '@lexical/selection';
-import {isBlockDomNode, isHTMLElement} from '@lexical/utils';
-import {
- $createLineBreakNode,
- $createParagraphNode,
- $getRoot,
- $isBlockElementNode,
- $isElementNode,
- $isRootOrShadowRoot,
- $isTextNode,
- ArtificialNode__DO_NOT_USE,
- ElementNode,
- getRegisteredNode,
- isDocumentFragment,
- isDOMDocumentNode,
- isInlineDomNode,
-} from 'lexical';
-
-/**
- * How you parse your html string to get a document is left up to you. In the browser you can use the native
- * DOMParser API to generate a document (see clipboard.ts), but to use in a headless environment you can use JSDom
- * or an equivalent library and pass in the document here.
- */
-export function $generateNodesFromDOM(
- editor: LexicalEditor,
- dom: Document | ParentNode,
-): Array {
- const elements = isDOMDocumentNode(dom)
- ? dom.body.childNodes
- : dom.childNodes;
- let lexicalNodes: Array = [];
- const allArtificialNodes: Array = [];
- for (const element of elements) {
- if (!IGNORE_TAGS.has(element.nodeName)) {
- const lexicalNode = $createNodesFromDOM(
- element,
- editor,
- allArtificialNodes,
- false,
- );
- if (lexicalNode !== null) {
- lexicalNodes = lexicalNodes.concat(lexicalNode);
- }
- }
- }
- $unwrapArtificialNodes(allArtificialNodes);
-
- return lexicalNodes;
-}
-
-export function $generateHtmlFromNodes(
- editor: LexicalEditor,
- selection?: BaseSelection | null,
-): string {
- if (
- typeof document === 'undefined' ||
- (typeof window === 'undefined' && typeof global.window === 'undefined')
- ) {
- throw new Error(
- 'To use $generateHtmlFromNodes in headless mode please initialize a headless browser implementation such as JSDom before calling this function.',
- );
- }
-
- const container = document.createElement('div');
- const root = $getRoot();
- const topLevelChildren = root.getChildren();
-
- for (let i = 0; i < topLevelChildren.length; i++) {
- const topLevelNode = topLevelChildren[i];
- $appendNodesToHTML(editor, topLevelNode, container, selection);
- }
-
- return container.innerHTML;
-}
-
-function $appendNodesToHTML(
- editor: LexicalEditor,
- currentNode: LexicalNode,
- parentElement: HTMLElement | DocumentFragment,
- selection: BaseSelection | null = null,
-): boolean {
- let shouldInclude =
- selection !== null ? currentNode.isSelected(selection) : true;
- const shouldExclude =
- $isElementNode(currentNode) && currentNode.excludeFromCopy('html');
- let target = currentNode;
-
- if (selection !== null && $isTextNode(currentNode)) {
- target = $sliceSelectedTextNodeContent(selection, currentNode, 'clone');
- }
- const children = $isElementNode(target) ? target.getChildren() : [];
- const registeredNode = getRegisteredNode(editor, target.getType());
- let exportOutput;
-
- // Use HTMLConfig overrides, if available.
- if (registeredNode && registeredNode.exportDOM !== undefined) {
- exportOutput = registeredNode.exportDOM(editor, target);
- } else {
- exportOutput = target.exportDOM(editor);
- }
-
- const {element, after} = exportOutput;
-
- if (!element) {
- return false;
- }
-
- const fragment = document.createDocumentFragment();
-
- for (let i = 0; i < children.length; i++) {
- const childNode = children[i];
- const shouldIncludeChild = $appendNodesToHTML(
- editor,
- childNode,
- fragment,
- selection,
- );
-
- if (
- !shouldInclude &&
- $isElementNode(currentNode) &&
- shouldIncludeChild &&
- currentNode.extractWithChild(childNode, selection, 'html')
- ) {
- shouldInclude = true;
- }
- }
-
- if (shouldInclude && !shouldExclude) {
- if (isHTMLElement(element) || isDocumentFragment(element)) {
- element.append(fragment);
- }
- parentElement.append(element);
-
- if (after) {
- const newElement = after.call(target, element);
- if (newElement) {
- if (isDocumentFragment(element)) {
- element.replaceChildren(newElement);
- } else {
- element.replaceWith(newElement);
- }
- }
- }
- } else {
- parentElement.append(fragment);
- }
-
- return shouldInclude;
-}
-
-function getConversionFunction(
- domNode: Node,
- editor: LexicalEditor,
-): DOMConversionFn | null {
- const {nodeName} = domNode;
-
- const cachedConversions = editor._htmlConversions.get(nodeName.toLowerCase());
-
- let currentConversion: DOMConversion | null = null;
-
- if (cachedConversions !== undefined) {
- for (const cachedConversion of cachedConversions) {
- const domConversion = cachedConversion(domNode);
- if (
- domConversion !== null &&
- (currentConversion === null ||
- // Given equal priority, prefer the last registered importer
- // which is typically an application custom node or HTMLConfig['import']
- (currentConversion.priority || 0) <= (domConversion.priority || 0))
- ) {
- currentConversion = domConversion;
- }
- }
- }
-
- return currentConversion !== null ? currentConversion.conversion : null;
-}
-
-const IGNORE_TAGS = new Set(['STYLE', 'SCRIPT']);
-
-function $createNodesFromDOM(
- node: Node,
- editor: LexicalEditor,
- allArtificialNodes: Array,
- hasBlockAncestorLexicalNode: boolean,
- forChildMap: Map = new Map(),
- parentLexicalNode?: LexicalNode | null | undefined,
-): Array {
- let lexicalNodes: Array = [];
-
- if (IGNORE_TAGS.has(node.nodeName)) {
- return lexicalNodes;
- }
-
- let currentLexicalNode = null;
- const transformFunction = getConversionFunction(node, editor);
- const transformOutput = transformFunction
- ? transformFunction(node as HTMLElement)
- : null;
- let postTransform = null;
-
- if (transformOutput !== null) {
- postTransform = transformOutput.after;
- const transformNodes = transformOutput.node;
- currentLexicalNode = Array.isArray(transformNodes)
- ? transformNodes[transformNodes.length - 1]
- : transformNodes;
-
- if (currentLexicalNode !== null) {
- for (const [, forChildFunction] of forChildMap) {
- currentLexicalNode = forChildFunction(
- currentLexicalNode,
- parentLexicalNode,
- );
-
- if (!currentLexicalNode) {
- break;
- }
- }
-
- if (currentLexicalNode) {
- lexicalNodes.push(
- ...(Array.isArray(transformNodes)
- ? transformNodes
- : [currentLexicalNode]),
- );
- }
- }
-
- if (transformOutput.forChild != null) {
- forChildMap.set(node.nodeName, transformOutput.forChild);
- }
- }
-
- // If the DOM node doesn't have a transformer, we don't know what
- // to do with it but we still need to process any childNodes.
- const children = node.childNodes;
- let childLexicalNodes = [];
-
- const hasBlockAncestorLexicalNodeForChildren =
- currentLexicalNode != null && $isRootOrShadowRoot(currentLexicalNode)
- ? false
- : (currentLexicalNode != null &&
- $isBlockElementNode(currentLexicalNode)) ||
- hasBlockAncestorLexicalNode;
-
- for (let i = 0; i < children.length; i++) {
- childLexicalNodes.push(
- ...$createNodesFromDOM(
- children[i],
- editor,
- allArtificialNodes,
- hasBlockAncestorLexicalNodeForChildren,
- new Map(forChildMap),
- currentLexicalNode,
- ),
- );
- }
-
- if (postTransform != null) {
- childLexicalNodes = postTransform(childLexicalNodes);
- }
-
- if (isBlockDomNode(node)) {
- if (!hasBlockAncestorLexicalNodeForChildren) {
- childLexicalNodes = wrapContinuousInlines(
- node,
- childLexicalNodes,
- $createParagraphNode,
- );
- } else {
- childLexicalNodes = wrapContinuousInlines(node, childLexicalNodes, () => {
- const artificialNode = new ArtificialNode__DO_NOT_USE();
- allArtificialNodes.push(artificialNode);
- return artificialNode;
- });
- }
- }
-
- if (currentLexicalNode == null) {
- if (childLexicalNodes.length > 0) {
- // If it hasn't been converted to a LexicalNode, we hoist its children
- // up to the same level as it.
- lexicalNodes = lexicalNodes.concat(childLexicalNodes);
- } else {
- if (isBlockDomNode(node) && isDomNodeBetweenTwoInlineNodes(node)) {
- // Empty block dom node that hasnt been converted, we replace it with a linebreak if its between inline nodes
- lexicalNodes = lexicalNodes.concat($createLineBreakNode());
- }
- }
- } else {
- if ($isElementNode(currentLexicalNode)) {
- // If the current node is a ElementNode after conversion,
- // we can append all the children to it.
- currentLexicalNode.append(...childLexicalNodes);
- }
- }
-
- return lexicalNodes;
-}
-
-function wrapContinuousInlines(
- domNode: Node,
- nodes: Array,
- createWrapperFn: () => ElementNode,
-): Array {
- const textAlign = (domNode as HTMLElement).style
- .textAlign as ElementFormatType;
- const out: Array = [];
- let continuousInlines: Array = [];
- // wrap contiguous inline child nodes in para
- for (let i = 0; i < nodes.length; i++) {
- const node = nodes[i];
- if ($isBlockElementNode(node)) {
- if (textAlign && !node.getFormat()) {
- node.setFormat(textAlign);
- }
- out.push(node);
- } else {
- continuousInlines.push(node);
- if (
- i === nodes.length - 1 ||
- (i < nodes.length - 1 && $isBlockElementNode(nodes[i + 1]))
- ) {
- const wrapper = createWrapperFn();
- wrapper.setFormat(textAlign);
- wrapper.append(...continuousInlines);
- out.push(wrapper);
- continuousInlines = [];
- }
- }
- }
- return out;
-}
-
-function $unwrapArtificialNodes(
- allArtificialNodes: Array,
-) {
- for (const node of allArtificialNodes) {
- if (node.getNextSibling() instanceof ArtificialNode__DO_NOT_USE) {
- node.insertAfter($createLineBreakNode());
- }
- }
- // Replace artificial node with it's children
- for (const node of allArtificialNodes) {
- const children = node.getChildren();
- for (const child of children) {
- node.insertBefore(child);
- }
- node.remove();
- }
-}
-
-function isDomNodeBetweenTwoInlineNodes(node: Node): boolean {
- if (node.nextSibling == null || node.previousSibling == null) {
- return false;
- }
- return (
- isInlineDomNode(node.nextSibling) && isInlineDomNode(node.previousSibling)
- );
-}
+export {
+ $generateDOMFromNodes,
+ $generateDOMFromRoot,
+ $generateHtmlFromNodes,
+} from './$generateDOMFromNodes';
+export {$generateNodesFromDOM} from './$generateNodesFromDOM';
+export {contextUpdater, contextValue} from './ContextRecord';
+export {DOMImportExtension} from './DOMImportExtension';
+export {domOverride} from './domOverride';
+export {DOMRenderExtension} from './DOMRenderExtension';
+export {
+ $applyTextAlignToElement,
+ $applyTextFormatsFromContext,
+ $getImportContextValue,
+ $setImportContextValue,
+ $updateImportContextValue,
+ ImportContextHasBlockAncestorLexicalNode,
+ ImportContextParentLexicalNode,
+ ImportContextTextAlign,
+ ImportContextTextFormats,
+ ImportContextWhiteSpaceCollapse,
+} from './ImportContext';
+export {importOverride} from './importOverride';
+export {
+ $getRenderContextValue,
+ $withRenderContext,
+ RenderContextExport,
+ RenderContextRoot,
+} from './RenderContext';
+export type {
+ AnyDOMRenderMatch,
+ AnyImportStateConfig,
+ AnyImportStateConfigPairOrUpdater,
+ AnyRenderStateConfig,
+ AnyRenderStateConfigPairOrUpdater,
+ ContextPairOrUpdater,
+ DOMImportConfig,
+ DOMImportConfigMatch,
+ DOMImportContextFinalizer,
+ DOMImportExtensionOutput,
+ DOMImportFunction,
+ DOMImportOutput,
+ DOMRenderConfig,
+ DOMRenderExtensionOutput,
+ DOMRenderMatch,
+ DOMTextWrapMode,
+ DOMWhiteSpaceCollapse,
+ NodeMatch,
+ NodeNameMap,
+ NodeNameToType,
+} from './types';
diff --git a/packages/lexical-html/src/isDomNodeBetweenTwoInlineNodes.ts b/packages/lexical-html/src/isDomNodeBetweenTwoInlineNodes.ts
new file mode 100644
index 00000000000..1a0c8aec377
--- /dev/null
+++ b/packages/lexical-html/src/isDomNodeBetweenTwoInlineNodes.ts
@@ -0,0 +1,17 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+import {isInlineDomNode} from 'lexical';
+
+export function isDomNodeBetweenTwoInlineNodes(node: Node): boolean {
+ if (node.nextSibling == null || node.previousSibling == null) {
+ return false;
+ }
+ return (
+ isInlineDomNode(node.nextSibling) && isInlineDomNode(node.previousSibling)
+ );
+}
diff --git a/packages/lexical-html/src/parseStringEnum.ts b/packages/lexical-html/src/parseStringEnum.ts
new file mode 100644
index 00000000000..9c6db7bd9c9
--- /dev/null
+++ b/packages/lexical-html/src/parseStringEnum.ts
@@ -0,0 +1,13 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+export function parseStringEnum(
+ stringEnum: {[K in T]: K},
+ value: string,
+): T | undefined {
+ return (stringEnum as Record)[value];
+}
diff --git a/packages/lexical-html/src/types.ts b/packages/lexical-html/src/types.ts
new file mode 100644
index 00000000000..28093b63edd
--- /dev/null
+++ b/packages/lexical-html/src/types.ts
@@ -0,0 +1,188 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+
+import type {
+ DOMImportContextSymbol,
+ DOMRenderContextSymbol,
+ DOMTextWrapModeKeys,
+ DOMWhiteSpaceCollapseKeys,
+} from './constants';
+import type {
+ BaseSelection,
+ DOMExportOutput,
+ ElementDOMSlot,
+ Klass,
+ LexicalEditor,
+ LexicalNode,
+ StateConfig,
+} from 'lexical';
+
+export type AnyContextSymbol =
+ | typeof DOMImportContextSymbol
+ | typeof DOMRenderContextSymbol;
+
+export type ContextRecord<_K extends symbol> = Record;
+
+export type ContextConfig = StateConfig & {
+ readonly [K in Sym]?: true;
+};
+
+export type ContextConfigUpdater = {
+ readonly cfg: ContextConfig;
+ readonly updater: (prev: V) => V;
+};
+export type ContextConfigPair = readonly [
+ ContextConfig,
+ V,
+];
+
+export type ContextPairOrUpdater =
+ | ContextConfigPair
+ | ContextConfigUpdater;
+
+export type AnyContextConfigPairOrUpdater =
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ContextPairOrUpdater;
+
+export interface DOMRenderExtensionOutput {
+ defaults: undefined | ContextRecord;
+}
+
+export type ImportStateConfig = ContextConfig<
+ typeof DOMImportContextSymbol,
+ V
+>;
+
+export type RenderStateConfig = ContextConfig<
+ typeof DOMRenderContextSymbol,
+ V
+>;
+
+export type AnyImportStateConfigPairOrUpdater = AnyContextConfigPairOrUpdater<
+ typeof DOMImportContextSymbol
+>;
+export type AnyRenderStateConfigPairOrUpdater = AnyContextConfigPairOrUpdater<
+ typeof DOMRenderContextSymbol
+>;
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export type AnyRenderStateConfig = RenderStateConfig;
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export type AnyImportStateConfig = ImportStateConfig;
+
+export interface DOMImportOutput {
+ node: null | LexicalNode | LexicalNode[];
+ childNodes?: NodeListOf | readonly ChildNode[];
+ $appendChild?: (node: LexicalNode, dom: ChildNode) => void;
+}
+
+export type DOMImportFunction = (
+ node: T,
+ $next: () => null | undefined | DOMImportOutput,
+ editor: LexicalEditor,
+) => null | undefined | DOMImportOutput;
+
+export interface NodeNameMap extends HTMLElementTagNameMap {
+ '*': Node;
+ '#text': Text;
+ '#document': Document;
+ '#comment': Comment;
+ '#cdata-section': CDATASection;
+}
+
+export type NodeNameToType = T extends keyof NodeNameMap
+ ? NodeNameMap[T]
+ : Node;
+
+/** @internal @experimental */
+export interface DOMRenderConfig {
+ overrides: AnyDOMRenderMatch[];
+ contextDefaults: AnyRenderStateConfigPairOrUpdater[];
+}
+
+/** @internal @experimental */
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export type AnyDOMRenderMatch = DOMRenderMatch;
+
+export type NodeMatch =
+ | Klass
+ | ((node: LexicalNode) => node is T);
+
+/** @internal @experimental */
+export interface DOMRenderMatch {
+ readonly nodes: '*' | readonly NodeMatch[];
+ $getDOMSlot?: (
+ node: N,
+ dom: HTMLElement,
+ $next: () => ElementDOMSlot,
+ editor: LexicalEditor,
+ ) => ElementDOMSlot;
+ $createDOM?: (
+ node: T,
+ $next: () => HTMLElement,
+ editor: LexicalEditor,
+ ) => HTMLElement;
+ $updateDOM?: (
+ nextNode: T,
+ prevNode: T,
+ dom: HTMLElement,
+ $next: () => boolean,
+ editor: LexicalEditor,
+ ) => boolean;
+ $exportDOM?: (
+ node: T,
+ $next: () => DOMExportOutput,
+ editor: LexicalEditor,
+ ) => DOMExportOutput;
+ $shouldExclude?: (
+ node: T,
+ selection: null | BaseSelection,
+ $next: () => boolean,
+ editor: LexicalEditor,
+ ) => boolean;
+ $shouldInclude?: (
+ node: T,
+ selection: null | BaseSelection,
+ $next: () => boolean,
+ editor: LexicalEditor,
+ ) => boolean;
+ $extractWithChild?: (
+ node: T,
+ childNode: LexicalNode,
+ selection: null | BaseSelection,
+ destination: 'clone' | 'html',
+ $next: () => boolean,
+ editor: LexicalEditor,
+ ) => boolean;
+}
+
+/** @internal @experimental */
+export interface DOMImportConfig {
+ overrides: DOMImportConfigMatch[];
+ compileLegacyImportNode: (
+ editor: LexicalEditor,
+ ) => DOMImportExtensionOutput['$importNode'];
+}
+export interface DOMImportConfigMatch {
+ readonly tag: '*' | '#text' | '#cdata-section' | '#comment' | (string & {});
+ readonly selector?: string;
+ readonly priority?: 0 | 1 | 2 | 3 | 4;
+ readonly $import: DOMImportFunction;
+}
+
+export interface DOMImportExtensionOutput {
+ $importNode: (node: Node) => null | undefined | DOMImportOutput;
+ $importNodes: (root: ParentNode | Document) => LexicalNode[];
+}
+
+export type DOMWhiteSpaceCollapse = keyof typeof DOMWhiteSpaceCollapseKeys;
+export type DOMTextWrapMode = keyof typeof DOMTextWrapModeKeys;
+
+export type DOMImportContextFinalizer = (
+ node: null | LexicalNode | LexicalNode[],
+) => null | LexicalNode | LexicalNode[];
diff --git a/packages/lexical-link/src/ClickableLinkExtension.ts b/packages/lexical-link/src/ClickableLinkExtension.ts
index 5c6378bd4f8..88b4f95676e 100644
--- a/packages/lexical-link/src/ClickableLinkExtension.ts
+++ b/packages/lexical-link/src/ClickableLinkExtension.ts
@@ -86,7 +86,7 @@ export function registerClickableLink(
}
// Allow user to select link text without following url
- const selection = editor.getEditorState().read($getSelection);
+ const selection = editor.getEditorState().read($getSelection, {editor});
if ($isRangeSelection(selection) && !selection.isCollapsed()) {
event.preventDefault();
return;
diff --git a/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx b/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx
index fcd10a41e29..b4438d70927 100644
--- a/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx
+++ b/packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx
@@ -849,7 +849,7 @@ function TableCellActionMenuContainer({
let timeoutId: ReturnType | undefined = undefined;
const callback = () => {
timeoutId = undefined;
- editor.getEditorState().read($moveMenu);
+ editor.getEditorState().read($moveMenu, {editor});
};
const delayedCallback = () => {
if (timeoutId === undefined) {
diff --git a/packages/lexical-react/src/LexicalErrorBoundary.tsx b/packages/lexical-react/src/LexicalErrorBoundary.tsx
index a10e26bcc33..59c9ad347be 100644
--- a/packages/lexical-react/src/LexicalErrorBoundary.tsx
+++ b/packages/lexical-react/src/LexicalErrorBoundary.tsx
@@ -8,7 +8,6 @@
import type {JSX} from 'react';
-import * as React from 'react';
import {ErrorBoundary as ReactErrorBoundary} from 'react-error-boundary';
export type LexicalErrorBoundaryProps = {
diff --git a/packages/lexical-react/src/shared/useCharacterLimit.ts b/packages/lexical-react/src/shared/useCharacterLimit.ts
index ce22b19a7ba..aa8fce62324 100644
--- a/packages/lexical-react/src/shared/useCharacterLimit.ts
+++ b/packages/lexical-react/src/shared/useCharacterLimit.ts
@@ -62,7 +62,7 @@ export function useCharacterLimit(
}, [editor]);
useEffect(() => {
- let text = editor.getEditorState().read($rootTextContent);
+ let text = editor.getEditorState().read($rootTextContent, {editor});
let lastComputedTextLength = 0;
return mergeRegister(
diff --git a/packages/lexical-table/src/LexicalTableNode.ts b/packages/lexical-table/src/LexicalTableNode.ts
index 41b4d23c915..1485fc36509 100644
--- a/packages/lexical-table/src/LexicalTableNode.ts
+++ b/packages/lexical-table/src/LexicalTableNode.ts
@@ -40,6 +40,7 @@ import {TableDOMCell, TableDOMTable} from './LexicalTableObserver';
import {$isTableRowNode, type TableRowNode} from './LexicalTableRowNode';
import {
$getNearestTableCellInTableFromDOMNode,
+ $getTableElement,
getTable,
isHTMLTableElement,
} from './LexicalTableSelectionHelpers';
@@ -338,8 +339,7 @@ export class TableNode extends ElementNode {
}
updateDOM(prevNode: this, dom: HTMLElement, config: EditorConfig): boolean {
- const slot = this.getDOMSlot(dom);
- const tableElement = slot.element;
+ const tableElement = $getTableElement(this, dom);
if ((dom === tableElement) === $isScrollableTablesActive()) {
return true;
}
diff --git a/packages/lexical-table/src/LexicalTableSelectionHelpers.ts b/packages/lexical-table/src/LexicalTableSelectionHelpers.ts
index e672e074dfd..6b6dc6a3f2a 100644
--- a/packages/lexical-table/src/LexicalTableSelectionHelpers.ts
+++ b/packages/lexical-table/src/LexicalTableSelectionHelpers.ts
@@ -46,6 +46,8 @@ import {
$extendCaretToRange,
$getAdjacentChildCaret,
$getChildCaret,
+ $getEditor,
+ $getEditorDOMRenderConfig,
$getNearestNodeFromDOMNode,
$getPreviousSelection,
$getSelection,
@@ -120,15 +122,19 @@ export function isHTMLTableElement(el: unknown): el is HTMLTableElement {
return isHTMLElement(el) && el.nodeName === 'TABLE';
}
-export function getTableElement(
+export function $getTableElement(
tableNode: TableNode,
dom: T,
): HTMLTableElementWithWithTableSelectionState | (T & null) {
if (!dom) {
return dom as T & null;
}
+ const editor = $getEditor();
const element = (
- isHTMLTableElement(dom) ? dom : tableNode.getDOMSlot(dom).element
+ isHTMLTableElement(dom)
+ ? dom
+ : $getEditorDOMRenderConfig(editor).$getDOMSlot(tableNode, dom, editor)
+ .element
) as HTMLTableElementWithWithTableSelectionState;
invariant(
element.nodeName === 'TABLE',
@@ -137,6 +143,8 @@ export function getTableElement(
);
return element;
}
+/** @deprecated renamed to {@link $getTableElement} by @lexical/eslint-plugin rules-of-lexical */
+export const getTableElement = $getTableElement;
export function getEditorWindow(editor: LexicalEditor): Window | null {
return editor._window;
@@ -176,7 +184,7 @@ const DELETE_KEY_COMMANDS = [
KEY_DELETE_COMMAND,
] as const;
-export function applyTableHandlers(
+export function $applyTableHandlers(
tableNode: TableNode,
element: HTMLElement,
editor: LexicalEditor,
@@ -191,7 +199,7 @@ export function applyTableHandlers(
const tableObserver = new TableObserver(editor, tableNode.getKey());
- const tableElement = getTableElement(tableNode, element);
+ const tableElement = $getTableElement(tableNode, element);
attachTableObserverToTableElement(tableElement, tableObserver);
tableObserver.listenersToRemove.add(() =>
detachTableObserverFromTableElement(tableElement, tableObserver),
@@ -1242,6 +1250,8 @@ export function applyTableHandlers(
return tableObserver;
}
+/** @deprecated renamed to {@link $applyTableHandlers} by @lexical/eslint-plugin rules-of-lexical */
+export const applyTableHandlers = $applyTableHandlers;
export type HTMLTableElementWithWithTableSelectionState = HTMLTableElement & {
[LEXICAL_ELEMENT_KEY]?: TableObserver | undefined;
@@ -1334,11 +1344,11 @@ export function doesTargetContainText(node: Node): boolean {
return false;
}
-export function getTable(
+export function $getTable(
tableNode: TableNode,
dom: HTMLElement,
): TableDOMTable {
- const tableElement = getTableElement(tableNode, dom);
+ const tableElement = $getTableElement(tableNode, dom);
const domRows: TableDOMRows = [];
const grid = {
columns: 0,
@@ -1409,6 +1419,8 @@ export function getTable(
return grid;
}
+/** @deprecated renamed to {@link $getTable} by @lexical/eslint-plugin rules-of-lexical */
+export const getTable = $getTable;
export function $updateDOMForSelection(
editor: LexicalEditor,
@@ -2192,12 +2204,12 @@ function $handleArrowKey(
}
const anchorCellTable = $findTableNode(anchorCellNode);
if (anchorCellTable !== tableNode && anchorCellTable != null) {
- const anchorCellTableElement = getTableElement(
+ const anchorCellTableElement = $getTableElement(
anchorCellTable,
editor.getElementByKey(anchorCellTable.getKey()),
);
if (anchorCellTableElement != null) {
- tableObserver.table = getTable(
+ tableObserver.table = $getTable(
anchorCellTable,
anchorCellTableElement,
);
@@ -2296,7 +2308,7 @@ function $handleArrowKey(
$isTableNode(tableNodeFromSelection),
'$handleArrowKey: TableSelection.getNodes()[0] expected to be TableNode',
);
- const tableElement = getTableElement(
+ const tableElement = $getTableElement(
tableNodeFromSelection,
editor.getElementByKey(tableNodeFromSelection.getKey()),
);
@@ -2310,7 +2322,7 @@ function $handleArrowKey(
}
tableObserver.$updateTableTableSelection(selection);
- const grid = getTable(tableNodeFromSelection, tableElement);
+ const grid = $getTable(tableNodeFromSelection, tableElement);
const cordsAnchor = tableNode.getCordsFromCellNode(anchorCellNode, grid);
const anchorCell = tableNode.getDOMCellFromCordsOrThrow(
cordsAnchor.x,
@@ -2395,7 +2407,7 @@ function $getTableEdgeCursorPosition(
}
const domAnchorNode = domSelection.anchorNode;
const tableNodeParentDOM = editor.getElementByKey(tableNodeParent.getKey());
- const tableElement = getTableElement(
+ const tableElement = $getTableElement(
tableNode,
editor.getElementByKey(tableNode.getKey()),
);
diff --git a/packages/lexical-utils/src/markSelection.ts b/packages/lexical-utils/src/markSelection.ts
index f1b7242d4e5..3959f84c838 100644
--- a/packages/lexical-utils/src/markSelection.ts
+++ b/packages/lexical-utils/src/markSelection.ts
@@ -7,6 +7,8 @@
*/
import {
+ $getEditor,
+ $getEditorDOMRenderConfig,
$getSelection,
$isElementNode,
$isRangeSelection,
@@ -28,7 +30,7 @@ function $getOrderedSelectionPoints(selection: RangeSelection): [Point, Point] {
return selection.isBackward() ? [points[1], points[0]] : points;
}
-function rangeTargetFromPoint(
+function $rangeTargetFromPoint(
point: Point,
node: ElementNode | TextNode,
dom: HTMLElement,
@@ -37,12 +39,17 @@ function rangeTargetFromPoint(
const textDOM = getDOMTextNode(dom) || dom;
return [textDOM, point.offset];
} else {
- const slot = node.getDOMSlot(dom);
+ const editor = $getEditor();
+ const slot = $getEditorDOMRenderConfig(editor).$getDOMSlot(
+ node,
+ dom,
+ editor,
+ );
return [slot.element, slot.getFirstChildOffset() + point.offset];
}
}
-function rangeFromPoints(
+function $rangeFromPoints(
editor: LexicalEditor,
start: Point,
startNode: ElementNode | TextNode,
@@ -53,8 +60,8 @@ function rangeFromPoints(
): Range {
const editorDocument = editor._window ? editor._window.document : document;
const range = editorDocument.createRange();
- range.setStart(...rangeTargetFromPoint(start, startNode, startDOM));
- range.setEnd(...rangeTargetFromPoint(end, endNode, endDOM));
+ range.setStart(...$rangeTargetFromPoint(start, startNode, startDOM));
+ range.setEnd(...$rangeTargetFromPoint(end, endNode, endDOM));
return range;
}
/**
@@ -113,7 +120,7 @@ export default function markSelection(
currentStartNodeDOM !== null &&
currentEndNodeDOM !== null
) {
- const range = rangeFromPoints(
+ const range = $rangeFromPoints(
editor,
start,
currentStartNode,
diff --git a/packages/lexical/flow/Lexical.js.flow b/packages/lexical/flow/Lexical.js.flow
index f560067ec3a..22ec65304f0 100644
--- a/packages/lexical/flow/Lexical.js.flow
+++ b/packages/lexical/flow/Lexical.js.flow
@@ -146,7 +146,29 @@ type DOMConversionCache = Map<
Array<(node: Node) => DOMConversion | null>,
>;
+export type EditorDOMRenderConfig = {
+ /** @internal @experimental */
+ createDOM: (
+ node: T,
+ editor: LexicalEditor,
+ ) => HTMLElement;
+ /** @internal @experimental */
+ exportDOM: (
+ node: T,
+ editor: LexicalEditor,
+ ) => DOMExportOutput;
+ /** @internal @experimental */
+ updateDOM: (
+ nextNode: T,
+ prevNode: T,
+ dom: HTMLElement,
+ editor: LexicalEditor,
+ ) => boolean;
+}
+
export type CreateEditorArgs = {
+ /** @internal @experimental */
+ dom?: Partial;
disableEvents?: boolean;
editorState?: EditorState;
namespace?: string;
@@ -316,6 +338,23 @@ export type EditorConfig = {
theme: EditorThemeClasses,
namespace: string,
disableEvents?: boolean,
+ /** @internal @experimental */
+ createDOM?: (
+ editor: LexicalEditor,
+ node: T,
+ ) => HTMLElement;
+ /** @internal @experimental */
+ exportDOM?: (
+ editor: LexicalEditor,
+ node: T,
+ ) => DOMExportOutput;
+ /** @internal @experimental */
+ updateDOM?: (
+ editor: LexicalEditor,
+ nextNode: T,
+ prevNode: T,
+ dom: HTMLElement,
+ ) => boolean;
};
export type CommandListenerPriority = 0 | 1 | 2 | 3 | 4;
export const COMMAND_PRIORITY_EDITOR = 0;
@@ -1568,6 +1607,7 @@ export interface ExtensionRegisterState
getOutput: () => Output;
}
export interface InitialEditorConfig {
+ dom?: CreateEditorArgs['dom'];
disableEvents?: CreateEditorArgs['disableEvents'];
parentEditor?: CreateEditorArgs['parentEditor'];
namespace?: CreateEditorArgs['namespace'];
diff --git a/packages/lexical/src/LexicalEditor.ts b/packages/lexical/src/LexicalEditor.ts
index 4cabfd88575..53d7041d74e 100644
--- a/packages/lexical/src/LexicalEditor.ts
+++ b/packages/lexical/src/LexicalEditor.ts
@@ -14,10 +14,17 @@ import type {
DOMExportOutputMap,
NodeKey,
} from './LexicalNode';
+import type {ElementDOMSlot} from './nodes/LexicalElementNode';
import invariant from 'shared/invariant';
-import {$getRoot, $getSelection, TextNode} from '.';
+import {
+ $getRoot,
+ $getSelection,
+ $isElementNode,
+ BaseSelection,
+ TextNode,
+} from '.';
import {FULL_RECONCILE, NO_DIRTY_NODES} from './LexicalConstants';
import {cloneEditorState, createEmptyEditorState} from './LexicalEditorState';
import {addRootElementEvents, removeRootElementEvents} from './LexicalEvents';
@@ -43,6 +50,7 @@ import {
getCachedTypeToNodeMap,
getDefaultView,
getDOMSelection,
+ getRegisteredNode,
getStaticNodeConfig,
hasOwnExportDOM,
hasOwnStaticMethod,
@@ -188,11 +196,12 @@ export type EditorThemeClasses = {
[key: string]: any;
};
-export type EditorConfig = {
+export interface EditorConfig {
+ dom?: EditorDOMRenderConfig;
disableEvents?: boolean;
namespace: string;
theme: EditorThemeClasses;
-};
+}
export type LexicalNodeReplacement = {
replace: Klass;
@@ -213,7 +222,54 @@ export type HTMLConfig = {
*/
export type LexicalNodeConfig = Klass | LexicalNodeReplacement;
-export type CreateEditorArgs = {
+/** @internal @experimental */
+export interface EditorDOMRenderConfig {
+ /** @internal @experimental */
+ $createDOM: (
+ node: T,
+ editor: LexicalEditor,
+ ) => HTMLElement;
+ /** @internal @experimental */
+ $getDOMSlot: (
+ node: T,
+ dom: HTMLElement,
+ editor: LexicalEditor,
+ ) => ElementDOMSlot;
+ /** @internal @experimental */
+ $exportDOM: (
+ node: T,
+ editor: LexicalEditor,
+ ) => DOMExportOutput;
+ /** @internal @experimental */
+ $extractWithChild: (
+ node: T,
+ childNode: LexicalNode,
+ selection: null | BaseSelection,
+ destination: 'clone' | 'html',
+ editor: LexicalEditor,
+ ) => boolean;
+ /** @internal @experimental */
+ $updateDOM: (
+ nextNode: T,
+ prevNode: T,
+ dom: HTMLElement,
+ editor: LexicalEditor,
+ ) => boolean;
+ /** @internal @experimental */
+ $shouldInclude: (
+ node: T,
+ selection: null | BaseSelection,
+ editor: LexicalEditor,
+ ) => boolean;
+ /** @internal @experimental */
+ $shouldExclude: