@oh-just-another/editor 0.58.2 → 0.59.0

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.
@@ -0,0 +1,99 @@
1
+ import { registerAnimationAdapter, notifyAnimationContentReady, } from "@oh-just-another/renderer-core";
2
+ import { DEFAULT_FRAME_DELAY_MS } from "./constants.js";
3
+ const decodeCache = new WeakMap();
4
+ const decoding = new WeakSet();
5
+ const compositeGifFrames = async (buffer) => {
6
+ // Lazy-load the decoder — only fetched when a GIF is first decoded.
7
+ const { parseGIF, decompressFrames } = await import("gifuct-js");
8
+ const gif = parseGIF(buffer);
9
+ const raw = decompressFrames(gif, true);
10
+ const width = gif.lsd.width;
11
+ const height = gif.lsd.height;
12
+ if (width <= 0 || height <= 0 || raw.length === 0) {
13
+ return { frames: [], totalMs: 0 };
14
+ }
15
+ // Persistent composite — each frame's patch is drawn on top so partial-frame
16
+ // GIFs (most of them) accumulate correctly. Disposal type 2 ("restore to
17
+ // background") clears the patch region after snapshotting; types 1/0 keep it
18
+ // (the common case).
19
+ const composite = new OffscreenCanvas(width, height);
20
+ const cctx = composite.getContext("2d");
21
+ const patch = new OffscreenCanvas(width, height);
22
+ const pctx = patch.getContext("2d");
23
+ if (!cctx || !pctx)
24
+ return { frames: [], totalMs: 0 };
25
+ const frames = [];
26
+ let cumulative = 0;
27
+ for (const fr of raw) {
28
+ // Copy into a fresh ArrayBuffer-backed array — gifuct's patch may be typed
29
+ // as `Uint8ClampedArray<ArrayBufferLike>` (SharedArrayBuffer union), which
30
+ // `ImageData` doesn't accept under TS's strict ArrayBuffer typing.
31
+ const imageData = new ImageData(new Uint8ClampedArray(fr.patch), fr.dims.width, fr.dims.height);
32
+ patch.width = fr.dims.width;
33
+ patch.height = fr.dims.height;
34
+ pctx.putImageData(imageData, 0, 0);
35
+ cctx.drawImage(patch, fr.dims.left, fr.dims.top);
36
+ // Snapshot the full composite as this frame.
37
+ const bitmap = await createImageBitmap(composite);
38
+ cumulative += fr.delay > 0 ? fr.delay : DEFAULT_FRAME_DELAY_MS;
39
+ frames.push({ bitmap, endMs: cumulative });
40
+ if (fr.disposalType === 2) {
41
+ cctx.clearRect(fr.dims.left, fr.dims.top, fr.dims.width, fr.dims.height);
42
+ }
43
+ }
44
+ return { frames, totalMs: cumulative };
45
+ };
46
+ const gifAdapter = {
47
+ kind: "gif",
48
+ getFrameAt(data, timestampMs) {
49
+ if (!(data instanceof ArrayBuffer) || data.byteLength === 0)
50
+ return null;
51
+ const decoded = decodeCache.get(data);
52
+ if (!decoded) {
53
+ // First sighting — kick off a one-time async decode. Return null
54
+ // meanwhile; the renderer skips a null handle and the next AnimationTick
55
+ // frame will find the cache populated.
56
+ if (!decoding.has(data)) {
57
+ decoding.add(data);
58
+ compositeGifFrames(data)
59
+ .then((d) => {
60
+ decodeCache.set(data, d);
61
+ // Nudge the host to render once more so a paused shape
62
+ // (reduced-motion / auto-stopped / frozen) — which has no animation
63
+ // tick to pick the frames up — paints its now-decoded frame.
64
+ notifyAnimationContentReady();
65
+ })
66
+ .catch(() => {
67
+ /* leave uncached — getFrameAt keeps returning null */
68
+ })
69
+ .finally(() => decoding.delete(data));
70
+ }
71
+ return null;
72
+ }
73
+ if (decoded.frames.length === 0)
74
+ return null;
75
+ const t = decoded.totalMs > 0 ? timestampMs % decoded.totalMs : 0;
76
+ for (const frame of decoded.frames) {
77
+ if (t < frame.endMs)
78
+ return frame.bitmap;
79
+ }
80
+ const last = decoded.frames[decoded.frames.length - 1];
81
+ return last ? last.bitmap : null;
82
+ },
83
+ totalDurationMs(data) {
84
+ return decodeCache.get(data)?.totalMs ?? 0;
85
+ },
86
+ };
87
+ let installed = false;
88
+ /**
89
+ * Register the built-in GIF animation adapter once. Idempotent — `<Editor>`
90
+ * calls this by default on mount, but hosts can also call it explicitly (or
91
+ * register their own `kind: "gif"` adapter to override it).
92
+ */
93
+ export const installGifAnimationAdapter = () => {
94
+ if (installed)
95
+ return;
96
+ installed = true;
97
+ registerAnimationAdapter(gifAdapter);
98
+ };
99
+ //# sourceMappingURL=gif-animation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gif-animation.js","sourceRoot":"","sources":["../src/gif-animation.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -15,15 +15,17 @@
15
15
  * full live engine (`EditorInstance` from `@oh-just-another/state`) as the
