@weasel-js/labkit 1.7.0 → 1.7.2
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/README.md +3 -3
- package/dist/_dts/{CanvasStackContext-D2jnIwfk.d.ts → CanvasStackContext-Cjy6I-Iv.d.ts} +4 -1
- package/dist/_dts/{Stage-CCWfQQWM.d.ts → Stage-D6t7o0pF.d.ts} +3 -2
- package/dist/_dts/{index-CsYqUHD3.d.ts → index-BTmaRy6a.d.ts} +10 -6
- package/dist/_dts/{types-CSm9jgol.d.ts → index-DCMA4Fy1.d.ts} +59 -113
- package/dist/_dts/{types-CRPSGFAp.d.ts → types-BUBSIZuV.d.ts} +8 -7
- package/dist/_dts/{useTrialState-CTZPgeZ7.d.ts → useTrialState-Bh8bzFgE.d.ts} +1 -1
- package/dist/canvas/index.d.ts +8 -6
- package/dist/canvas/index.js +6 -6
- package/dist/chrome/index.d.ts +7 -5
- package/dist/chrome/index.js +10 -9
- package/dist/chunk-2ES4W47N.js +8 -0
- package/dist/chunk-2ES4W47N.js.map +1 -0
- package/dist/{chunk-WPLAANH4.js → chunk-2N7UBSS2.js} +12 -12
- package/dist/chunk-2N7UBSS2.js.map +1 -0
- package/dist/{chunk-275JRRVD.js → chunk-E23Q6A3Y.js} +232 -37
- package/dist/chunk-E23Q6A3Y.js.map +1 -0
- package/dist/{chunk-GOZLNM4L.js → chunk-E6NARGU7.js} +5 -5
- package/dist/{chunk-GOZLNM4L.js.map → chunk-E6NARGU7.js.map} +1 -1
- package/dist/{chunk-IJJUK4FU.js → chunk-EESJUSYR.js} +5 -6
- package/dist/chunk-EESJUSYR.js.map +1 -0
- package/dist/{chunk-HXXTULDN.js → chunk-EFXRM6XQ.js} +8 -11
- package/dist/chunk-EFXRM6XQ.js.map +1 -0
- package/dist/chunk-F4ACIK7Z.js +210 -0
- package/dist/chunk-F4ACIK7Z.js.map +1 -0
- package/dist/{chunk-AWQG7FCC.js → chunk-FG3EXZDV.js} +3 -3
- package/dist/{chunk-AWQG7FCC.js.map → chunk-FG3EXZDV.js.map} +1 -1
- package/dist/{chunk-YT75VYRD.js → chunk-IBVRMHW5.js} +5 -5
- package/dist/{chunk-YT75VYRD.js.map → chunk-IBVRMHW5.js.map} +1 -1
- package/dist/{chunk-RWNDDKOH.js → chunk-PMLZP7RT.js} +18 -15
- package/dist/chunk-PMLZP7RT.js.map +1 -0
- package/dist/{chunk-Y23G2VZL.js → chunk-READTDQX.js} +2 -2
- package/dist/chunk-READTDQX.js.map +1 -0
- package/dist/{chunk-I5DUQ5HM.js → chunk-RODIY7HI.js} +75 -72
- package/dist/chunk-RODIY7HI.js.map +1 -0
- package/dist/{chunk-JVBYV6TL.js → chunk-ROGJWDQA.js} +3 -3
- package/dist/{chunk-JVBYV6TL.js.map → chunk-ROGJWDQA.js.map} +1 -1
- package/dist/{chunk-ZIFPHIWZ.js → chunk-T6DLGEJB.js} +12 -14
- package/dist/chunk-T6DLGEJB.js.map +1 -0
- package/dist/chunk-U6UQVGFP.js +15583 -0
- package/dist/chunk-U6UQVGFP.js.map +1 -0
- package/dist/{chunk-24W5VEJW.js → chunk-ULYYNWGP.js} +2 -2
- package/dist/{chunk-24W5VEJW.js.map → chunk-ULYYNWGP.js.map} +1 -1
- package/dist/{chunk-UNAZSLWE.js → chunk-VYVGVBGY.js} +17 -20
- package/dist/chunk-VYVGVBGY.js.map +1 -0
- package/dist/chunk-WFALF2X2.js +302 -0
- package/dist/chunk-WFALF2X2.js.map +1 -0
- package/dist/{chunk-KMJ7RWD3.js → chunk-WLMDTI2Q.js} +3 -3
- package/dist/{chunk-KMJ7RWD3.js.map → chunk-WLMDTI2Q.js.map} +1 -1
- package/dist/{chunk-T5IBSPAM.js → chunk-WWJDPNZZ.js} +43 -33
- package/dist/chunk-WWJDPNZZ.js.map +1 -0
- package/dist/{chunk-J7OWWTCW.js → chunk-XE5HJOPL.js} +5 -6
- package/dist/chunk-XE5HJOPL.js.map +1 -0
- package/dist/{chunk-7BO7HNGF.js → chunk-XRX5S5NT.js} +8 -61
- package/dist/chunk-XRX5S5NT.js.map +1 -0
- package/dist/chunk-XVUKDSYV.js +38 -0
- package/dist/chunk-XVUKDSYV.js.map +1 -0
- package/dist/{chunk-FMK7UQ6V.js → chunk-XZDCEMEL.js} +64 -47
- package/dist/chunk-XZDCEMEL.js.map +1 -0
- package/dist/{chunk-FZ7YFQN7.js → chunk-YCFKW5RX.js} +3 -3
- package/dist/chunk-YCFKW5RX.js.map +1 -0
- package/dist/{chunk-CQLQPQ4P.js → chunk-ZQIHJXP4.js} +2 -2
- package/dist/chunk-ZQIHJXP4.js.map +1 -0
- package/dist/config/index.d.ts +18 -10
- package/dist/config/index.js +4 -4
- package/dist/controls/index.d.ts +58 -9
- package/dist/controls/index.js +7 -5
- package/dist/dragdrop/index.d.ts +23 -3
- package/dist/dragdrop/index.js +4 -3
- package/dist/fonts/oswald-tabular-digits.woff2 +0 -0
- package/dist/index.d.ts +61 -715
- package/dist/index.js +456 -432
- package/dist/index.js.map +1 -1
- package/dist/job/index.d.ts +8 -0
- package/dist/job/index.js +1 -1
- package/dist/layers/index.d.ts +6 -5
- package/dist/layers/index.js +3 -2
- package/dist/loupe/index.d.ts +100 -30
- package/dist/loupe/index.js +585 -6
- package/dist/loupe/index.js.map +1 -1
- package/dist/overview/index.d.ts +4 -2
- package/dist/overview/index.js +15 -14
- package/dist/overview/index.js.map +1 -1
- package/dist/passthrough/weasel-canvas.d.ts +2 -0
- package/dist/passthrough/weasel-ui.d.ts +2 -2871
- package/dist/passthrough/weasel-ui.js +3 -2
- package/dist/primitives/index.d.ts +213 -3
- package/dist/primitives/index.js +8 -7
- package/dist/state/index.d.ts +7 -5
- package/dist/state/index.js +6 -6
- package/dist/styles.css +284 -51
- package/dist/surface/index.d.ts +10 -2
- package/dist/surface/index.js +1 -1
- package/dist/undo/index.d.ts +5 -3
- package/package.json +11 -11
- package/src/annotations/AnnotationOverlay.abandon.test.tsx +143 -0
- package/src/annotations/AnnotationOverlay.tsx +50 -31
- package/src/annotations/Annotations.overlay.test.tsx +31 -0
- package/src/annotations/capture.browser.test.ts +47 -0
- package/src/annotations/capture.ts +14 -7
- package/src/annotations/drawOne.ts +2 -2
- package/src/annotations/frac.test.ts +44 -1
- package/src/annotations/frac.ts +46 -18
- package/src/annotations/index.ts +1 -0
- package/src/annotations/paint.test.ts +74 -33
- package/src/annotations/paint.ts +70 -32
- package/src/annotations/store.test.ts +212 -2
- package/src/annotations/store.ts +130 -27
- package/src/annotations/svgNodes.test.ts +22 -10
- package/src/annotations/svgNodes.ts +3 -3
- package/src/annotations/types.ts +29 -10
- package/src/canvas/CameraInput.test.tsx +30 -0
- package/src/canvas/CameraInput.tsx +16 -15
- package/src/canvas/CanvasStack.tsx +5 -5
- package/src/canvas/CanvasStackContext.ts +4 -1
- package/src/canvas/Stage.test.tsx +34 -25
- package/src/canvas/Stage.tsx +3 -3
- package/src/canvas/cameraRegistry.ts +1 -0
- package/src/canvas/worldSpec.ts +3 -1
- package/src/chrome/builtins.test.ts +7 -6
- package/src/chrome/builtins.tsx +5 -1
- package/src/chrome/index.ts +1 -1
- package/src/chrome/labRegions.test.tsx +37 -26
- package/src/chrome/merge.test.ts +5 -0
- package/src/chrome/merge.ts +4 -2
- package/src/chrome/regions/PaletteRegion.test.tsx +4 -5
- package/src/chrome/regions/PaletteRegion.tsx +3 -4
- package/src/chrome/regions/ViewportRegion.browser.test.less +6 -0
- package/src/chrome/regions/ViewportRegion.browser.test.tsx +38 -0
- package/src/chrome/regions/ViewportRegion.less +6 -0
- package/src/chrome/regions/ViewportRegion.tsx +10 -4
- package/src/chrome/types.ts +4 -2
- package/src/config/auto.ts +1 -0
- package/src/config/builder.ts +6 -0
- package/src/config/types.ts +2 -1
- package/src/controls/ControlMatrix.less +245 -0
- package/src/controls/ControlMatrix.stories.less +13 -0
- package/src/controls/ControlMatrix.stories.tsx +135 -0
- package/src/controls/ControlMatrix.test.tsx +206 -0
- package/src/controls/ControlMatrix.tsx +446 -0
- package/src/controls/ControlPanel.test.tsx +37 -3
- package/src/controls/ControlPanel.tsx +16 -5
- package/src/controls/index.ts +6 -0
- package/src/dragdrop/DragDropRuntime.tsx +22 -13
- package/src/dragdrop/DragGhost.tsx +3 -0
- package/src/dragdrop/Palette.tsx +2 -0
- package/src/dragdrop/dragDrop.test.tsx +34 -33
- package/src/index.test.ts +5 -0
- package/src/index.ts +7 -1
- package/src/instrument/types.ts +0 -6
- package/src/job/useJob.ts +14 -9
- package/src/lab/Lab.chrome.test.tsx +15 -10
- package/src/lab/Lab.nebula.test.tsx +5 -5
- package/src/lab/Lab.surface.test.tsx +30 -21
- package/src/lab/Lab.test.tsx +75 -74
- package/src/lab/Lab.tsx +5 -1
- package/src/lab/Lab.undock.test.tsx +15 -10
- package/src/lab/LabHeader.test.tsx +15 -14
- package/src/lab/LabPalette.test.tsx +12 -7
- package/src/lab/LabShell.less +1 -1
- package/src/lab/LabSwitcher.browser.test.tsx +27 -0
- package/src/lab/LabSwitcher.less +2 -0
- package/src/lab/LabZoom.test.tsx +55 -44
- package/src/lab/LabZoom.tsx +4 -4
- package/src/lab/Workspace.surface.test.tsx +16 -13
- package/src/lab/Workspace.test.tsx +32 -27
- package/src/lab/Workspace.tsx +48 -52
- package/src/loupe/AGENTS.md +28 -15
- package/src/loupe/CanvasLoupe.tsx +2 -3
- package/src/loupe/DomLoupe.tsx +1 -7
- package/src/loupe/Loupe.less +16 -0
- package/src/loupe/TrialLoupe.tsx +120 -57
- package/src/loupe/index.ts +1 -6
- package/src/loupe/types.test.ts +3 -3
- package/src/loupe/types.ts +24 -27
- package/src/loupe/useLoupe.test.tsx +29 -4
- package/src/loupe/useLoupe.ts +20 -17
- package/src/overview/OverviewMarks.test.tsx +9 -8
- package/src/overview/OverviewMarks.tsx +12 -4
- package/src/overview/TrialOverview.test.tsx +18 -17
- package/src/overview/TrialOverview.tsx +3 -3
- package/src/passthrough/weasel-ui.test.ts +1 -1
- package/src/passthrough/weasel-ui.ts +1 -1
- package/src/primitives/FloatingPanel.tsx +7 -3
- package/src/primitives/FpsMeter.less +1 -2
- package/src/primitives/JobProgress.less +1 -1
- package/src/primitives/Readout.test.tsx +2 -2
- package/src/primitives/ScaleIndicator.less +1 -1
- package/src/primitives/Split.tsx +69 -41
- package/src/primitives/StatusBar.less +1 -1
- package/src/primitives/Toolbar.tsx +3 -3
- package/src/primitives/ZoomControl.less +1 -2
- package/src/specimen/Specimen.less +1 -0
- package/src/specimen/Specimen.tsx +0 -1
- package/src/state/undock.ts +3 -0
- package/src/state/useOpenOnce.ts +20 -16
- package/src/state/view.ts +1 -0
- package/src/styles.less +3 -0
- package/src/surface/index.ts +1 -1
- package/src/surface/useTiledSurface.test.tsx +14 -0
- package/src/surface/useTiledSurface.ts +11 -3
- package/src/trial/Trial.annotations.persist.test.tsx +20 -9
- package/src/trial/Trial.annotations.test.tsx +105 -27
- package/src/trial/Trial.canvas.test.tsx +21 -17
- package/src/trial/Trial.config.test.tsx +34 -27
- package/src/trial/Trial.less +0 -16
- package/src/trial/Trial.loupe.test.tsx +51 -25
- package/src/trial/Trial.targets.test.tsx +9 -8
- package/src/trial/Trial.test.tsx +51 -46
- package/src/trial/Trial.trialId.test.tsx +7 -6
- package/src/trial/Trial.tsx +74 -62
- package/src/trial/TrialChrome.tsx +6 -3
- package/src/trial/index.ts +2 -0
- package/src/trial/loupeSwitch.ts +15 -0
- package/dist/_dts/LayerList.d-DiuEArKq.d.ts +0 -83
- package/dist/_dts/PrefsRow.d-TOZ7BgD9.d.ts +0 -79
- package/dist/_dts/PropertyPanel.d-D-1paCbE.d.ts +0 -141
- package/dist/_dts/Select.d-Bensr_MT.d.ts +0 -579
- package/dist/_dts/index-B2Yj5aA0.d.ts +0 -274
- package/dist/chunk-275JRRVD.js.map +0 -1
- package/dist/chunk-4LJSC7MB.js +0 -143
- package/dist/chunk-4LJSC7MB.js.map +0 -1
- package/dist/chunk-7BO7HNGF.js.map +0 -1
- package/dist/chunk-CQLQPQ4P.js.map +0 -1
- package/dist/chunk-FMK7UQ6V.js.map +0 -1
- package/dist/chunk-FZ7YFQN7.js.map +0 -1
- package/dist/chunk-HXXTULDN.js.map +0 -1
- package/dist/chunk-I5DUQ5HM.js.map +0 -1
- package/dist/chunk-IJJUK4FU.js.map +0 -1
- package/dist/chunk-J7OWWTCW.js.map +0 -1
- package/dist/chunk-M7HP3FTK.js +0 -549
- package/dist/chunk-M7HP3FTK.js.map +0 -1
- package/dist/chunk-MIM5R4ZT.js +0 -14972
- package/dist/chunk-MIM5R4ZT.js.map +0 -1
- package/dist/chunk-RWNDDKOH.js.map +0 -1
- package/dist/chunk-T5IBSPAM.js.map +0 -1
- package/dist/chunk-UNAZSLWE.js.map +0 -1
- package/dist/chunk-WPLAANH4.js.map +0 -1
- package/dist/chunk-Y23G2VZL.js.map +0 -1
- package/dist/chunk-ZIFPHIWZ.js.map +0 -1
- package/src/primitives/useRovingTabIndex.test.ts +0 -48
- package/src/primitives/useRovingTabIndex.ts +0 -88
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { screenToWorld } from './chunk-
|
|
2
|
-
import { resolveFrame } from './chunk-
|
|
1
|
+
import { screenToWorld } from './chunk-FG3EXZDV.js';
|
|
2
|
+
import { resolveFrame } from './chunk-ULYYNWGP.js';
|
|
3
|
+
import { boxContainsPoint } from './chunk-XVUKDSYV.js';
|
|
3
4
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
4
5
|
import { createPortal } from 'react-dom';
|
|
5
6
|
import { jsx } from 'react/jsx-runtime';
|
|
6
|
-
import { useVisibleRaf, openPointerSession } from '@weasel-js/core';
|
|
7
|
+
import { useLatest, useVisibleRaf, openPointerSession } from '@weasel-js/core';
|
|
7
8
|
|
|
8
9
|
function DragGhost({ item, screenPos }) {
|
|
9
10
|
const [mounted, setMounted] = useState(false);
|
|
@@ -30,17 +31,15 @@ function useDragDrop({
|
|
|
30
31
|
}) {
|
|
31
32
|
const [drag, setDrag] = useState(null);
|
|
32
33
|
const dragRef = useRef(null);
|
|
33
|
-
dragRef.current = drag;
|
|
34
34
|
const pendingPos = useRef(null);
|
|
35
35
|
const sessionRef = useRef(null);
|
|
36
|
-
const liveRef =
|
|
37
|
-
liveRef.current = { capability, state, config, setState, emit, view, worldSpec };
|
|
36
|
+
const liveRef = useLatest({ capability, state, config, setState, emit, view, worldSpec });
|
|
38
37
|
const isOverCanvas = useCallback(
|
|
39
38
|
(screenPos) => {
|
|
40
39
|
const el = canvasContainerRef.current;
|
|
41
40
|
if (!el) return false;
|
|
42
41
|
const r = el.getBoundingClientRect();
|
|
43
|
-
return
|
|
42
|
+
return boxContainsPoint([r.left, r.top, r.right, r.bottom], screenPos.x, screenPos.y);
|
|
44
43
|
},
|
|
45
44
|
[canvasContainerRef]
|
|
46
45
|
);
|
|
@@ -56,7 +55,7 @@ function useDragDrop({
|
|
|
56
55
|
frame
|
|
57
56
|
);
|
|
58
57
|
},
|
|
59
|
-
[canvasContainerRef]
|
|
58
|
+
[canvasContainerRef, liveRef]
|
|
60
59
|
);
|
|
61
60
|
const frameLoop = useVisibleRaf(() => {
|
|
62
61
|
const screenPos = pendingPos.current;
|
|
@@ -69,7 +68,8 @@ function useDragDrop({
|
|
|
69
68
|
const world = screenToWorldFromContainer(screenPos);
|
|
70
69
|
if (world) feedback = live.capability.onDragOver(world, active.item, live.state, live.config);
|
|
71
70
|
}
|
|
72
|
-
|
|
71
|
+
dragRef.current = { ...active, screenPos, feedback };
|
|
72
|
+
setDrag(dragRef.current);
|
|
73
73
|
});
|
|
74
74
|
const clearDrag = useCallback(() => {
|
|
75
75
|
pendingPos.current = null;
|
|
@@ -113,7 +113,7 @@ function useDragDrop({
|
|
|
113
113
|
onCancel: clearDrag
|
|
114
114
|
});
|
|
115
115
|
},
|
|
116
|
-
[clearDrag, frameLoop, isOverCanvas, screenToWorldFromContainer]
|
|
116
|
+
[clearDrag, frameLoop, isOverCanvas, liveRef, screenToWorldFromContainer]
|
|
117
117
|
);
|
|
118
118
|
useEffect(() => () => sessionRef.current?.cancel(), []);
|
|
119
119
|
return { drag, startDrag };
|
|
@@ -139,5 +139,5 @@ function Palette({ items, onDragStart, className }) {
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
export { DragGhost, DragOverlay, Palette, useDragDrop };
|
|
142
|
-
//# sourceMappingURL=chunk-
|
|
143
|
-
//# sourceMappingURL=chunk-
|
|
142
|
+
//# sourceMappingURL=chunk-2N7UBSS2.js.map
|
|
143
|
+
//# sourceMappingURL=chunk-2N7UBSS2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/dragdrop/DragGhost.tsx","../src/dragdrop/DragDropRuntime.tsx","../src/dragdrop/Palette.tsx"],"names":["useState","useEffect","jsx"],"mappings":"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","file":"chunk-2N7UBSS2.js","sourcesContent":["import { type ReactPortal, useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { PaletteItem, Point } from '../instrument/types';\n\n/** Props for `DragGhost`. `screenPos` is in client pixels. */\nexport interface DragGhostProps {\n item: PaletteItem;\n screenPos: Point;\n}\n\n/** The dragged item's label, portaled to `document.body` just below-right of\n * `screenPos`. Renders nothing until mounted, so it is SSR-safe. */\nexport function DragGhost({ item, screenPos }: DragGhostProps): ReactPortal | null {\n const [mounted, setMounted] = useState(false);\n useEffect(() => setMounted(true), []);\n if (!mounted || typeof document === 'undefined') return null;\n const style = {\n left: `${screenPos.x + 12}px`,\n top: `${screenPos.y + 12}px`,\n };\n return createPortal(\n <div className=\"lk-drag-ghost\" style={style}>\n <span className=\"lk-drag-ghost__label\">{item.label}</span>\n </div>,\n document.body,\n );\n}\n","import { openPointerSession, type PointerSession, useLatest, useVisibleRaf } from '@weasel-js/core';\nimport { boxContainsPoint } from '@weasel-js/geom';\nimport {\n type PointerEvent as ReactPointerEvent,\n type RefObject,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { screenToWorld } from '../canvas/canvasCoords';\nimport { resolveFrame, type WorldSpec } from '../canvas/worldSpec';\nimport type {\n DragDropCapability,\n DragFeedback,\n PaletteItem,\n Point,\n ViewTransform,\n} from '../instrument/types';\nimport { DragGhost } from './DragGhost';\n\n/** A palette drag in progress. `screenPos` is in client pixels; `feedback` is\n * the last `onDragOver` answer — `null` off the canvas or without one. */\nexport interface DragState {\n item: PaletteItem;\n screenPos: Point;\n feedback: DragFeedback | null;\n}\n\n/** Inputs to `useDragDrop`: the capability, the element that counts as the\n * drop target, and the trial state a drop rewrites. */\nexport interface UseDragDropArgs<TS, TC> {\n capability: DragDropCapability<TS, TC>;\n canvasContainerRef: RefObject<HTMLElement | null>;\n view: ViewTransform;\n /** The instrument's coordinate system, resolved against the container each\n * time a screen point is converted — the container is what knows its size. */\n worldSpec?: WorldSpec;\n state: TS;\n config: TC;\n setState: (next: TS | ((prev: TS) => TS)) => void;\n emit: (event: string) => void;\n}\n\n/** The live drag, and the handler a palette item calls on pointerdown. */\nexport interface UseDragDropResult {\n drag: DragState | null;\n startDrag: (item: PaletteItem, e: ReactPointerEvent) => void;\n}\n\n/**\n * Run palette-to-canvas drags for a `DragDropCapability`. Releasing over the\n * container converts the pointer to world coordinates, applies `onDrop`'s\n * state and emits `'canvas.itemAdded'`; releasing anywhere else, or a canceled\n * gesture, drops nothing. `onDragOver` is probed at most once per frame.\n */\nexport function useDragDrop<TS, TC>({\n capability,\n canvasContainerRef,\n view,\n state,\n config,\n setState,\n emit,\n worldSpec,\n}: UseDragDropArgs<TS, TC>): UseDragDropResult {\n const [drag, setDrag] = useState<DragState | null>(null);\n // Owned by the handlers below, which write it alongside every `setDrag`.\n const dragRef = useRef<DragState | null>(null);\n /** The move the next frame will resolve. Doubles as the throttle's flag:\n * non-null means a frame is already queued. */\n const pendingPos = useRef<Point | null>(null);\n const sessionRef = useRef<PointerSession | null>(null);\n\n /** A session keeps the closure it was opened with, so everything the drop\n * reads has to come from here rather than from that closure. */\n const liveRef = useLatest({ capability, state, config, setState, emit, view, worldSpec });\n\n const isOverCanvas = useCallback(\n (screenPos: Point): boolean => {\n const el = canvasContainerRef.current;\n if (!el) return false;\n const r = el.getBoundingClientRect();\n return boxContainsPoint([r.left, r.top, r.right, r.bottom], screenPos.x, screenPos.y);\n },\n [canvasContainerRef],\n );\n\n const screenToWorldFromContainer = useCallback(\n (screenPos: Point): Point | null => {\n const el = canvasContainerRef.current;\n if (!el) return null;\n const r = el.getBoundingClientRect();\n const frame = resolveFrame(liveRef.current.worldSpec, { width: r.width, height: r.height });\n return screenToWorld(\n { x: screenPos.x - r.left, y: screenPos.y - r.top },\n liveRef.current.view,\n frame,\n );\n },\n [canvasContainerRef, liveRef],\n );\n\n const frameLoop = useVisibleRaf(() => {\n const screenPos = pendingPos.current;\n pendingPos.current = null;\n const active = dragRef.current;\n if (!active || !screenPos) return;\n const live = liveRef.current;\n let feedback: DragFeedback | null = null;\n if (live.capability.onDragOver && isOverCanvas(screenPos)) {\n const world = screenToWorldFromContainer(screenPos);\n if (world) feedback = live.capability.onDragOver(world, active.item, live.state, live.config);\n }\n dragRef.current = { ...active, screenPos, feedback };\n setDrag(dragRef.current);\n });\n\n const clearDrag = useCallback(() => {\n pendingPos.current = null;\n frameLoop.cancel();\n sessionRef.current = null;\n dragRef.current = null;\n setDrag(null);\n }, [frameLoop]);\n\n const startDrag = useCallback(\n (item: PaletteItem, e: ReactPointerEvent) => {\n if (sessionRef.current) return;\n const next: DragState = { item, screenPos: { x: e.clientX, y: e.clientY }, feedback: null };\n dragRef.current = next;\n setDrag(next);\n sessionRef.current = openPointerSession(e.currentTarget, e, {\n onMove: (ev) => {\n const screenPos = { x: ev.clientX, y: ev.clientY };\n const current = dragRef.current;\n if (!current) return;\n if (pendingPos.current !== null) {\n // A frame is already queued: keep the ghost under the cursor and\n // let that frame probe the drop target from the newest position.\n pendingPos.current = screenPos;\n dragRef.current = { ...current, screenPos };\n setDrag(dragRef.current);\n return;\n }\n pendingPos.current = screenPos;\n frameLoop.request();\n },\n onEnd: (ev) => {\n const screenPos = { x: ev.clientX, y: ev.clientY };\n const active = dragRef.current;\n clearDrag();\n if (!active || !isOverCanvas(screenPos)) return;\n const world = screenToWorldFromContainer(screenPos);\n if (!world) return;\n const live = liveRef.current;\n live.setState(live.capability.onDrop(world, active.item, live.state, live.config));\n live.emit('canvas.itemAdded');\n },\n // An interrupted gesture never named a destination, so it drops nothing.\n onCancel: clearDrag,\n });\n },\n [clearDrag, frameLoop, isOverCanvas, liveRef, screenToWorldFromContainer],\n );\n\n useEffect(() => () => sessionRef.current?.cancel(), []);\n\n return { drag, startDrag };\n}\n\n/** Props for `DragOverlay`. */\nexport interface DragOverlayProps {\n drag: DragState | null;\n}\n\n/** The ghost for `drag`, or nothing when no drag is live. */\nexport function DragOverlay({ drag }: DragOverlayProps) {\n if (!drag) return null;\n return <DragGhost item={drag.item} screenPos={drag.screenPos} />;\n}\n","import type { PointerEvent as ReactPointerEvent } from 'react';\nimport type { PaletteItem } from '../instrument/types';\n\n/** Props for `Palette`. `onDragStart` is usually `useDragDrop`'s `startDrag`. */\nexport interface PaletteProps {\n items: PaletteItem[];\n onDragStart: (item: PaletteItem, e: ReactPointerEvent) => void;\n className?: string;\n}\n\n/** One button per item, each starting a drag on pointerdown. */\nexport function Palette({ items, onDragStart, className }: PaletteProps) {\n return (\n <div className={className ? `lk-palette ${className}` : 'lk-palette'}>\n {items.map((item) => (\n <button\n type=\"button\"\n key={item.id}\n className=\"lk-palette__item\"\n onPointerDown={(e) => {\n e.preventDefault();\n onDragStart(item, e);\n }}\n >\n <span className=\"lk-palette__label\">{item.label}</span>\n </button>\n ))}\n </div>\n );\n}\n"]}
|
|
@@ -1,22 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { identity, multiply } from './chunk-XVUKDSYV.js';
|
|
2
|
+
import { resolveScreenLength, scriptMetricsFor, boundsOfPath, getMarker, PATH_M, PATH_L, PATH_C, PATH_Q, PATH_Z, resolveAlign, resolveRunFace, resolveTextStyle, parseColor, rgbaToHex, getPaintKind, resolveMarkerSize } from '@weasel-js/core';
|
|
2
3
|
import { tileGeometry } from '@weasel-js/core/patterns-builtin';
|
|
3
4
|
|
|
4
|
-
// ../svg/dist/index.js
|
|
5
|
-
|
|
6
|
-
// ../geom/dist/index.js
|
|
7
|
-
function identity() {
|
|
8
|
-
return [1, 0, 0, 1, 0, 0];
|
|
9
|
-
}
|
|
10
|
-
function multiply(m, n) {
|
|
11
|
-
return [
|
|
12
|
-
m[0] * n[0] + m[2] * n[1],
|
|
13
|
-
m[1] * n[0] + m[3] * n[1],
|
|
14
|
-
m[0] * n[2] + m[2] * n[3],
|
|
15
|
-
m[1] * n[2] + m[3] * n[3],
|
|
16
|
-
m[0] * n[4] + m[2] * n[5] + m[4],
|
|
17
|
-
m[1] * n[4] + m[3] * n[5] + m[5]
|
|
18
|
-
];
|
|
19
|
-
}
|
|
20
5
|
var IDENTITY_MATRIX = identity();
|
|
21
6
|
function isIdentity(m, eps = 1e-9) {
|
|
22
7
|
return Math.abs(m[0] - 1) < eps && Math.abs(m[1]) < eps && Math.abs(m[2]) < eps && Math.abs(m[3] - 1) < eps && Math.abs(m[4]) < eps && Math.abs(m[5]) < eps;
|
|
@@ -31,10 +16,201 @@ function trimNumber(n) {
|
|
|
31
16
|
if (Number.isInteger(r)) return String(r);
|
|
32
17
|
return String(r);
|
|
33
18
|
}
|
|
34
|
-
function anchorOffset(style,
|
|
19
|
+
function anchorOffset(style, width2) {
|
|
35
20
|
const edge = resolveAlign(style?.align ?? "left", style?.direction ?? "ltr");
|
|
36
|
-
return edge === "center" ?
|
|
21
|
+
return edge === "center" ? width2 / 2 : edge === "right" ? width2 : 0;
|
|
22
|
+
}
|
|
23
|
+
function parsePaintAttr(raw) {
|
|
24
|
+
if (raw == null) return null;
|
|
25
|
+
const s = raw.trim();
|
|
26
|
+
if (s === "") return null;
|
|
27
|
+
if (s === "none") return { kind: "none" };
|
|
28
|
+
if (s.toLowerCase() === "currentcolor") {
|
|
29
|
+
return { kind: "solid", color: "#000000", alpha: 1 };
|
|
30
|
+
}
|
|
31
|
+
const urlMatch = /^url\(\s*#([^)\s]+)\s*\)(.*)$/.exec(s);
|
|
32
|
+
if (urlMatch) {
|
|
33
|
+
const out = { kind: "ref", id: urlMatch[1] };
|
|
34
|
+
const rest = urlMatch[2].trim();
|
|
35
|
+
if (rest !== "" && rest !== "none") {
|
|
36
|
+
const fallback = parsePaintAttr(rest);
|
|
37
|
+
if (fallback?.kind === "solid") {
|
|
38
|
+
out.fallback = { color: fallback.color, alpha: fallback.alpha };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const [r, g, b, a] = parseColor(s);
|
|
45
|
+
return { kind: "solid", color: rgbaToHex([r, g, b]), alpha: a };
|
|
46
|
+
} catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
var TEXT_TRANSFORMS = /* @__PURE__ */ new Set(["none", "uppercase", "lowercase", "capitalize"]);
|
|
51
|
+
var DIMENSION = /^([+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?)([a-z%]*)$/i;
|
|
52
|
+
function dimension(v) {
|
|
53
|
+
const m = DIMENSION.exec(v);
|
|
54
|
+
return m ? { n: Number(m[1]), unit: m[2].toLowerCase() } : void 0;
|
|
55
|
+
}
|
|
56
|
+
var clamp01 = (n) => n < 0 ? 0 : n > 1 ? 1 : n;
|
|
57
|
+
var length = (native, coercedAs) => (v, warn, prop) => {
|
|
58
|
+
const d = dimension(v);
|
|
59
|
+
if (!d) return void 0;
|
|
60
|
+
if (d.unit && !native.includes(d.unit)) {
|
|
61
|
+
warn(`${prop} "${v}" uses unit "${d.unit}", which is not converted; treated as ${d.n} ${coercedAs}`);
|
|
62
|
+
}
|
|
63
|
+
return d.n;
|
|
64
|
+
};
|
|
65
|
+
var worldLength = length(["px"], "world units");
|
|
66
|
+
var keyword2 = (...words) => (v) => words.includes(v) ? v : void 0;
|
|
67
|
+
var isCurrentColor = (v) => v.toLowerCase() === "currentcolor";
|
|
68
|
+
function readPaint(v) {
|
|
69
|
+
if (v === "context-fill") return { kind: "context", of: "fill" };
|
|
70
|
+
if (v === "context-stroke") return { kind: "context", of: "stroke" };
|
|
71
|
+
return parsePaintAttr(v) ?? void 0;
|
|
72
|
+
}
|
|
73
|
+
function readRatio(v) {
|
|
74
|
+
const d = dimension(v);
|
|
75
|
+
if (!d || d.unit !== "" && d.unit !== "%") return void 0;
|
|
76
|
+
return clamp01(d.unit === "%" ? d.n / 100 : d.n);
|
|
77
|
+
}
|
|
78
|
+
function readSolidColor(v, warn, prop) {
|
|
79
|
+
const parsed = parsePaintAttr(v);
|
|
80
|
+
if (parsed?.kind !== "solid") return void 0;
|
|
81
|
+
if (isCurrentColor(v)) warn(`${prop}="${v}" is read as black; it is not resolved against color`);
|
|
82
|
+
return parsed;
|
|
83
|
+
}
|
|
84
|
+
function readMarkerRef(v) {
|
|
85
|
+
if (v === "none") return null;
|
|
86
|
+
return /^url\(\s*#([^)\s]+)\s*\)$/.exec(v)?.[1];
|
|
87
|
+
}
|
|
88
|
+
function readLinecap(v, warn) {
|
|
89
|
+
const cap = keyword2("butt", "round", "square")(v);
|
|
90
|
+
if (!cap) warn(`unsupported stroke-linecap: ${v}`);
|
|
91
|
+
return cap;
|
|
92
|
+
}
|
|
93
|
+
function readLinejoin(v, warn) {
|
|
94
|
+
const join = keyword2("miter", "round", "bevel")(v);
|
|
95
|
+
if (join) return join;
|
|
96
|
+
if (v === "arcs" || v === "miter-clip") {
|
|
97
|
+
warn(`stroke-linejoin "${v}" not supported; falling back to miter`);
|
|
98
|
+
return "miter";
|
|
99
|
+
}
|
|
100
|
+
warn(`unsupported stroke-linejoin: ${v}`);
|
|
101
|
+
return void 0;
|
|
102
|
+
}
|
|
103
|
+
function readDashArray(v, warn) {
|
|
104
|
+
if (v === "none" || v === "") return null;
|
|
105
|
+
const nums = [];
|
|
106
|
+
for (const t of v.split(/[\s,]+/).filter(Boolean)) {
|
|
107
|
+
const d = dimension(t);
|
|
108
|
+
if (!d || d.unit !== "" && d.unit !== "px" || d.n < 0) {
|
|
109
|
+
warn(`unrecognized stroke-dasharray: ${v}`);
|
|
110
|
+
return void 0;
|
|
111
|
+
}
|
|
112
|
+
nums.push(d.n);
|
|
113
|
+
}
|
|
114
|
+
return nums.length % 2 === 1 ? [...nums, ...nums] : nums;
|
|
115
|
+
}
|
|
116
|
+
function readMiterLimit(v, warn) {
|
|
117
|
+
const d = dimension(v);
|
|
118
|
+
if (d && d.unit === "" && d.n >= 1) return d.n;
|
|
119
|
+
warn(`unrecognized stroke-miterlimit: ${v}`);
|
|
120
|
+
return void 0;
|
|
121
|
+
}
|
|
122
|
+
function readColor(v) {
|
|
123
|
+
return isCurrentColor(v) || parsePaintAttr(v)?.kind === "solid" ? v : void 0;
|
|
37
124
|
}
|
|
125
|
+
function readFontSize(v, warn, prop) {
|
|
126
|
+
const d = dimension(v);
|
|
127
|
+
if (d?.unit === "%") return { fontScale: d.n / 100 };
|
|
128
|
+
const n = worldLength(v, warn, prop);
|
|
129
|
+
return n == null ? void 0 : { fontSize: n };
|
|
130
|
+
}
|
|
131
|
+
function readFontWeight(v) {
|
|
132
|
+
if (v === "normal" || v === "bold" || v === "bolder") return v;
|
|
133
|
+
const d = dimension(v);
|
|
134
|
+
return d && d.unit === "" && d.n >= 1 && d.n <= 1e3 ? d.n : void 0;
|
|
135
|
+
}
|
|
136
|
+
function readFontStyle(v, warn) {
|
|
137
|
+
if (v === "normal" || v === "italic") return v;
|
|
138
|
+
if (v === "oblique") {
|
|
139
|
+
warn('font-style "oblique" is read as italic');
|
|
140
|
+
return "italic";
|
|
141
|
+
}
|
|
142
|
+
return void 0;
|
|
143
|
+
}
|
|
144
|
+
function readLetterSpacing(v, warn, prop) {
|
|
145
|
+
return v === "normal" ? null : worldLength(v, warn, prop);
|
|
146
|
+
}
|
|
147
|
+
function readDecoration(v, warn) {
|
|
148
|
+
const out = {};
|
|
149
|
+
for (const t of v.toLowerCase().split(/\s+/)) {
|
|
150
|
+
if (t === "underline") out.underline = true;
|
|
151
|
+
else if (t === "line-through") out.strikethrough = true;
|
|
152
|
+
else if (t === "overline") out.overline = true;
|
|
153
|
+
else if (t !== "none" && t !== "blink") warn(`text-decoration "${v}": "${t}" is not modeled; dropped`);
|
|
154
|
+
}
|
|
155
|
+
return out;
|
|
156
|
+
}
|
|
157
|
+
function readFontVariant(v, warn) {
|
|
158
|
+
let out;
|
|
159
|
+
for (const t of v.toLowerCase().split(/\s+/)) {
|
|
160
|
+
if (t === "small-caps" || t === "normal") out = t;
|
|
161
|
+
else if (t) warn(`font-variant "${v}": "${t}" is not modeled; dropped`);
|
|
162
|
+
}
|
|
163
|
+
return out;
|
|
164
|
+
}
|
|
165
|
+
function readTextTransform(v) {
|
|
166
|
+
const t = v.toLowerCase();
|
|
167
|
+
return TEXT_TRANSFORMS.has(t) ? t : void 0;
|
|
168
|
+
}
|
|
169
|
+
var emLength = length(["em"], "em");
|
|
170
|
+
function readBaselineShift(v, warn, prop) {
|
|
171
|
+
const k = v.toLowerCase();
|
|
172
|
+
if (k === "super" || k === "sub") return { script: k };
|
|
173
|
+
if (k === "baseline") return {};
|
|
174
|
+
const d = dimension(v);
|
|
175
|
+
if (d?.unit === "%") return d.n === 0 ? {} : { baselineShift: d.n / 100 };
|
|
176
|
+
const n = emLength(v, warn, prop);
|
|
177
|
+
if (n == null) return void 0;
|
|
178
|
+
return n === 0 ? {} : { baselineShift: n };
|
|
179
|
+
}
|
|
180
|
+
var inherited = (read) => ({ inherits: true, read });
|
|
181
|
+
var own = (read) => ({ inherits: false, read });
|
|
182
|
+
var PROPERTIES = {
|
|
183
|
+
"fill": inherited(readPaint),
|
|
184
|
+
"fill-opacity": inherited(readRatio),
|
|
185
|
+
"fill-rule": inherited(keyword2("nonzero", "evenodd")),
|
|
186
|
+
"stroke": inherited(readPaint),
|
|
187
|
+
"stroke-width": inherited(worldLength),
|
|
188
|
+
"stroke-opacity": inherited(readRatio),
|
|
189
|
+
"stroke-linecap": inherited(readLinecap),
|
|
190
|
+
"stroke-linejoin": inherited(readLinejoin),
|
|
191
|
+
"stroke-dasharray": inherited(readDashArray),
|
|
192
|
+
"stroke-miterlimit": inherited(readMiterLimit),
|
|
193
|
+
"marker-start": inherited(readMarkerRef),
|
|
194
|
+
"marker-mid": inherited(readMarkerRef),
|
|
195
|
+
"marker-end": inherited(readMarkerRef),
|
|
196
|
+
"color": inherited(readColor),
|
|
197
|
+
"font-size": inherited(readFontSize),
|
|
198
|
+
"font-family": inherited((v) => v.length > 0 ? v : void 0),
|
|
199
|
+
"font-weight": inherited(readFontWeight),
|
|
200
|
+
"font-style": inherited(readFontStyle),
|
|
201
|
+
"text-anchor": inherited(keyword2("start", "middle", "end")),
|
|
202
|
+
"letter-spacing": inherited(readLetterSpacing),
|
|
203
|
+
"text-decoration": inherited(readDecoration),
|
|
204
|
+
"direction": inherited(keyword2("ltr", "rtl")),
|
|
205
|
+
"text-transform": inherited(readTextTransform),
|
|
206
|
+
"font-variant": inherited(readFontVariant),
|
|
207
|
+
"opacity": own(readRatio),
|
|
208
|
+
"stop-color": own(readSolidColor),
|
|
209
|
+
"stop-opacity": own(readRatio),
|
|
210
|
+
"baseline-shift": own(readBaselineShift),
|
|
211
|
+
"vector-effect": own(keyword2("none", "non-scaling-stroke"))
|
|
212
|
+
};
|
|
213
|
+
Object.keys(PROPERTIES).filter((p) => PROPERTIES[p].inherits);
|
|
38
214
|
function patternSpecOf(paint) {
|
|
39
215
|
return "tile" in paint.pattern ? paint.pattern : null;
|
|
40
216
|
}
|
|
@@ -53,7 +229,11 @@ function patternXml(id, paint, onWarn) {
|
|
|
53
229
|
`width="${trimNumber(geometry.size)}"`,
|
|
54
230
|
`height="${trimNumber(geometry.size)}"`
|
|
55
231
|
];
|
|
56
|
-
|
|
232
|
+
const [a, b, c, d] = paint.transform ?? [1, 0, 0, 1];
|
|
233
|
+
const placement = formatMatrix([a, b, c, d, origin.x, origin.y]);
|
|
234
|
+
if (paint.transform && !isIdentity([a, b, c, d, 0, 0]) && placement) {
|
|
235
|
+
attrs.push(`patternTransform="${placement}"`);
|
|
236
|
+
} else if (origin.x !== 0 || origin.y !== 0) {
|
|
57
237
|
attrs.push(`x="${trimNumber(origin.x)}"`, `y="${trimNumber(origin.y)}"`);
|
|
58
238
|
}
|
|
59
239
|
attrs.push(`data-weasel-tile="${escapeAttr(JSON.stringify(spec))}"`);
|
|
@@ -90,8 +270,8 @@ function escapeAttr(s) {
|
|
|
90
270
|
}
|
|
91
271
|
function serializePathD(path) {
|
|
92
272
|
if (path.kind === "rect") {
|
|
93
|
-
const { x, y, width, height } = path;
|
|
94
|
-
return `M${trimNumber(x)} ${trimNumber(y)}h${trimNumber(
|
|
273
|
+
const { x, y, width: width2, height: height2 } = path;
|
|
274
|
+
return `M${trimNumber(x)} ${trimNumber(y)}h${trimNumber(width2)}v${trimNumber(height2)}h${trimNumber(-width2)}Z`;
|
|
95
275
|
}
|
|
96
276
|
const cmds = path.commands;
|
|
97
277
|
const xs = path.coords;
|
|
@@ -176,6 +356,10 @@ var PaintServerRegistry = class {
|
|
|
176
356
|
if (hasNativeSvgForm(paint)) return `url(#${id})`;
|
|
177
357
|
return `url(#${id}) ${paintFallback(paint)}`;
|
|
178
358
|
}
|
|
359
|
+
/** The paint kind of each registered paint, once, in first-use order. */
|
|
360
|
+
paintKinds() {
|
|
361
|
+
return [...new Set(this.order.map((paint) => paint.fill ?? "solid"))];
|
|
362
|
+
}
|
|
179
363
|
/** Whether any registered paint serializes outside SVG's own vocabulary, so
|
|
180
364
|
* the root has to declare {@link WEASEL_NS}. */
|
|
181
365
|
usesPrivateNamespace() {
|
|
@@ -258,9 +442,10 @@ function paintServerXml(id, paint, onWarn) {
|
|
|
258
442
|
if (paint.fill === "pattern") return patternXml(id, paint, onWarn);
|
|
259
443
|
const builtin = gradientXml(id, paint);
|
|
260
444
|
if (builtin) return builtin;
|
|
261
|
-
const
|
|
445
|
+
const kind = getPaintKind(paint.fill);
|
|
446
|
+
const custom = kind?.toSvg?.(id, paint);
|
|
262
447
|
if (custom) return custom;
|
|
263
|
-
onWarn?.(`${paint.fill} fill has no vector form \u2014 omitted from <defs>`);
|
|
448
|
+
onWarn?.(kind ? `${paint.fill} fill has no vector form \u2014 omitted from <defs>` : `${paint.fill} fill is not registered \u2014 omitted from <defs>; a kind loaded on demand needs \`await warmSvg(nodes)\` before a synchronous export`);
|
|
264
449
|
return "";
|
|
265
450
|
}
|
|
266
451
|
function gradientUnitsAttr(units) {
|
|
@@ -508,19 +693,19 @@ function svgPaintOpacity(paint) {
|
|
|
508
693
|
function opacityAttr(name, v) {
|
|
509
694
|
return v != null && v !== 1 ? [`${name}="${trimNumber(v)}"`] : [];
|
|
510
695
|
}
|
|
511
|
-
function strokeWidthAttrs(
|
|
512
|
-
if (typeof
|
|
513
|
-
return [`stroke-width="${trimNumber(
|
|
696
|
+
function strokeWidthAttrs(width2) {
|
|
697
|
+
if (typeof width2 === "number") return [`stroke-width="${trimNumber(width2)}"`];
|
|
698
|
+
return [`stroke-width="${trimNumber(width2.px)}"`, 'vector-effect="non-scaling-stroke"'];
|
|
514
699
|
}
|
|
515
700
|
function coreStrokeAttrs(stroke, registry, warn) {
|
|
516
701
|
const paint = stroke?.paint;
|
|
517
702
|
if (!stroke || !paint) return [];
|
|
518
|
-
const
|
|
519
|
-
if (!((typeof
|
|
703
|
+
const width2 = stroke.width ?? 1;
|
|
704
|
+
if (!((typeof width2 === "object" ? width2.px : width2) > 0)) return [];
|
|
520
705
|
warnStrokeAlign(stroke.align, warn);
|
|
521
706
|
const attrs = [`stroke="${"color" in paint ? paint.color : registry.ref(paint)}"`];
|
|
522
707
|
attrs.push(...opacityAttr("stroke-opacity", paint.opacity));
|
|
523
|
-
attrs.push(...strokeWidthAttrs(
|
|
708
|
+
attrs.push(...strokeWidthAttrs(width2));
|
|
524
709
|
if (stroke.cap) attrs.push(`stroke-linecap="${stroke.cap}"`);
|
|
525
710
|
if (stroke.join) attrs.push(`stroke-linejoin="${stroke.join}"`);
|
|
526
711
|
if (stroke.dash && stroke.dash.length > 0) {
|
|
@@ -621,12 +806,14 @@ function textXml(node, registry, namespaces, warn) {
|
|
|
621
806
|
if (style?.fontFamily) attrs.push(`font-family="${escapeAttr2(style.fontFamily)}"`);
|
|
622
807
|
if (style?.fontWeight != null) attrs.push(`font-weight="${String(style.fontWeight)}"`);
|
|
623
808
|
if (style?.fontStyle && style.fontStyle !== "normal") attrs.push(`font-style="${style.fontStyle}"`);
|
|
809
|
+
if (style?.fontVariantCaps === "small-caps") attrs.push('font-variant="small-caps"');
|
|
624
810
|
const direction = style?.direction ?? "ltr";
|
|
625
811
|
if (direction === "rtl") attrs.push('direction="rtl"');
|
|
626
812
|
if (style?.align != null || direction === "rtl") {
|
|
627
813
|
const align = style?.align ?? "left";
|
|
628
|
-
const anchor = align === "center" ? "middle" : align === "start" ? "start" : align === "end" ? "end" : align === "left" === (direction === "ltr") ? "start" : "end";
|
|
814
|
+
const anchor = align === "center" ? "middle" : align === "start" || align === "justify" ? "start" : align === "end" ? "end" : align === "left" === (direction === "ltr") ? "start" : "end";
|
|
629
815
|
if (anchor !== "start") attrs.push(`text-anchor="${anchor}"`);
|
|
816
|
+
if (align === "justify") attrs.push('data-weasel-align="justify"');
|
|
630
817
|
}
|
|
631
818
|
if (style?.letterSpacing != null && style.letterSpacing !== 0) {
|
|
632
819
|
attrs.push(`letter-spacing="${trimNumber(resolveScreenLength(style.letterSpacing, 1))}"`);
|
|
@@ -661,17 +848,25 @@ function textXml(node, registry, namespaces, warn) {
|
|
|
661
848
|
const deg = node.rotation * 180 / Math.PI;
|
|
662
849
|
attrs.push(`transform="rotate(${trimNumber(deg)} ${trimNumber(cx)} ${trimNumber(cy)})"`);
|
|
663
850
|
}
|
|
664
|
-
const body = node.runs && node.runs.length > 0 ? node.runs.map((r) => runXml(r, registry, warn)).join("") : escapeText(node.text);
|
|
851
|
+
const body = node.runs && node.runs.length > 0 ? node.runs.map((r) => runXml(r, style, registry, warn)).join("") : escapeText(node.text);
|
|
665
852
|
const metaAttrs = metaAttrsXml(node.meta, namespaces);
|
|
666
853
|
const metaEls = metaElementsXml(node.meta, namespaces);
|
|
667
854
|
return `<text ${attrs.join(" ")}${metaAttrs}>${body}${metaEls}</text>`;
|
|
668
855
|
}
|
|
669
|
-
function
|
|
856
|
+
function scriptSizeFace(run, style) {
|
|
857
|
+
if (run.script == null || run.baselineShift == null) return void 0;
|
|
858
|
+
const face = resolveRunFace(run, resolveTextStyle(style));
|
|
859
|
+
return { family: face.fontFamily, weight: face.fontWeight, style: face.fontStyle };
|
|
860
|
+
}
|
|
861
|
+
function runXml(run, style, registry, warn) {
|
|
670
862
|
const attrs = [];
|
|
671
|
-
if (run.
|
|
863
|
+
if (run.fontWeight != null) attrs.push(`font-weight="${run.fontWeight}"`);
|
|
864
|
+
else if (run.bold) attrs.push(`font-weight="700"`);
|
|
672
865
|
if (run.italic) attrs.push(`font-style="italic"`);
|
|
866
|
+
if (run.fontVariantCaps) attrs.push(`font-variant="${run.fontVariantCaps}"`);
|
|
673
867
|
if (run.fontFamily) attrs.push(`font-family="${escapeAttr2(run.fontFamily)}"`);
|
|
674
|
-
const
|
|
868
|
+
const face = scriptSizeFace(run, style);
|
|
869
|
+
const presetScale = face && run.script ? scriptMetricsFor(face.family, face.weight, face.style)[run.script].size : void 0;
|
|
675
870
|
const scale = run.fontScale ?? presetScale;
|
|
676
871
|
if (run.fontSize != null) attrs.push(`font-size="${trimNumber(resolveScreenLength(run.fontSize, 1))}"`);
|
|
677
872
|
else if (scale != null) attrs.push(`font-size="${trimNumber(scale * 100)}%"`);
|
|
@@ -724,5 +919,5 @@ function pathBounds(path) {
|
|
|
724
919
|
}
|
|
725
920
|
|
|
726
921
|
export { nativeSvgKind, nativeSvgSpace, serializeSvg, tilePreviewCssUrl };
|
|
727
|
-
//# sourceMappingURL=chunk-
|
|
728
|
-
//# sourceMappingURL=chunk-
|
|
922
|
+
//# sourceMappingURL=chunk-E23Q6A3Y.js.map
|
|
923
|
+
//# sourceMappingURL=chunk-E23Q6A3Y.js.map
|