@grida/svg-editor 1.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +831 -0
- package/dist/dom-CfP_ZURh.js +963 -0
- package/dist/dom-kA8NDuVh.mjs +929 -0
- package/dist/dom.d.mts +16 -0
- package/dist/dom.d.ts +16 -0
- package/dist/dom.js +3 -0
- package/dist/dom.mjs +2 -0
- package/dist/editor-B5z-gTML.mjs +1821 -0
- package/dist/editor-CTtU2gu4.d.ts +607 -0
- package/dist/editor-DQWUWrVZ.js +1833 -0
- package/dist/editor-JY7AQrR1.d.mts +607 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/index.mjs +2 -0
- package/dist/paint-DHq_3iwU.js +509 -0
- package/dist/paint-DuCg6Y-K.mjs +461 -0
- package/dist/react.d.mts +49 -0
- package/dist/react.d.ts +49 -0
- package/dist/react.js +97 -0
- package/dist/react.mjs +92 -0
- package/package.json +66 -0
package/dist/react.mjs
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as createSvgEditor } from "./editor-B5z-gTML.mjs";
|
|
3
|
+
import { t as attach_dom_surface } from "./dom-kA8NDuVh.mjs";
|
|
4
|
+
import { createContext, useContext, useEffect, useMemo, useRef, useSyncExternalStore } from "react";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
//#region src/react.tsx
|
|
7
|
+
const SvgEditorContext = createContext(null);
|
|
8
|
+
/**
|
|
9
|
+
* Owns the headless editor and exposes it via context. The editor is created
|
|
10
|
+
* once on first render; subsequent prop changes to `svg` call `editor.load()`.
|
|
11
|
+
*/
|
|
12
|
+
function SvgEditorProvider({ svg, providers, style, children }) {
|
|
13
|
+
const editor_ref = useRef(null);
|
|
14
|
+
if (editor_ref.current === null) editor_ref.current = createSvgEditor({
|
|
15
|
+
svg,
|
|
16
|
+
providers,
|
|
17
|
+
style
|
|
18
|
+
});
|
|
19
|
+
const editor = editor_ref.current;
|
|
20
|
+
const last_svg = useRef(svg);
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (last_svg.current !== svg) {
|
|
23
|
+
editor.load(svg);
|
|
24
|
+
last_svg.current = svg;
|
|
25
|
+
}
|
|
26
|
+
}, [svg, editor]);
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
return () => {
|
|
29
|
+
editor.dispose();
|
|
30
|
+
};
|
|
31
|
+
}, [editor]);
|
|
32
|
+
return /* @__PURE__ */ jsx(SvgEditorContext.Provider, {
|
|
33
|
+
value: editor,
|
|
34
|
+
children
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Renders the editor's SVG into a `div` and wires it to the DOM surface.
|
|
39
|
+
*
|
|
40
|
+
* Internally calls `attach_dom_surface(editor, { container })` on mount and
|
|
41
|
+
* `handle.detach()` on unmount. This is the only UI component the package
|
|
42
|
+
* ships; everything else (toolbar, property panel, etc.) is consumer-built.
|
|
43
|
+
*/
|
|
44
|
+
function SvgEditorCanvas({ className, style }) {
|
|
45
|
+
const editor = useSvgEditor();
|
|
46
|
+
const ref = useRef(null);
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
const container = ref.current;
|
|
49
|
+
if (!container) return;
|
|
50
|
+
const handle = attach_dom_surface(editor, { container });
|
|
51
|
+
return () => handle.detach();
|
|
52
|
+
}, [editor]);
|
|
53
|
+
return /* @__PURE__ */ jsx("div", {
|
|
54
|
+
ref,
|
|
55
|
+
className,
|
|
56
|
+
style
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function useSvgEditor() {
|
|
60
|
+
const editor = useContext(SvgEditorContext);
|
|
61
|
+
if (editor === null) throw new Error("useSvgEditor must be used inside a <SvgEditorProvider>.");
|
|
62
|
+
return editor;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Subscribe to a slice of `editor.state`. Re-renders when the selected slice
|
|
66
|
+
* changes by reference (or by the supplied `equals` function).
|
|
67
|
+
*/
|
|
68
|
+
function useEditorState(selector, equals = Object.is) {
|
|
69
|
+
const editor = useSvgEditor();
|
|
70
|
+
const last_ref = useRef({
|
|
71
|
+
has: false,
|
|
72
|
+
value: void 0
|
|
73
|
+
});
|
|
74
|
+
return useSyncExternalStore((cb) => editor.subscribe(cb), () => {
|
|
75
|
+
const next = selector(editor.state);
|
|
76
|
+
if (!last_ref.current.has || !equals(last_ref.current.value, next)) last_ref.current = {
|
|
77
|
+
has: true,
|
|
78
|
+
value: next
|
|
79
|
+
};
|
|
80
|
+
return last_ref.current.value;
|
|
81
|
+
}, () => selector(editor.state));
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Sugar for `useSvgEditor().commands`. The returned object is stable across
|
|
85
|
+
* re-renders (commands themselves don't change identity).
|
|
86
|
+
*/
|
|
87
|
+
function useCommands() {
|
|
88
|
+
const editor = useSvgEditor();
|
|
89
|
+
return useMemo(() => editor.commands, [editor]);
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
export { SvgEditorCanvas, SvgEditorProvider, useCommands, useEditorState, useSvgEditor };
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@grida/svg-editor",
|
|
3
|
+
"version": "1.0.0-alpha.1",
|
|
4
|
+
"description": "Headless SVG editor (experimental).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Grida",
|
|
7
|
+
"repository": "https://github.com/gridaco/grida",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"main": "./dist/index.js",
|
|
12
|
+
"module": "./dist/index.mjs",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.mjs",
|
|
18
|
+
"require": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./dom": {
|
|
21
|
+
"types": "./dist/dom.d.ts",
|
|
22
|
+
"import": "./dist/dom.mjs",
|
|
23
|
+
"require": "./dist/dom.js"
|
|
24
|
+
},
|
|
25
|
+
"./react": {
|
|
26
|
+
"types": "./dist/react.d.ts",
|
|
27
|
+
"import": "./dist/react.mjs",
|
|
28
|
+
"require": "./dist/react.js"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public",
|
|
33
|
+
"tag": "alpha"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"svg-pathdata": "^7.2.0",
|
|
37
|
+
"@grida/hud": "0.1.0",
|
|
38
|
+
"@grida/history": "0.1.0",
|
|
39
|
+
"@grida/cmath": "0.1.0",
|
|
40
|
+
"@grida/keybinding": "0.1.0",
|
|
41
|
+
"@grida/text-editor": "0.1.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/react": "^19",
|
|
45
|
+
"react": "^19",
|
|
46
|
+
"tsdown": "^0.21.9",
|
|
47
|
+
"typescript": "^6",
|
|
48
|
+
"vitest": "^4"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"react": ">=18"
|
|
52
|
+
},
|
|
53
|
+
"peerDependenciesMeta": {
|
|
54
|
+
"react": {
|
|
55
|
+
"optional": true
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"bench": "vitest bench --run",
|
|
60
|
+
"build": "tsdown",
|
|
61
|
+
"dev": "tsdown --watch",
|
|
62
|
+
"test": "vitest run",
|
|
63
|
+
"test:watch": "vitest",
|
|
64
|
+
"typecheck": "tsc --noEmit"
|
|
65
|
+
}
|
|
66
|
+
}
|