16
16
  * power-user escape hatch. See `EditorProps` for the customisation surface.
17
17
  *
18
- * `Diagram` is a deprecated alias for `Editor`, kept for back-compat.
18
+ * @deprecated `Diagram` use {@link Editor} instead.
19
19
  */
20
20
  export { Diagram as Editor, Diagram, type DiagramAPI as EditorAPI, type DiagramAPI, type DiagramProps as EditorProps, type DiagramProps, type DiagramTheme as EditorTheme, type DiagramTheme, } from "./Diagram.js";
21
21
  export { detectCapabilities, logCapabilities, type CapabilityProfile, type CapabilityOverrides, } from "./capabilities.js";
22
22
  export { isEditableTarget } from "./dom-focus.js";
23
+ export { bindEditorHotkeys, type HotkeyBindingOptions } from "@oh-just-another/state";
23
24
  export { exportSceneToPng, type PngExportBackground, type PngExportOptions } from "./png-export.js";
24
25
  export { registerBounder, registerLayoutKind } from "@oh-just-another/scene";
25
26
  export { registerElementRenderer, registerAnimationAdapter } from "@oh-just-another/renderer-core";
26
27
  export { registerMigration } from "@oh-just-another/serialization";
28
+ export { installGifAnimationAdapter } from "./gif-animation.js";
27
29
  export type { ElementId } from "@oh-just-another/types";
28
30
  export type { Editor as EditorInstance, Mode, FileDropHandler } from "@oh-just-another/state";
29
31
  export type { Scene, LayoutKindEntry } from "@oh-just-another/scene";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EACL,OAAO,IAAI,MAAM,EACjB,OAAO,EACP,KAAK,UAAU,IAAI,SAAS,EAC5B,KAAK,UAAU,EACf,KAAK,YAAY,IAAI,WAAW,EAChC,KAAK,YAAY,EACjB,KAAK,YAAY,IAAI,WAAW,EAChC,KAAK,YAAY,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,KAAK,mBAAmB,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAKpG,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAOnE,YAAY,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,YAAY,EAAE,MAAM,IAAI,cAAc,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9F,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACrE,YAAY,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,YAAY,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5E,YAAY,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EACL,OAAO,IAAI,MAAM,EACjB,OAAO,EACP,KAAK,UAAU,IAAI,SAAS,EAC5B,KAAK,UAAU,EACf,KAAK,YAAY,IAAI,WAAW,EAChC,KAAK,YAAY,EACjB,KAAK,YAAY,IAAI,WAAW,EAChC,KAAK,YAAY,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,KAAK,mBAAmB,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAKpG,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAGnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAOhE,YAAY,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,YAAY,EAAE,MAAM,IAAI,cAAc,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9F,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACrE,YAAY,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,YAAY,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5E,YAAY,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC"}
package/dist/index.js CHANGED
@@ -15,11 +15,12 @@
15
15
  * full live engine (`EditorInstance` from `@oh-just-another/state`) as the
16
16
  * power-user escape hatch. See `EditorProps` for the customisation surface.
17
17
  *
