sketchmark 2.1.9 → 2.2.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.
package/bin/editor-ui.cjs CHANGED
@@ -699,6 +699,7 @@ async function deleteTreeElement(id) {
699
699
  }
700
700
 
701
701
  function renderTree() {
702
+ const elementsScroll = captureElementsTreeScroll();
702
703
  const canvas = doc && doc.canvas ? doc.canvas : {};
703
704
  const canvasSummary = Math.round(valueOr(canvas.width, 1)) + "x" + Math.round(valueOr(canvas.height, 1));
704
705
  const canvasBody =
@@ -785,6 +786,7 @@ function renderTree() {
785
786
  treeRoot.appendChild(row);
786
787
  }
787
788
  resizeElementsTree();
789
+ restoreElementsTreeScroll(elementsScroll);
788
790
  }
789
791
 
790
792
  function resizeElementsTree() {
@@ -802,8 +804,28 @@ function resizeElementsTree() {
802
804
  const available = treeRect.bottom - bodyRect.top - fixedRect.height - paddingBottom - 6;
803
805
  treeRoot.style.maxHeight = Math.max(72, Math.floor(available)) + "px";
804
806
  }
805
-
806
- function bindCanvasInputs() {
807
+
808
+ function captureElementsTreeScroll() {
809
+ const treeRoot = document.getElementById("elementsTree");
810
+ return treeRoot ? { top: treeRoot.scrollTop, left: treeRoot.scrollLeft } : { top: 0, left: 0 };
811
+ }
812
+
813
+ function restoreElementsTreeScroll(scroll) {
814
+ const treeRoot = document.getElementById("elementsTree");
815
+ if (!treeRoot || !scroll) return;
816
+ const top = Math.max(0, Number(scroll.top) || 0);
817
+ const left = Math.max(0, Number(scroll.left) || 0);
818
+ treeRoot.scrollTop = top;
819
+ treeRoot.scrollLeft = left;
820
+ requestAnimationFrame(() => {
821
+ const nextRoot = document.getElementById("elementsTree");
822
+ if (!nextRoot) return;
823
+ nextRoot.scrollTop = top;
824
+ nextRoot.scrollLeft = left;
825
+ });
826
+ }
827
+
828
+ function bindCanvasInputs() {
807
829
  const bind = (id, callback) => {
808
830
  const input = document.getElementById(id);
809
831
  if (!input) return;
@@ -2191,12 +2213,14 @@ function scheduleSidebarKeyframe(property, valueReader) {
2191
2213
  }, 120);
2192
2214
  }
2193
2215
 
2194
- function readNumberInput(id) {
2195
- const input = document.getElementById(id);
2196
- if (!input) return NaN;
2197
- const value = Number(input.value);
2198
- return Number.isFinite(value) ? value : NaN;
2199
- }
2216
+ function readNumberInput(id) {
2217
+ const input = document.getElementById(id);
2218
+ if (!input) return NaN;
2219
+ const raw = String(input.value ?? "").trim();
2220
+ if (!raw) return NaN;
2221
+ const value = Number(raw);
2222
+ return Number.isFinite(value) ? value : NaN;
2223
+ }
2200
2224
 
2201
2225
  function readTextInput(id) {
2202
2226
  const input = document.getElementById(id);
@@ -2224,11 +2248,11 @@ async function mutate(path, body, options) {
2224
2248
  if (currentTime > duration) currentTime = duration;
2225
2249
  rebuildElementIndex();
2226
2250
  if (selectedId && !findElement(selectedId)) selectedId = "";
2227
- if (refreshTree) renderTree();
2228
- if (refreshInspector) renderInspector();
2229
- if (refreshTimeline) renderTimeline();
2230
- requestDraw();
2231
- }
2251
+ if (refreshTree) renderTree();
2252
+ if (refreshInspector) renderInspector();
2253
+ if (refreshTimeline) renderTimeline();
2254
+ if (!options || options.requestDraw !== false) requestDraw();
2255
+ }
2232
2256
 
2233
2257
  stageWrap.addEventListener("wheel", (event) => {
2234
2258
  if (!stage.contains(event.target)) return;
@@ -2349,9 +2373,11 @@ stage.addEventListener("pointermove", (event) => {
2349
2373
  drag.changed = drag.changed || Math.abs(dx) > 0.25 || Math.abs(dy) > 0.25;
2350
2374
  let x = drag.x;
2351
2375
  let y = drag.y;
2352
- let rotation = drag.rotation;
2353
- let scale = drag.scale;
2354
- if (drag.mode === "move") {
2376
+ let rotation = drag.rotation;
2377
+ let scale = drag.scale;
2378
+ let scaleX = drag.scaleX;
2379
+ let scaleY = drag.scaleY;
2380
+ if (drag.mode === "move") {
2355
2381
  x = Math.round(drag.x + dx);
2356
2382
  y = Math.round(drag.y + dy);
2357
2383
  setInput("propX", x);
@@ -2363,18 +2389,25 @@ stage.addEventListener("pointermove", (event) => {
2363
2389
  rotation = Math.round((drag.rotation + delta) * 100) / 100;
2364
2390
  setInput("propRotation", rotation);
2365
2391
  previewDraggedTransform("rotate(" + delta + " " + drag.center.x + " " + drag.center.y + ")");
2366
- } else {
2367
- const startDistance = Math.max(distance(drag.center, drag.start), 1);
2368
- const nextDistance = Math.max(distance(drag.center, point), 1);
2369
- const ratio = Math.max(0.05, nextDistance / startDistance);
2370
- drag.changed = drag.changed || Math.abs(ratio - 1) > 0.005;
2371
- scale = Math.max(0.05, Math.round((drag.scale * ratio) * 100) / 100);
2372
- setInput("propScale", scale);
2373
- previewDraggedTransform("translate(" + drag.center.x + " " + drag.center.y + ") scale(" + ratio + ") translate(" + (-drag.center.x) + " " + (-drag.center.y) + ")");
2374
- }
2375
- drag.value = { x, y, rotation, scale };
2376
- refreshHandles();
2377
- });
2392
+ } else {
2393
+ const startDistance = Math.max(distance(drag.center, drag.start), 1);
2394
+ const nextDistance = Math.max(distance(drag.center, point), 1);
2395
+ const ratio = Math.max(0.05, nextDistance / startDistance);
2396
+ drag.changed = drag.changed || Math.abs(ratio - 1) > 0.005;
2397
+ if (drag.usesAxisScale) {
2398
+ scaleX = scaleComponentValue(drag.scaleX, ratio);
2399
+ scaleY = scaleComponentValue(drag.scaleY, ratio);
2400
+ setInput("propScaleX", scaleX);
2401
+ setInput("propScaleY", scaleY);
2402
+ } else {
2403
+ scale = scaleComponentValue(drag.scale, ratio);
2404
+ setInput("propScale", scale);
2405
+ }
2406
+ previewDraggedTransform("translate(" + drag.center.x + " " + drag.center.y + ") scale(" + ratio + ") translate(" + (-drag.center.x) + " " + (-drag.center.y) + ")");
2407
+ }
2408
+ drag.value = { x, y, rotation, scale, scaleX, scaleY };
2409
+ refreshHandles();
2410
+ });
2378
2411
 
2379
2412
  stage.addEventListener("pointerup", finishDrag);
2380
2413
  stage.addEventListener("pointercancel", finishDrag);
@@ -2400,21 +2433,25 @@ async function finishDrag() {
2400
2433
 
2401
2434
  function startDrag(event, target, mode) {
2402
2435
  if (!target || isElementLocked(target.id) || isElementHidden(target.id)) return;
2403
- const element = findElement(target.id);
2404
- if (!element) return;
2405
- const resolved = findResolvedElement(target.id) || element;
2406
- drag = {
2436
+ const element = findElement(target.id);
2437
+ if (!element) return;
2438
+ const resolved = findResolvedElement(target.id) || element;
2439
+ const scaleState = resolvedScaleState(resolved, element);
2440
+ drag = {
2407
2441
  id: target.id,
2408
2442
  target,
2409
2443
  mode,
2410
2444
  start: parentPoint(event, target),
2411
2445
  center: targetCenterInParent(target),
2412
- x: Number(resolved.x ?? element.x ?? 0),
2413
- y: Number(resolved.y ?? element.y ?? 0),
2414
- rotation: Number(resolved.rotation ?? element.rotation ?? 0),
2415
- scale: Number(resolved.scale ?? element.scale ?? 1),
2416
- transform: target.getAttribute("transform") || "",
2417
- changed: false,
2446
+ x: Number(resolved.x ?? element.x ?? 0),
2447
+ y: Number(resolved.y ?? element.y ?? 0),
2448
+ rotation: Number(resolved.rotation ?? element.rotation ?? 0),
2449
+ scale: scaleState.scale,
2450
+ scaleX: scaleState.scaleX,
2451
+ scaleY: scaleState.scaleY,
2452
+ usesAxisScale: scaleState.usesAxisScale,
2453
+ transform: target.getAttribute("transform") || "",
2454
+ changed: false,
2418
2455
  value: null
2419
2456
  };
2420
2457
  event.preventDefault();
@@ -2427,17 +2464,22 @@ async function commitDrag(snapshot) {
2427
2464
  if (!element || !snapshot.value) return;
2428
2465
  if (snapshot.mode === "move") {
2429
2466
  await commitEditedProperty(element, "position", [snapshot.value.x, snapshot.value.y]);
2430
- } else if (snapshot.mode === "rotate") {
2431
- await commitEditedProperty(element, "rotation", snapshot.value.rotation);
2432
- } else if (snapshot.mode === "scale") {
2433
- await commitEditedProperty(element, "scale", snapshot.value.scale);
2434
- }
2435
- }
2436
-
2437
- async function commitEditedProperty(element, property, value) {
2438
- if (!ensureElementEditable(element.id)) return;
2439
- await mutate(apiPath("/keyframe"), { id: element.id, property, value, time: currentTime, curvePreset: "linear" });
2440
- }
2467
+ } else if (snapshot.mode === "rotate") {
2468
+ await commitEditedProperty(element, "rotation", snapshot.value.rotation);
2469
+ } else if (snapshot.mode === "scale") {
2470
+ if (snapshot.usesAxisScale) {
2471
+ await commitEditedProperty(element, "scaleX", snapshot.value.scaleX, { refreshTree: false, refreshInspector: false, refreshTimeline: false, requestDraw: false });
2472
+ await commitEditedProperty(element, "scaleY", snapshot.value.scaleY);
2473
+ } else {
2474
+ await commitEditedProperty(element, "scale", snapshot.value.scale);
2475
+ }
2476
+ }
2477
+ }
2478
+
2479
+ async function commitEditedProperty(element, property, value, options) {
2480
+ if (!ensureElementEditable(element.id)) return;
2481
+ await mutate(apiPath("/keyframe"), { id: element.id, property, value, time: currentTime, curvePreset: "linear" }, options);
2482
+ }
2441
2483
 
2442
2484
  function ensureElementEditable(id) {
2443
2485
  if (!id) return false;
@@ -2540,13 +2582,13 @@ function drawHandles(target) {
2540
2582
  const old = svg.querySelector("#__sketchmark_handles");
2541
2583
  if (old) old.remove();
2542
2584
  let box;
2543
- let matrix;
2544
- try {
2545
- box = target.getBBox();
2546
- matrix = elementMatrixInSvg(target, svg);
2547
- } catch {
2548
- return;
2549
- }
2585
+ let matrix;
2586
+ try {
2587
+ box = editorHandleBox(target.getBBox());
2588
+ matrix = elementMatrixInSvg(target, svg);
2589
+ } catch {
2590
+ return;
2591
+ }
2550
2592
  if (!matrix) return;
2551
2593
  const topLeft = matrixPoint(svg, matrix, box.x, box.y);
2552
2594
  const topRight = matrixPoint(svg, matrix, box.x + box.width, box.y);
@@ -2611,17 +2653,34 @@ function elementMatrixInSvg(target, svg) {
2611
2653
  function targetCenterInParent(target) {
2612
2654
  const svg = target.ownerSVGElement || stage.querySelector("svg");
2613
2655
  if (!svg || !target.getBBox || !target.getCTM) return { x: 0, y: 0 };
2614
- try {
2615
- const box = target.getBBox();
2616
- const targetMatrix = target.getCTM();
2617
- const parent = target.parentNode && target.parentNode.getCTM ? target.parentNode : svg;
2618
- const parentMatrix = parent.getCTM ? parent.getCTM() : null;
2656
+ try {
2657
+ const box = editorHandleBox(target.getBBox());
2658
+ const targetMatrix = target.getCTM();
2659
+ const parent = target.parentNode && target.parentNode.getCTM ? target.parentNode : svg;
2660
+ const parentMatrix = parent.getCTM ? parent.getCTM() : null;
2619
2661
  if (!targetMatrix || !parentMatrix) return { x: box.x + box.width / 2, y: box.y + box.height / 2 };
2620
2662
  return matrixPoint(svg, parentMatrix.inverse().multiply(targetMatrix), box.x + box.width / 2, box.y + box.height / 2);
2621
2663
  } catch {
2622
- return { x: 0, y: 0 };
2623
- }
2624
- }
2664
+ return { x: 0, y: 0 };
2665
+ }
2666
+ }
2667
+ function editorHandleBox(box) {
2668
+ const minSize = 18;
2669
+ const x = Number(box && box.x || 0);
2670
+ const y = Number(box && box.y || 0);
2671
+ const width = Math.max(0, Number(box && box.width || 0));
2672
+ const height = Math.max(0, Number(box && box.height || 0));
2673
+ const centerX = x + width / 2;
2674
+ const centerY = y + height / 2;
2675
+ const stableWidth = width < minSize ? minSize : width;
2676
+ const stableHeight = height < minSize ? minSize : height;
2677
+ return {
2678
+ x: centerX - stableWidth / 2,
2679
+ y: centerY - stableHeight / 2,
2680
+ width: stableWidth,
2681
+ height: stableHeight
2682
+ };
2683
+ }
2625
2684
  function matrixPoint(svg, matrix, x, y) {
2626
2685
  const point = svg.createSVGPoint();
2627
2686
  point.x = x;
@@ -2644,14 +2703,33 @@ function svgNode(name) {
2644
2703
  function angleAround(center, point) {
2645
2704
  return Math.atan2(point.y - center.y, point.x - center.x) * 180 / Math.PI;
2646
2705
  }
2647
- function distance(a, b) {
2648
- const dx = a.x - b.x;
2649
- const dy = a.y - b.y;
2650
- return Math.sqrt(dx * dx + dy * dy);
2651
- }
2652
- function supportsPosition(element) {
2653
- return element && ["path","point","text","image","group"].includes(element.type);
2654
- }
2706
+ function distance(a, b) {
2707
+ const dx = a.x - b.x;
2708
+ const dy = a.y - b.y;
2709
+ return Math.sqrt(dx * dx + dy * dy);
2710
+ }
2711
+ function scaleComponentValue(value, ratio) {
2712
+ const sign = Number(value) < 0 ? -1 : 1;
2713
+ const next = Number(value) * Number(ratio);
2714
+ const clamped = Math.max(0.05, Math.abs(Number.isFinite(next) ? next : sign * 0.05));
2715
+ return Math.round(sign * clamped * 100) / 100;
2716
+ }
2717
+ function resolvedScaleState(resolved, element) {
2718
+ const tracks = element && element.timeline && element.timeline.tracks ? element.timeline.tracks : {};
2719
+ const usesAxisScale = resolved.scaleX !== undefined || resolved.scaleY !== undefined || element.scaleX !== undefined || element.scaleY !== undefined || tracks.scaleX || tracks.scaleY;
2720
+ const baseScale = finiteNumber(resolved.scale ?? element.scale, 1);
2721
+ const scaleX = finiteNumber(resolved.scaleX ?? element.scaleX, baseScale);
2722
+ const scaleY = finiteNumber(resolved.scaleY ?? element.scaleY, baseScale);
2723
+ return {
2724
+ scale: baseScale,
2725
+ scaleX,
2726
+ scaleY,
2727
+ usesAxisScale: Boolean(usesAxisScale)
2728
+ };
2729
+ }
2730
+ function supportsPosition(element) {
2731
+ return element && ["path","point","text","image","group"].includes(element.type);
2732
+ }
2655
2733
  function setInput(id, value) {
2656
2734
  const input = document.getElementById(id);
2657
2735
  if (input) input.value = value;
@@ -2752,18 +2830,67 @@ function setPointInputs(prefix, point) {
2752
2830
  setInput(prefix + "X", valueOr(value[0], 0));
2753
2831
  setInput(prefix + "Y", valueOr(value[1], 0));
2754
2832
  }
2755
- function originPointValue(element) {
2756
- if (Array.isArray(element && element.origin) && element.origin.length === 2) {
2757
- const x = Number(element.origin[0]);
2758
- const y = Number(element.origin[1]);
2759
- if (Number.isFinite(x) && Number.isFinite(y)) return [x, y];
2760
- }
2761
- const x = Number(element && element.x);
2762
- const y = Number(element && element.y);
2763
- if (Number.isFinite(x) && Number.isFinite(y)) return [x, y];
2764
- return [0, 0];
2765
- }
2766
- function valueOr(value, fallback) { return value === undefined ? fallback : value; }
2833
+ function originPointValue(element) {
2834
+ if (Array.isArray(element && element.origin) && element.origin.length === 2) {
2835
+ const x = Number(element.origin[0]);
2836
+ const y = Number(element.origin[1]);
2837
+ if (Number.isFinite(x) && Number.isFinite(y)) return [x, y];
2838
+ }
2839
+ if (element && element.type === "group") {
2840
+ return [
2841
+ finiteNumber(element.x, 0) + finiteNumber(element.width, 0) / 2,
2842
+ finiteNumber(element.y, 0) + finiteNumber(element.height, 0) / 2
2843
+ ];
2844
+ }
2845
+ const x = Number(element && element.x);
2846
+ const y = Number(element && element.y);
2847
+ if (element && (element.type === "text" || element.type === "point") && Number.isFinite(x) && Number.isFinite(y)) return [x, y];
2848
+ const box = editorElementBox(element);
2849
+ if (box) return [box.x + box.width / 2, box.y + box.height / 2];
2850
+ if (Number.isFinite(x) && Number.isFinite(y)) return [x, y];
2851
+ return [0, 0];
2852
+ }
2853
+ function valueOr(value, fallback) { return value === undefined ? fallback : value; }
2854
+ function editorElementBox(element) {
2855
+ if (!element) return null;
2856
+ const target = element.id ? stage.querySelector("#" + cssId(element.id)) : null;
2857
+ if (target && target.getBBox) {
2858
+ try {
2859
+ const box = target.getBBox();
2860
+ if (Number.isFinite(box.x) && Number.isFinite(box.y) && Number.isFinite(box.width) && Number.isFinite(box.height)) {
2861
+ return { x: box.x, y: box.y, width: box.width, height: box.height };
2862
+ }
2863
+ } catch {}
2864
+ }
2865
+ if (element.type === "image" || element.type === "group") {
2866
+ const x = Number(element.x);
2867
+ const y = Number(element.y);
2868
+ const width = Number(element.width);
2869
+ const height = Number(element.height);
2870
+ if ([x, y, width, height].every(Number.isFinite)) return { x, y, width, height };
2871
+ }
2872
+ if (element.type === "path" && typeof element.d === "string") return pathDataBox(element.d);
2873
+ return null;
2874
+ }
2875
+ function pathDataBox(data) {
2876
+ const numbers = String(data || "").match(/-?\\d+(?:\\.\\d+)?(?:e[+-]?\\d+)?/gi);
2877
+ if (!numbers || numbers.length < 2) return null;
2878
+ let minX = Infinity;
2879
+ let minY = Infinity;
2880
+ let maxX = -Infinity;
2881
+ let maxY = -Infinity;
2882
+ for (let index = 0; index < numbers.length - 1; index += 2) {
2883
+ const x = Number(numbers[index]);
2884
+ const y = Number(numbers[index + 1]);
2885
+ if (!Number.isFinite(x) || !Number.isFinite(y)) continue;
2886
+ minX = Math.min(minX, x);
2887
+ minY = Math.min(minY, y);
2888
+ maxX = Math.max(maxX, x);
2889
+ maxY = Math.max(maxY, y);
2890
+ }
2891
+ if (![minX, minY, maxX, maxY].every(Number.isFinite)) return null;
2892
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
2893
+ }
2767
2894
  function clipRadiusValue(element) {
2768
2895
  if (!element || !element.clip || typeof element.clip.d !== "string") return 0;
2769
2896
  const numbers = element.clip.d.match(/-?\\d+(?:\\.\\d+)?(?:e[+-]?\\d+)?/gi);
@@ -0,0 +1 @@
1
+ export function previewHtml(title: string): string;
@@ -58,3 +58,4 @@ export declare function listTimelineTracks(document: VisualDocument, id: string)
58
58
  }>;
59
59
  export declare function roundedRectClipPath(x: number, y: number, width: number, height: number, radius?: number): string;
60
60
  export declare function imageRoundedClip(element: Pick<ImageElement, "x" | "y" | "width" | "height">, radius?: number): ClipShape;
61
+ export { deleteElement as remove, findElementById as find, insertElementPreset as insertPreset, listElementReferences as listReferences, listTimelineTracks as listTracks, removeTimelineKeyframe as removeKeyframe, reorderElement as reorder, setElementProperty as setProperty, setTimelineKeyframe as setKeyframe };
package/dist/src/edit.js CHANGED
@@ -1,14 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.listElementReferences = listElementReferences;
4
+ exports.listReferences = listElementReferences;
4
5
  exports.findElementById = findElementById;
6
+ exports.find = findElementById;
5
7
  exports.insertElementPreset = insertElementPreset;
8
+ exports.insertPreset = insertElementPreset;
6
9
  exports.reorderElement = reorderElement;
10
+ exports.reorder = reorderElement;
7
11
  exports.deleteElement = deleteElement;
12
+ exports.remove = deleteElement;
8
13
  exports.setElementProperty = setElementProperty;
14
+ exports.setProperty = setElementProperty;
9
15
  exports.setTimelineKeyframe = setTimelineKeyframe;
16
+ exports.setKeyframe = setTimelineKeyframe;
10
17
  exports.removeTimelineKeyframe = removeTimelineKeyframe;
18
+ exports.removeKeyframe = removeTimelineKeyframe;
11
19
  exports.listTimelineTracks = listTimelineTracks;
20
+ exports.listTracks = listTimelineTracks;
12
21
  exports.roundedRectClipPath = roundedRectClipPath;
13
22
  exports.imageRoundedClip = imageRoundedClip;
14
23
  const animatable_1 = require("./animatable");
@@ -5,8 +5,10 @@ export * from "./diagnostics";
5
5
  export * from "./schema";
6
6
  export * from "./keyframes";
7
7
  export * from "./edit";
8
+ export * as edit from "./edit";
8
9
  export { deleteElement, insertElementPreset, reorderElement } from "./edit";
9
10
  export * from "./animatable";
11
+ export * as render from "./render";
10
12
  export * from "./render/svg";
11
13
  export * from "./render/html";
12
14
  export * from "./render/embed";
package/dist/src/index.js CHANGED
@@ -10,11 +10,33 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
10
10
  if (k2 === undefined) k2 = k;
11
11
  o[k2] = m[k];
12
12
  }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
13
18
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
19
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
20
  };
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
16
38
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.reorderElement = exports.insertElementPreset = exports.deleteElement = void 0;
39
+ exports.render = exports.reorderElement = exports.insertElementPreset = exports.deleteElement = exports.edit = void 0;
18
40
  __exportStar(require("./types"), exports);
19
41
  __exportStar(require("./validate"), exports);
20
42
  __exportStar(require("./normalize"), exports);
@@ -22,11 +44,13 @@ __exportStar(require("./diagnostics"), exports);
22
44
  __exportStar(require("./schema"), exports);
23
45
  __exportStar(require("./keyframes"), exports);
24
46
  __exportStar(require("./edit"), exports);
47
+ exports.edit = __importStar(require("./edit"));
25
48
  var edit_1 = require("./edit");
26
49
  Object.defineProperty(exports, "deleteElement", { enumerable: true, get: function () { return edit_1.deleteElement; } });
27
50
  Object.defineProperty(exports, "insertElementPreset", { enumerable: true, get: function () { return edit_1.insertElementPreset; } });
28
51
  Object.defineProperty(exports, "reorderElement", { enumerable: true, get: function () { return edit_1.reorderElement; } });
29
52
  __exportStar(require("./animatable"), exports);
53
+ exports.render = __importStar(require("./render"));
30
54
  __exportStar(require("./render/svg"), exports);
31
55
  __exportStar(require("./render/html"), exports);
32
56
  __exportStar(require("./render/embed"), exports);
@@ -19,6 +19,7 @@ function renderToEmbedHtml(document, options = {}) {
19
19
  const initialFrameIndex = frameIndexForTime(initialTime, frameTimes);
20
20
  const initialFrame = frames[initialFrameIndex] ?? frames[0] ?? (0, svg_1.renderToSvg)(document, options);
21
21
  const chromeBackground = escapeHtml(String(options.chromeBackground ?? "transparent"));
22
+ const mp4MuxerRuntimeSource = inlineMp4MuxerRuntime(mp4_muxer_source_1.MP4_MUXER_SOURCE);
22
23
  const statusLabel = escapeHtml(title || "Sketchmark embed");
23
24
  const payload = {
24
25
  title,
@@ -225,9 +226,11 @@ function renderToEmbedHtml(document, options = {}) {
225
226
  </details>` : ""}
226
227
  <div id="meta">${statusLabel}</div>
227
228
  </div>
229
+ <script>
230
+ ${mp4MuxerRuntimeSource}
231
+ </script>
228
232
  <script>
229
233
  const payload = ${serializeForScript(payload)};
230
- const mp4MuxerSource = ${serializeForScript(mp4_muxer_source_1.MP4_MUXER_SOURCE)};
231
234
  const stage = document.getElementById("stage");
232
235
  const playButton = document.getElementById("play");
233
236
  const slider = document.getElementById("time");
@@ -244,7 +247,6 @@ function renderToEmbedHtml(document, options = {}) {
244
247
  };
245
248
  let metaTimer = 0;
246
249
  let exportBusy = false;
247
- let mp4MuxerModulePromise = null;
248
250
 
249
251
  function clampTime(value) {
250
252
  if (!payload.duration) return 0;
@@ -372,9 +374,7 @@ function renderToEmbedHtml(document, options = {}) {
372
374
  }
373
375
 
374
376
  function loadSvgImage(svg) {
375
- const blob = new Blob([svg], { type: "image/svg+xml;charset=utf-8" });
376
- const url = URL.createObjectURL(blob);
377
- return loadImage(url).finally(() => URL.revokeObjectURL(url));
377
+ return loadImage(svgDataUrl(svg));
378
378
  }
379
379
 
380
380
  function loadImage(url) {
@@ -386,6 +386,10 @@ function renderToEmbedHtml(document, options = {}) {
386
386
  });
387
387
  }
388
388
 
389
+ function svgDataUrl(svg) {
390
+ return "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg);
391
+ }
392
+
389
393
  function canvasToBlob(canvas, type, quality) {
390
394
  return new Promise((resolve, reject) => {
391
395
  canvas.toBlob((blob) => {
@@ -431,17 +435,9 @@ function renderToEmbedHtml(document, options = {}) {
431
435
  }
432
436
 
433
437
  async function loadMp4Muxer() {
434
- if (!mp4MuxerModulePromise) {
435
- const blob = new Blob([mp4MuxerSource], { type: "text/javascript;charset=utf-8" });
436
- const url = URL.createObjectURL(blob);
437
- mp4MuxerModulePromise = import(url)
438
- .catch((error) => {
439
- mp4MuxerModulePromise = null;
440
- throw error;
441
- })
442
- .finally(() => URL.revokeObjectURL(url));
443
- }
444
- return mp4MuxerModulePromise;
438
+ const module = globalThis.__SKETCHMARK_MP4_MUXER__;
439
+ if (module && module.Muxer && module.ArrayBufferTarget) return module;
440
+ throw new Error("MP4 runtime could not be initialized in this host.");
445
441
  }
446
442
 
447
443
  async function rasterBlob(format) {
@@ -686,3 +682,17 @@ function serializeForScript(value) {
686
682
  .replace(/\u2028/g, "\\u2028")
687
683
  .replace(/\u2029/g, "\\u2029");
688
684
  }
685
+ function inlineMp4MuxerRuntime(source) {
686
+ const withoutExportBlock = source.replace(/\s*export\s*\{[\s\S]*?\}\s*;?\s*$/, "");
687
+ const runtime = `${withoutExportBlock}
688
+ globalThis.__SKETCHMARK_MP4_MUXER__ = {
689
+ ArrayBufferTarget,
690
+ FileSystemWritableFileStreamTarget,
691
+ Muxer,
692
+ StreamTarget
693
+ };`;
694
+ return escapeInlineScript(runtime);
695
+ }
696
+ function escapeInlineScript(value) {
697
+ return value.replace(/<\/script/gi, "<\\/script").replace(/<!--/g, "<\\!--");
698
+ }
@@ -0,0 +1,6 @@
1
+ export * from "./svg";
2
+ export * from "./html";
3
+ export * from "./embed";
4
+ export { renderToSvg as svg, renderResolvedSvg as resolvedSvg } from "./svg";
5
+ export { renderToHtml as html } from "./html";
6
+ export { renderToEmbedHtml as embedHtml } from "./embed";
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.embedHtml = exports.html = exports.resolvedSvg = exports.svg = void 0;
18
+ __exportStar(require("./svg"), exports);
19
+ __exportStar(require("./html"), exports);
20
+ __exportStar(require("./embed"), exports);
21
+ var svg_1 = require("./svg");
22
+ Object.defineProperty(exports, "svg", { enumerable: true, get: function () { return svg_1.renderToSvg; } });
23
+ Object.defineProperty(exports, "resolvedSvg", { enumerable: true, get: function () { return svg_1.renderResolvedSvg; } });
24
+ var html_1 = require("./html");
25
+ Object.defineProperty(exports, "html", { enumerable: true, get: function () { return html_1.renderToHtml; } });
26
+ var embed_1 = require("./embed");
27
+ Object.defineProperty(exports, "embedHtml", { enumerable: true, get: function () { return embed_1.renderToEmbedHtml; } });
package/dist/tests/run.js CHANGED
@@ -137,7 +137,9 @@ test("renders a self-contained interactive embed HTML shell", () => {
137
137
  assert(html.includes('data-export-format="svg"'), "should include export controls");
138
138
  assert(html.includes('data-export-format="mp4"'), "should include mp4 export");
139
139
  assert(html.includes("__SKETCHMARK_EMBED__"), "should expose a runtime controller");
140
- assert(html.includes("loadMp4Muxer"), "should inline mp4 export runtime");
140
+ assert(html.includes("__SKETCHMARK_MP4_MUXER__"), "should inline the mp4 muxer runtime");
141
+ assert(!html.includes("import(url)"), "should avoid blob-based dynamic module imports");
142
+ assert(html.includes("data:image/svg+xml;charset=utf-8,"), "should use data URLs for SVG rasterization inside embed hosts");
141
143
  assert(html.includes("sketchmark-rendered"), "should notify host frames when ready");
142
144
  });
143
145
  test("resolves element-local timeline tracks", () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sketchmark",
3
- "version": "2.1.9",
3
+ "version": "2.2.0",
4
4
  "description": "Render kernel for Sketchmark visual documents.",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -30,11 +30,21 @@
30
30
  "require": "./dist/src/edit.js",
31
31
  "default": "./dist/src/edit.js"
32
32
  },
33
+ "./render": {
34
+ "types": "./dist/src/render/index.d.ts",
35
+ "require": "./dist/src/render/index.js",
36
+ "default": "./dist/src/render/index.js"
37
+ },
33
38
  "./editor": {
34
39
  "types": "./bin/editor-ui.d.ts",
35
40
  "require": "./bin/editor-ui.cjs",
36
41
  "default": "./bin/editor-ui.cjs"
37
42
  },
43
+ "./preview": {
44
+ "types": "./bin/preview-ui.d.ts",
45
+ "require": "./bin/preview-ui.cjs",
46
+ "default": "./bin/preview-ui.cjs"
47
+ },
38
48
  "./schema": {
39
49
  "default": "./schema/visual.schema.json"
40
50
  }
@@ -52,6 +62,7 @@
52
62
  "files": [
53
63
  "bin",
54
64
  "dist",
65
+ "skills",
55
66
  "schema",
56
67
  "README.md"
57
68
  ],