18
- * `Diagram` is a deprecated alias for `Editor`, kept for back-compat.
18
+ * @deprecated `Diagram` use {@link Editor} instead.
19
19
  */
20
20
  export { Diagram as Editor, Diagram, } from "./Diagram.js";
21
21
  export { detectCapabilities, logCapabilities, } from "./capabilities.js";
22
22
  export { isEditableTarget } from "./dom-focus.js";
23
+ export { bindEditorHotkeys } from "@oh-just-another/state";
23
24
  export { exportSceneToPng } from "./png-export.js";
24
25
  // Plug-in registries from the underlying packages, surfaced here so the
25
26
  // umbrella package is the single import for extending the editor without
@@ -27,4 +28,7 @@ export { exportSceneToPng } from "./png-export.js";
27
28
  export { registerBounder, registerLayoutKind } from "@oh-just-another/scene";
28
29
  export { registerElementRenderer, registerAnimationAdapter } from "@oh-just-another/renderer-core";
29
30
  export { registerMigration } from "@oh-just-another/serialization";
31
+ // Built-in GIF decoder — `<Editor>` installs it by default; exported so hosts
32
+ // can install it explicitly or opt into it without the component.
33
+ export { installGifAnimationAdapter } from "./gif-animation.js";
30
34
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EACL,OAAO,IAAI,MAAM,EACjB,OAAO,GAOR,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,EAClB,eAAe,GAGhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAmD,MAAM,iBAAiB,CAAC;AAEpG,wEAAwE;AACxE,yEAAyE;AACzE,0CAA0C;AAC1C,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EACL,OAAO,IAAI,MAAM,EACjB,OAAO,GAOR,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,EAClB,eAAe,GAGhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAA6B,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAmD,MAAM,iBAAiB,CAAC;AAEpG,wEAAwE;AACxE,yEAAyE;AACzE,0CAA0C;AAC1C,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,8EAA8E;AAC9E,kEAAkE;AAClE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC"}
@@ -1,21 +1,15 @@
1
1
  import { type Scene } from "@oh-just-another/scene";
2
2
  /**
3
3
  * Browser-side PNG export — renders the **full scene** (not just the
4
- * current viewport) into an OffscreenCanvas via the standard
5
- * `renderScene` + `renderLinks` pipeline, then converts to a PNG blob.
4
+ * current viewport) into an OffscreenCanvas via the `renderScene` +
5
+ * `renderLinks` pipeline, then converts to a PNG blob.
6
6
  *
7
7
  * Three variants, exposed as separate menu items:
8
8
  *
9
9
  * • "transparent" — no background fill, PNG alpha channel preserved.
10
10
  * • "color" — solid fill in the host's canvas colour.
11
11
  * • "color-and-grid" — solid fill + the same grid the user sees on
12
- * the canvas (same gridSize / gridStyle).
13
- *
14
- * This host-side helper is used instead of `@oh-just-another/exporter.exportPng`
15
- * because exporter's path goes through `@headless.renderToPng`, which pulls
16
- * `@resvg/resvg-js` (~3 MB WASM peer dep). For a browser host the kernel's
17
- * `Canvas2DTarget` + `renderScene` are already on hand — no extra
18
- * dependency, no SVG round-trip, identical visual output.
12
+ * the canvas (same gridStyle).
19
13
  *
20
14
  * Returns `null` when the scene has no shapes (host shows an alert).
21
15
  */
@@ -1 +1 @@
1
- {"version":3,"file":"png-export.d.ts","sourceRoot":"","sources":["../src/png-export.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,KAAK,EACX,MAAM,wBAAwB,CAAC;AAKhC;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,4DAA4D;AAC5D,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG,OAAO,GAAG,gBAAgB,CAAC;AAE7E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IACzC,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAUD,eAAO,MAAM,gBAAgB,GAC3B,OAAO,KAAK,EACZ,SAAS,gBAAgB,KACxB,OAAO,CAAC,IAAI,GAAG,IAAI,CA6DrB,CAAC"}
1
+ {"version":3,"file":"png-export.d.ts","sourceRoot":"","sources":["../src/png-export.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,KAAK,EACX,MAAM,wBAAwB,CAAC;AAMhC;;;;;;;;;;;;;GAaG;AAEH,4DAA4D;AAC5D,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG,OAAO,GAAG,gBAAgB,CAAC;AAE7E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IACzC,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,eAAO,MAAM,gBAAgB,GAC3B,OAAO,KAAK,EACZ,SAAS,gBAAgB,KACxB,OAAO,CAAC,IAAI,GAAG,IAAI,CAyDrB,CAAC"}
@@ -1,13 +1,7 @@
1
1
  import { getLayersInOrder, getElementWorldBounds, getElementsInLayer, } from "@oh-just-another/scene";
2
2
  import { renderLinks, renderGrid, renderScene } from "@oh-just-another/renderer-core";
3
3
  import { createOffscreenCanvas2DTarget } from "@oh-just-another/renderer-canvas";
4
- /**
5
- * Padding around the scene bbox, in world units. Matches the
6
- * `zoomToFit` default so the exported framing feels like "what fit
7
- * on screen would look like". Hosts that want a tight bbox can crop
8
- * after the fact.
9
- */
10
- const EXPORT_PADDING_WORLD = 20;
4
+ import { EXPORT_PADDING_WORLD } from "./constants.js";
11
5
  export const exportSceneToPng = async (scene, options) => {
12
6
  if (typeof OffscreenCanvas === "undefined")
13
7
  return null;
@@ -45,15 +39,13 @@ export const exportSceneToPng = async (scene, options) => {
45
39
  zoom: options.scale,
46
40
  rotation: 0,
47
41
  size: { width: canvasW, height: canvasH },
48
- ...(scene.viewport.gridSize !== undefined ? { gridSize: scene.viewport.gridSize } : {}),
42
+ gridEnabled: scene.viewport.gridEnabled,
49
43
  ...(scene.viewport.gridStyle !== undefined ? { gridStyle: scene.viewport.gridStyle } : {}),
50
44
  },
51
45
  };
52
- // Grid pass — only for the color-and-grid variant. Skipped when the
53
- // scene has no gridSize (user disabled it).
54
- if (options.background === "color-and-grid" &&
55
- exportScene.viewport.gridSize &&
56
- exportScene.viewport.gridSize > 0) {
46
+ // Grid pass — only for the color-and-grid variant, and only when the scene
47
+ // has the grid enabled.
48
+ if (options.background === "color-and-grid" && exportScene.viewport.gridEnabled) {
57
49
  renderGrid(exportScene, target);
58
50
  }
59
51
  // Shapes (skipClear: true so background / grid survive).
@@ -1 +1 @@
1
- {"version":3,"file":"png-export.js","sourceRoot":"","sources":["../src/png-export.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,GAEnB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AACtF,OAAO,EAAE,6BAA6B,EAAE,MAAM,kCAAkC,CAAC;AAsCjF;;;;;GAKG;AACH,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEhC,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EACnC,KAAY,EACZ,OAAyB,EACH,EAAE;IACxB,IAAI,OAAO,eAAe,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAExD,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC,CAAC,oCAAoC;IAE5D,MAAM,MAAM,GAAW;QACrB,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,oBAAoB;QAChC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,oBAAoB;QAChC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC,GAAG,oBAAoB;QAC5C,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,oBAAoB;KAC/C,CAAC;IAEF,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IACrE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAEtE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,6BAA6B,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAE3E,mEAAmE;IACnE,gEAAgE;IAChE,qEAAqE;IACrE,6BAA6B;IAC7B,IAAI,OAAO,CAAC,UAAU,KAAK,aAAa,EAAE,CAAC;QACzC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QACxC,MAAM,CAAC,SAAS,EAAE,CAAC;QACnB,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACpC,MAAM,CAAC,IAAI,EAAE,CAAC;IAChB,CAAC;IAED,iEAAiE;IACjE,qDAAqD;IACrD,4DAA4D;IAC5D,4DAA4D;IAC5D,kEAAkE;IAClE,MAAM,WAAW,GAAU;QACzB,GAAG,KAAK;QACR,QAAQ,EAAE;YACR,GAAG,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE;YACjC,IAAI,EAAE,OAAO,CAAC,KAAK;YACnB,QAAQ,EAAE,CAAC;YACX,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;YACzC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvF,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC3F;KACF,CAAC;IAEF,oEAAoE;IACpE,4CAA4C;IAC5C,IACE,OAAO,CAAC,UAAU,KAAK,gBAAgB;QACvC,WAAW,CAAC,QAAQ,CAAC,QAAQ;QAC7B,WAAW,CAAC,QAAQ,CAAC,QAAQ,GAAG,CAAC,EACjC,CAAC;QACD,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,yDAAyD;IACzD,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAEjC,OAAO,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;AACrD,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,KAAY,EAAiB,EAAE;IACvD,IAAI,GAAG,GAAkB,IAAI,CAAC;IAC9B,KAAK,MAAM,KAAK,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5C,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,SAAS;QAC7B,KAAK,MAAM,KAAK,IAAI,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;YACxD,MAAM,CAAC,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;YACvC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,yEAAyE;AACzE,MAAM,WAAW,GAAG,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE;IACnD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IACxD,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;AACxD,CAAC,CAAC"}
1
+ {"version":3,"file":"png-export.js","sourceRoot":"","sources":["../src/png-export.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { DiagramTheme } from "./Diagram.js";
2
+ /**
3
+ * Create a portal container that mirrors the editor's `theme` as a `data-theme`
4
+ * attribute, nested inside whatever portal container is already in effect
5
+ * (another provider, or `document.body` by default).
6
+ *
7
+ * Floating chrome (the selection / property panel, popovers, tooltips, menus)
8
+ * portals out of the editor's clipped subtree. That also escapes the
9
+ * `data-theme` set on the editor root, so the stylesheet's `:root` +
10
+ * `prefers-color-scheme` fallback leaks the OS theme into the portaled UI —
11
+ * e.g. a dark menu while the app is set to light. Portaling into this themed
12
+ * wrapper instead makes the floating UI inherit the editor's chosen theme
13
+ * regardless of the OS preference.
14
+ *
15
+ * Nesting (rather than always appending to `document.body`) preserves any host
16
+ * setup: the web-component wrapper portals into a shadow-internal layer so its
17
+ * adopted stylesheet still reaches the menus — this wrapper stays inside it.
18
+ *
19
+ * `"system"` removes the attribute so the media query (OS theme) takes over,
20
+ * matching the editor root. The element is unstyled and unpositioned, so it
21
+ * never creates a containing block — absolutely / fixed positioned portal
22
+ * children resolve exactly as they did against the parent container.
23
+ */
24
+ export declare const useThemedPortalContainer: (theme: DiagramTheme) => HTMLElement | null;
25
+ //# sourceMappingURL=themed-portal-container.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"themed-portal-container.d.ts","sourceRoot":"","sources":["../src/themed-portal-container.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,wBAAwB,GAAI,OAAO,YAAY,KAAG,WAAW,GAAG,IAsB5E,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { useEffect, useState } from "react";
2
+ import { usePortalContainer } from "@oh-just-another/react-ui";
3
+ /**
4
+ * Create a portal container that mirrors the editor's `theme` as a `data-theme`
5
+ * attribute, nested inside whatever portal container is already in effect
6
+ * (another provider, or `document.body` by default).
7
+ *
8
+ * Floating chrome (the selection / property panel, popovers, tooltips, menus)
9
+ * portals out of the editor's clipped subtree. That also escapes the
10
+ * `data-theme` set on the editor root, so the stylesheet's `:root` +
11
+ * `prefers-color-scheme` fallback leaks the OS theme into the portaled UI —
12
+ * e.g. a dark menu while the app is set to light. Portaling into this themed
13
+ * wrapper instead makes the floating UI inherit the editor's chosen theme
14
+ * regardless of the OS preference.
15
+ *
16
+ * Nesting (rather than always appending to `document.body`) preserves any host
17
+ * setup: the web-component wrapper portals into a shadow-internal layer so its
18
+ * adopted stylesheet still reaches the menus — this wrapper stays inside it.
19
+ *
20
+ * `"system"` removes the attribute so the media query (OS theme) takes over,
21
+ * matching the editor root. The element is unstyled and unpositioned, so it
22
+ * never creates a containing block — absolutely / fixed positioned portal
23
+ * children resolve exactly as they did against the parent container.
24
+ */
25
+ export const useThemedPortalContainer = (theme) => {
26
+ const parent = usePortalContainer();
27
+ const [el] = useState(() => typeof document === "undefined" ? null : document.createElement("div"));
28
+ useEffect(() => {
29
+ if (!el)
30
+ return;
31
+ el.setAttribute("data-diagram-portal", "");
32
+ parent.appendChild(el);
33
+ return () => {
34
+ el.remove();
35
+ };
36
+ }, [el, parent]);
37
+ useEffect(() => {
38
+ if (!el)
39
+ return;
40
+ if (theme === "system")
41
+ el.removeAttribute("data-theme");
42
+ else
43
+ el.setAttribute("data-theme", theme);
44
+ }, [el, theme]);
45
+ return el;
46
+ };
47
+ //# sourceMappingURL=themed-portal-container.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"themed-portal-container.js","sourceRoot":"","sources":["../src/themed-portal-container.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,KAAmB,EAAsB,EAAE;IAClF,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAC;IACpC,MAAM,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAwB,GAAG,EAAE,CAChD,OAAO,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CACvE,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,EAAE,CAAC,YAAY,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;QAC3C,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACvB,OAAO,GAAG,EAAE;YACV,EAAE,CAAC,MAAM,EAAE,CAAC;QACd,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IAEjB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,IAAI,KAAK,KAAK,QAAQ;YAAE,EAAE,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;;YACpD,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IAEhB,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oh-just-another/editor",
3
- "version": "0.58.2",
3
+ "version": "0.59.0",
4
4
  "description": "Drop-in diagram editor as a single React component. Auto-detects renderer / WASM / worker capabilities and exposes a programmatic editor API.",
5
5
  "license": "MIT",
6
6
  "author": "Rustam Garifulin <rustam@n69.in>",
@@ -39,17 +39,19 @@
39
39
  "access": "public"
40
40
  },
41
41
  "dependencies": {
42
- "lucide-react": "^1.16.0",
43
- "@oh-just-another/react-ui": "0.57.3",
44
- "@oh-just-another/raster-wasm": "0.57.1",
45
- "@oh-just-another/renderer-canvas": "0.58.1",
46
- "@oh-just-another/renderer-core": "0.57.1",
47
- "@oh-just-another/renderer-svg": "0.57.1",
48
- "@oh-just-another/state": "0.58.0",
49
- "@oh-just-another/serialization": "0.57.1",
50
- "@oh-just-another/scene": "0.58.0",
51
- "@oh-just-another/templates": "0.57.1",
52
- "@oh-just-another/text-wasm": "0.57.1",
42
+ "gifuct-js": "2.1.2",
43
+ "lucide-react": "1.16.0",
44
+ "@oh-just-another/fonts": "0.1.0",
45
+ "@oh-just-another/raster-wasm": "0.57.2",
46
+ "@oh-just-another/react-ui": "0.58.0",
47
+ "@oh-just-another/renderer-canvas": "0.59.0",
48
+ "@oh-just-another/renderer-core": "0.58.0",
49
+ "@oh-just-another/renderer-svg": "0.57.2",
50
+ "@oh-just-another/scene": "0.59.0",
51
+ "@oh-just-another/serialization": "0.58.0",
52
+ "@oh-just-another/state": "0.59.0",
53
+ "@oh-just-another/templates": "0.57.2",
54
+ "@oh-just-another/text-wasm": "0.57.2",
53
55
  "@oh-just-another/types": "0.57.0"
54
56
  },
55
57
  "peerDependencies": {
@@ -57,12 +59,12 @@
57
59
  "react-dom": ">=18"
58
60
  },
59
61
  "devDependencies": {
60
- "@testing-library/react": "^16.1.0",
61
- "@types/react": "^19.0.0",
62
- "@types/react-dom": "^19.0.0",
63
- "jsdom": "^25.0.0",
64
- "react": "^19.0.0",
65
- "react-dom": "^19.0.0"
62
+ "@testing-library/react": "16.3.2",
63
+ "@types/react": "19.2.15",
64
+ "@types/react-dom": "19.2.3",
65
+ "jsdom": "25.0.1",
66
+ "react": "19.2.6",
67
+ "react-dom": "19.2.6"
66
68
  },
67
69
  "scripts": {
68
70
  "build": "tsc -b tsconfig.build.json",