@heyramzi/ui 2.11.0 → 2.11.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/dist/agents/helpers.js +38 -38
- package/dist/agents/page-state.js +49 -50
- package/dist/agents/vendor/color.js +146 -127
- package/dist/agents/vendor/draw.js +617 -508
- package/dist/agents/vendor/engine.js +698 -599
- package/dist/agents/vendor/mesh.js +653 -683
- package/dist/agents/vendor/plastic.js +3913 -3112
- package/dist/agents/vendor/presets.js +163 -164
- package/dist/agents/vendor/shapes.js +21 -20
- package/dist/agents/vendor/ticker.js +41 -42
- package/dist/agents/vendor/types.js +1 -0
- package/dist/agents/vendor/wear.js +1421 -1448
- package/dist/ai/confirmation/confirmation-context.svelte.js +6 -6
- package/dist/ai/confirmation/index.js +3 -1
- package/dist/ai/index.js +33 -0
- package/dist/ai/prompt-input/index.js +3 -1
- package/dist/ai/reasoning/index.js +3 -1
- package/dist/ai/reasoning/reasoning-context.svelte.js +6 -6
- package/dist/ai/suggestion/index.js +3 -1
- package/dist/ai/typing-dots/index.js +3 -1
- package/dist/animations/text-swap.js +24 -24
- package/dist/brand/index.js +54 -48
- package/dist/canvas/card/resize.js +5 -3
- package/dist/canvas/edges/edge-path.js +255 -242
- package/dist/canvas/editor/context-menu.js +39 -36
- package/dist/canvas/editor/dispatch.svelte.js +154 -151
- package/dist/canvas/editor/editor-context.js +7 -2
- package/dist/canvas/editor/editor-mode.js +1 -0
- package/dist/canvas/editor/frame.js +73 -76
- package/dist/canvas/editor/hand-context.js +5 -2
- package/dist/canvas/editor/history-core.js +163 -191
- package/dist/canvas/editor/keymap.js +95 -169
- package/dist/canvas/editor/layout-actions.js +143 -144
- package/dist/canvas/editor/lock.js +52 -51
- package/dist/canvas/editor/rebase.js +217 -240
- package/dist/canvas/editor/style.js +132 -137
- package/dist/canvas/editor/text-field-context.js +7 -2
- package/dist/canvas/editor/z-order.js +65 -70
- package/dist/canvas/headless/alignment.js +22 -16
- package/dist/canvas/headless/break-apart-find.js +286 -279
- package/dist/canvas/headless/break-apart-pieces.js +62 -58
- package/dist/canvas/headless/break-apart-plan.js +299 -325
- package/dist/canvas/headless/break-apart-style.js +75 -70
- package/dist/canvas/headless/break-apart.js +188 -181
- package/dist/canvas/headless/canvas-cleanup.js +78 -58
- package/dist/canvas/headless/edge-anchors.js +115 -116
- package/dist/canvas/headless/edge-memo.js +24 -22
- package/dist/canvas/headless/edge-serialization.js +17 -27
- package/dist/canvas/headless/figure-geometry.js +232 -264
- package/dist/canvas/headless/fit-viewport.js +84 -67
- package/dist/canvas/headless/grid.js +88 -86
- package/dist/canvas/headless/icon-node.js +44 -36
- package/dist/canvas/headless/index.js +1 -0
- package/dist/canvas/headless/linkify.js +17 -19
- package/dist/canvas/headless/pen-marks.js +101 -95
- package/dist/canvas/headless/sketch.js +231 -209
- package/dist/canvas/headless/snap-guides.js +99 -83
- package/dist/canvas/headless/svg-figure.js +133 -117
- package/dist/canvas/headless/table-layout.js +146 -107
- package/dist/canvas/index.js +2 -0
- package/dist/canvas/lod/lod-mode.svelte.js +20 -18
- package/dist/canvas/lod/render-all.svelte.js +36 -39
- package/dist/canvas/ops/arrange.js +78 -71
- package/dist/canvas/ops/ops.js +260 -255
- package/dist/canvas/pen/colors.js +37 -35
- package/dist/canvas/pen/eraser.js +28 -27
- package/dist/canvas/pen/geometry.js +120 -130
- package/dist/canvas/pen/index.js +1 -0
- package/dist/canvas/pen/ops.js +11 -11
- package/dist/canvas/pen/pen-session.js +150 -159
- package/dist/canvas/pen/plugin.js +107 -104
- package/dist/canvas/pen/shapes.js +73 -68
- package/dist/canvas/pen/stroke-path.js +32 -30
- package/dist/canvas/pen/types.js +21 -21
- package/dist/canvas/pen/ui.js +10 -8
- package/dist/canvas/plugin.js +46 -46
- package/dist/canvas/screen/glyphs.js +12 -11
- package/dist/canvas/screen/labels.js +22 -22
- package/dist/canvas/screen/parts.js +98 -111
- package/dist/canvas/screen/plugin.js +47 -56
- package/dist/canvas/screen/types.js +30 -35
- package/dist/canvas/screen/ui.js +7 -7
- package/dist/canvas/test-utils.js +14 -14
- package/dist/canvas/types.js +1 -0
- package/dist/canvas/ui/forward-wheel.js +24 -25
- package/dist/canvas/ui/icons.js +64 -131
- package/dist/canvas/ui/place-panel.js +58 -49
- package/dist/canvas/ui/shortcut-tip.js +14 -12
- package/dist/canvas/ui/tools.js +300 -385
- package/dist/charts/dashboard/chart.js +4 -0
- package/dist/charts/dashboard/data-table.js +11 -0
- package/dist/charts/dashboard/windows.js +8 -3
- package/dist/charts/edge-fade.js +10 -5
- package/dist/charts/hover-band.js +16 -11
- package/dist/charts/index.js +0 -1
- package/dist/charts/motion.js +11 -7
- package/dist/charts/primitives/chart-utils.js +12 -12
- package/dist/components/copy/clipboard.js +32 -32
- package/dist/components/copy/copied.svelte.js +31 -23
- package/dist/components/data-table/data-table.js +39 -39
- package/dist/components/docs/index.js +4 -0
- package/dist/components/docs/scroll-spy.svelte.js +73 -68
- package/dist/components/list-page/filter-section.js +4 -1
- package/dist/components/list-page/index.js +2 -0
- package/dist/components/list-page/list-table.js +7 -2
- package/dist/components/list-page/queue-rail.js +14 -0
- package/dist/components/list-page/section-host.js +4 -2
- package/dist/components/list-page/step.js +4 -3
- package/dist/components/list-page/types.js +1 -0
- package/dist/components/picker/trigger.js +48 -30
- package/dist/components/picker/types.js +1 -0
- package/dist/components/segmented/collapse.js +38 -27
- package/dist/components/segmented/index.js +8 -0
- package/dist/components/segmented/segmented.js +67 -42
- package/dist/components/star-rating-input/index.js +3 -1
- package/dist/components/table-view/types.js +1 -0
- package/dist/components/tags-input/tags.js +81 -69
- package/dist/components/theme/index.js +4 -0
- package/dist/components/toolbar/index.js +4 -0
- package/dist/components/toolbar/toolbar-trigger.js +14 -1
- package/dist/editor/anchors.js +17 -13
- package/dist/editor/block-id.js +52 -51
- package/dist/editor/block-ops.js +108 -80
- package/dist/editor/doc-blocks.js +155 -166
- package/dist/editor/extensions.js +139 -180
- package/dist/editor/index.js +4 -0
- package/dist/editor/markdown-test-helpers.js +4 -2
- package/dist/editor/markdown.js +420 -408
- package/dist/editor/serializer.js +204 -200
- package/dist/editor/slash-items.js +89 -101
- package/dist/editor/youtube-url.js +25 -20
- package/dist/effects/animated-beam/path-calculator.svelte.js +43 -38
- package/dist/effects/animated-beam/types.js +1 -0
- package/dist/effects/border-beam/css.js +92 -78
- package/dist/effects/border-beam/presets.js +1705 -1720
- package/dist/effects/border-beam/register-properties.js +43 -33
- package/dist/effects/border-beam/types.js +1 -0
- package/dist/effects/image-comparison/compare.js +3 -2
- package/dist/effects/image-reveal/types.js +1 -0
- package/dist/effects/magnetic/magnetic.js +58 -52
- package/dist/effects/reveal/observe.js +50 -40
- package/dist/effects/reveal/types.js +1 -0
- package/dist/effects/shader-gradient/color.js +36 -29
- package/dist/effects/shader-gradient/renderer.js +384 -295
- package/dist/effects/shader-gradient/shaders.js +31 -0
- package/dist/effects/shader-gradient/types.js +1 -0
- package/dist/icons/apple-symbol-exports.js +99 -124
- package/dist/icons/sf-symbols.js +357 -461
- package/dist/icons/trades.js +43 -28
- package/dist/inbox/index.js +1 -0
- package/dist/inbox/logic.js +126 -122
- package/dist/inbox/types.js +43 -43
- package/dist/lib/arrive.js +19 -12
- package/dist/lib/icon-types.js +1 -0
- package/dist/lib/initials.js +16 -10
- package/dist/lib/layout.js +5 -0
- package/dist/lib/panel.js +13 -0
- package/dist/lib/result.js +22 -22
- package/dist/lib/sliding-pill.js +59 -44
- package/dist/lib/theme-transition.js +43 -43
- package/dist/lib/tone.js +31 -24
- package/dist/lib/utils.js +3 -1
- package/dist/onboarding/define-tours.js +24 -23
- package/dist/onboarding/onboarding.svelte.js +16 -12
- package/dist/onboarding/pick.js +10 -6
- package/dist/onboarding/stores.js +40 -41
- package/dist/onboarding/wait.js +24 -23
- package/dist/panel/side-panel-types.js +1 -0
- package/dist/record/demo-data.js +459 -486
- package/dist/record/fields.js +129 -131
- package/dist/record/format.js +70 -82
- package/dist/record/gutter.js +1 -0
- package/dist/record/kinds.js +95 -105
- package/dist/record/logic.js +238 -219
- package/dist/record/types.js +49 -48
- package/dist/shadcn/accordion/index.js +3 -1
- package/dist/shadcn/alert/index.js +3 -1
- package/dist/shadcn/alert-dialog/index.js +3 -1
- package/dist/shadcn/attachment/index.js +3 -1
- package/dist/shadcn/avatar/index.js +3 -1
- package/dist/shadcn/breadcrumb/index.js +3 -1
- package/dist/shadcn/bubble/index.js +3 -1
- package/dist/shadcn/button/index.js +3 -1
- package/dist/shadcn/calendar/index.js +3 -1
- package/dist/shadcn/card/index.js +3 -1
- package/dist/shadcn/checkbox/index.js +3 -1
- package/dist/shadcn/code-block/index.js +3 -1
- package/dist/shadcn/collapsible/index.js +3 -1
- package/dist/shadcn/command/index.js +4 -1
- package/dist/shadcn/context-menu/index.js +3 -1
- package/dist/shadcn/dialog/index.js +3 -1
- package/dist/shadcn/dropdown-menu/menu-item.js +40 -20
- package/dist/shadcn/empty/index.js +3 -1
- package/dist/shadcn/field/index.js +3 -1
- package/dist/shadcn/hooks/highlighter.js +77 -75
- package/dist/shadcn/hooks/is-mobile.svelte.js +3 -3
- package/dist/shadcn/hooks/use-highlighted-code.svelte.js +62 -62
- package/dist/shadcn/input/index.js +3 -1
- package/dist/shadcn/kbd/index.js +3 -1
- package/dist/shadcn/label/index.js +3 -1
- package/dist/shadcn/marker/index.js +3 -1
- package/dist/shadcn/message/index.js +3 -1
- package/dist/shadcn/message-scroller/index.js +3 -1
- package/dist/shadcn/popover/index.js +3 -1
- package/dist/shadcn/progress/index.js +3 -1
- package/dist/shadcn/progress/tone.js +8 -7
- package/dist/shadcn/radio-group/index.js +3 -1
- package/dist/shadcn/scroll-area/index.js +3 -1
- package/dist/shadcn/select/index.js +3 -1
- package/dist/shadcn/separator/index.js +3 -1
- package/dist/shadcn/sheet/index.js +3 -1
- package/dist/shadcn/sidebar/context.svelte.js +42 -28
- package/dist/shadcn/sidebar/index.js +3 -1
- package/dist/shadcn/skeleton/index.js +3 -1
- package/dist/shadcn/slider/index.js +3 -1
- package/dist/shadcn/switch/index.js +3 -1
- package/dist/shadcn/table/index.js +3 -1
- package/dist/shadcn/tabs/index.js +3 -1
- package/dist/shadcn/textarea/index.js +3 -1
- package/dist/shadcn/toggle/index.js +3 -1
- package/dist/shadcn/toggle-group/index.js +3 -1
- package/dist/shadcn/tooltip/context.js +7 -2
- package/dist/shadcn/tooltip/index.js +3 -1
- package/dist/shadcn/trace/index.js +3 -1
- package/dist/slides/bridges.js +65 -59
- package/dist/slides/deck-controller.svelte.js +210 -207
- package/dist/slides/export/capture.js +66 -71
- package/dist/slides/export/ffmpeg.js +76 -72
- package/dist/slides/export/index.js +3 -0
- package/dist/slides/export/launch.js +9 -6
- package/dist/slides/export/pdf.js +60 -54
- package/dist/slides/export/types.js +1 -0
- package/dist/slides/labels.js +24 -24
- package/dist/slides/layout.js +39 -41
- package/dist/slides/model.js +9 -7
- package/dist/slides/navigation.js +78 -73
- package/dist/slides/types.js +2 -2
- package/dist/status/define-statuses.js +18 -14
- package/dist/status/status-types.js +1 -0
- package/dist/test-setup.js +24 -20
- package/dist/thread/logic.js +73 -77
- package/dist/thread/types.js +21 -21
- package/dist/work/board-order.js +94 -90
- package/dist/work/dates.js +16 -9
- package/dist/work/detail/detail-types.js +18 -18
- package/dist/work/docs/edited.js +32 -29
- package/dist/work/docs/index.js +4 -0
- package/dist/work/docs/labels.js +34 -34
- package/dist/work/docs/menu.js +113 -106
- package/dist/work/docs/outline.js +39 -29
- package/dist/work/gantt/logic.js +211 -235
- package/dist/work/inbox/inbox-logic.js +71 -75
- package/dist/work/inbox/inbox-statuses.js +75 -72
- package/dist/work/inbox/inbox-types.js +1 -0
- package/dist/work/kanban-drag.js +27 -22
- package/dist/work/kanban-types.js +1 -0
- package/dist/work/presets/sales.js +36 -32
- package/dist/work/reorder.js +9 -8
- package/dist/work/task-types.js +1 -0
- package/dist/work/time/duration.js +51 -46
- package/dist/work/time/time-types.js +23 -23
- package/dist/work/use-kanban-dnd.svelte.js +126 -125
- package/package.json +3 -1
- package/src/components/list-page/master-detail.svelte +3 -1
- package/src/components/list-page/rail-row.svelte +4 -4
- package/src/components/tags-input/tags-input.svelte +2 -0
- package/src/editor/markdown.ts +30 -35
|
@@ -1,174 +1,169 @@
|
|
|
1
1
|
import { PEN_COLORS, SHAPE_NODE, STROKE_NODE, TEXT_NODE } from "../pen/types.js";
|
|
2
2
|
export const FONT_SIZES = [
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
16,
|
|
4
|
+
20,
|
|
5
|
+
28,
|
|
6
|
+
40
|
|
7
7
|
];
|
|
8
8
|
const SHAPE_WIDTHS = [
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
2,
|
|
10
|
+
3,
|
|
11
|
+
5
|
|
12
12
|
];
|
|
13
13
|
const PEN_WIDTHS = [
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
2,
|
|
15
|
+
4,
|
|
16
|
+
8
|
|
17
17
|
];
|
|
18
18
|
const HIGHLIGHTER_WIDTHS = [
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
12,
|
|
20
|
+
20,
|
|
21
|
+
32
|
|
22
22
|
];
|
|
23
23
|
const FRAME_WIDTHS = [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
1,
|
|
25
|
+
2,
|
|
26
|
+
4
|
|
27
27
|
];
|
|
28
28
|
const CONTROLS = {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"stroke",
|
|
46
|
-
"width"
|
|
47
|
-
]
|
|
29
|
+
shape: [
|
|
30
|
+
"fill",
|
|
31
|
+
"stroke",
|
|
32
|
+
"width"
|
|
33
|
+
],
|
|
34
|
+
text: [
|
|
35
|
+
"stroke",
|
|
36
|
+
"fontSize",
|
|
37
|
+
"fontWeight"
|
|
38
|
+
],
|
|
39
|
+
stroke: ["stroke", "width"],
|
|
40
|
+
frame: [
|
|
41
|
+
"fill",
|
|
42
|
+
"stroke",
|
|
43
|
+
"width"
|
|
44
|
+
]
|
|
48
45
|
};
|
|
49
46
|
function kindOf(node, frameType) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
if (node.type === SHAPE_NODE) return "shape";
|
|
48
|
+
if (node.type === TEXT_NODE) return "text";
|
|
49
|
+
if (node.type === STROKE_NODE) return "stroke";
|
|
50
|
+
// Only a frame from the F tool wears a fill and a line; a group draws its own colour.
|
|
51
|
+
return node.type === frameType && node.data.frame === true ? "frame" : null;
|
|
54
52
|
}
|
|
55
53
|
function widthsOf(kind, node) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
if (kind === "shape") return SHAPE_WIDTHS;
|
|
55
|
+
if (kind === "frame") return FRAME_WIDTHS;
|
|
56
|
+
return node.data.tool === "highlighter" ? HIGHLIGHTER_WIDTHS : PEN_WIDTHS;
|
|
59
57
|
}
|
|
60
58
|
function widthKey(kind) {
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
if (kind === "stroke") return "size";
|
|
60
|
+
return "strokeWidth";
|
|
63
61
|
}
|
|
64
62
|
function colorOf(value) {
|
|
65
|
-
|
|
63
|
+
return PEN_COLORS.find((color) => color === value);
|
|
66
64
|
}
|
|
67
65
|
function levelOf(kind, node) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
66
|
+
const widths = widthsOf(kind, node);
|
|
67
|
+
// A frame nobody styled draws the thinnest line, and a pen mark its middle one.
|
|
68
|
+
const stored = Number(node.data[widthKey(kind)]);
|
|
69
|
+
if (!Number.isFinite(stored)) return kind === "frame" ? 0 : 1;
|
|
70
|
+
let nearest = 0;
|
|
71
|
+
for (let at = 1; at < widths.length; at += 1) {
|
|
72
|
+
if (Math.abs(widths[at] - stored) < Math.abs(widths[nearest] - stored)) nearest = at;
|
|
73
|
+
}
|
|
74
|
+
return nearest;
|
|
76
75
|
}
|
|
76
|
+
/** What a card of each kind shows, given the colour it draws in. */
|
|
77
77
|
const VALUES = {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
78
|
+
shape: (node, color) => ({
|
|
79
|
+
fill: node.data.filled ? colorOf(node.data.fill) ?? color : "none",
|
|
80
|
+
stroke: color,
|
|
81
|
+
width: levelOf("shape", node)
|
|
82
|
+
}),
|
|
83
|
+
text: (node, color) => ({
|
|
84
|
+
stroke: color,
|
|
85
|
+
fontSize: Number(node.data.fontSize) || 20,
|
|
86
|
+
fontWeight: node.data.fontWeight === "bold" ? "bold" : "regular"
|
|
87
|
+
}),
|
|
88
|
+
stroke: (node, color) => ({
|
|
89
|
+
stroke: color,
|
|
90
|
+
width: levelOf("stroke", node)
|
|
91
|
+
}),
|
|
92
|
+
frame: (node) => ({
|
|
93
|
+
fill: colorOf(node.data.fill) ?? "none",
|
|
94
|
+
stroke: colorOf(node.data.stroke) ?? "ink",
|
|
95
|
+
width: levelOf("frame", node)
|
|
96
|
+
})
|
|
97
97
|
};
|
|
98
98
|
function valuesOf(kind, node) {
|
|
99
|
-
|
|
99
|
+
return VALUES[kind](node, colorOf(node.data.color) ?? "ink");
|
|
100
100
|
}
|
|
101
|
+
/** What the panel shows for a selection, or null when nothing in it takes a style. */
|
|
101
102
|
export function summarizeStyle(nodes, frameType) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
controls,
|
|
128
|
-
values,
|
|
129
|
-
widths
|
|
130
|
-
};
|
|
103
|
+
const controls = new Set();
|
|
104
|
+
const seen = new Map();
|
|
105
|
+
let widths = [];
|
|
106
|
+
for (const node of nodes) {
|
|
107
|
+
const kind = kindOf(node, frameType);
|
|
108
|
+
if (!kind) continue;
|
|
109
|
+
const values = valuesOf(kind, node);
|
|
110
|
+
for (const control of CONTROLS[kind]) {
|
|
111
|
+
controls.add(control);
|
|
112
|
+
const set = seen.get(control) ?? new Set();
|
|
113
|
+
set.add(values[control]);
|
|
114
|
+
seen.set(control, set);
|
|
115
|
+
}
|
|
116
|
+
if (widths.length === 0 && CONTROLS[kind].includes("width")) widths = widthsOf(kind, node);
|
|
117
|
+
}
|
|
118
|
+
if (controls.size === 0) return null;
|
|
119
|
+
const values = {};
|
|
120
|
+
for (const [control, set] of seen) {
|
|
121
|
+
if (set.size === 1) Object.assign(values, { [control]: [...set][0] });
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
controls,
|
|
125
|
+
values,
|
|
126
|
+
widths
|
|
127
|
+
};
|
|
131
128
|
}
|
|
129
|
+
/** A frame keeps its fill as is; a shape's fill also says whether it is filled. */
|
|
132
130
|
function fillData(kind, fill) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
} : {
|
|
139
|
-
filled: true,
|
|
140
|
-
fill
|
|
141
|
-
};
|
|
131
|
+
if (kind === "frame") return { fill };
|
|
132
|
+
return fill === "none" ? { filled: false } : {
|
|
133
|
+
filled: true,
|
|
134
|
+
fill
|
|
135
|
+
};
|
|
142
136
|
}
|
|
143
137
|
function textData(change) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
138
|
+
const data = {};
|
|
139
|
+
if (change.fontSize !== undefined) data.fontSize = change.fontSize;
|
|
140
|
+
if (change.fontWeight !== undefined) data.fontWeight = change.fontWeight;
|
|
141
|
+
return data;
|
|
148
142
|
}
|
|
149
143
|
function dataFor(kind, node, change) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
144
|
+
const data = {};
|
|
145
|
+
if (change.stroke) data[kind === "frame" ? "stroke" : "color"] = change.stroke;
|
|
146
|
+
if (change.fill !== undefined && (kind === "shape" || kind === "frame")) {
|
|
147
|
+
Object.assign(data, fillData(kind, change.fill));
|
|
148
|
+
}
|
|
149
|
+
if (change.width !== undefined && kind !== "text") {
|
|
150
|
+
data[widthKey(kind)] = widthsOf(kind, node)[change.width];
|
|
151
|
+
}
|
|
152
|
+
if (kind === "text") Object.assign(data, textData(change));
|
|
153
|
+
return data;
|
|
160
154
|
}
|
|
155
|
+
/** One patch per card the change applies to. All of them are one undo step when dispatched together. */
|
|
161
156
|
export function styleOps(nodes, change, frameType) {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
157
|
+
const ops = [];
|
|
158
|
+
for (const node of nodes) {
|
|
159
|
+
const kind = kindOf(node, frameType);
|
|
160
|
+
if (!kind) continue;
|
|
161
|
+
const data = dataFor(kind, node, change);
|
|
162
|
+
if (Object.keys(data).length > 0) ops.push({
|
|
163
|
+
kind: "patchNode",
|
|
164
|
+
nodeId: node.id,
|
|
165
|
+
data
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
return ops;
|
|
174
169
|
}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
// The text field a host hands the pen. A plain textarea keeps the canvas MIT-clean; a host that
|
|
2
|
+
// formats text provides a component, set once with the page skin.
|
|
1
3
|
import { getContext, setContext } from "svelte";
|
|
4
|
+
/** For a host that mounts a pen node with `mount(..., { context })`, as a test does. */
|
|
2
5
|
export const TEXT_FIELD_KEY = Symbol("canvas-text-field");
|
|
6
|
+
/** Call during component init. */
|
|
3
7
|
export function setTextField(component) {
|
|
4
|
-
|
|
8
|
+
setContext(TEXT_FIELD_KEY, component);
|
|
5
9
|
}
|
|
10
|
+
/** The host's field, or null: the pen then draws its own textarea. */
|
|
6
11
|
export function useTextField() {
|
|
7
|
-
|
|
12
|
+
return getContext(TEXT_FIELD_KEY) ?? null;
|
|
8
13
|
}
|
|
@@ -1,82 +1,77 @@
|
|
|
1
|
+
/** Ink is an annotation layer pinned above every card by pen.css, so it has no place in a stack. */
|
|
1
2
|
export const INK_TYPES = new Set([
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
"stroke",
|
|
4
|
+
"text",
|
|
5
|
+
"shape"
|
|
5
6
|
]);
|
|
6
7
|
function layerOf(node) {
|
|
7
|
-
|
|
8
|
+
return typeof node.zIndex === "number" ? node.zIndex : 0;
|
|
8
9
|
}
|
|
10
|
+
/** Cards stack among their siblings: a child never leaves its group's own stack. */
|
|
9
11
|
function stacks(nodes) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
12
|
+
const byParent = new Map();
|
|
13
|
+
nodes.forEach((node, index) => {
|
|
14
|
+
if (INK_TYPES.has(node.type ?? "")) return;
|
|
15
|
+
const key = node.parentId ?? "";
|
|
16
|
+
const stack = byParent.get(key) ?? [];
|
|
17
|
+
stack.push({
|
|
18
|
+
node,
|
|
19
|
+
index
|
|
20
|
+
});
|
|
21
|
+
byParent.set(key, stack);
|
|
22
|
+
});
|
|
23
|
+
for (const stack of byParent.values()) {
|
|
24
|
+
stack.sort((a, b) => layerOf(a.node) - layerOf(b.node) || a.index - b.index);
|
|
25
|
+
}
|
|
26
|
+
return byParent;
|
|
25
27
|
}
|
|
28
|
+
/** One stack after a move, bottom first. Selected cards keep their order among themselves. */
|
|
26
29
|
function moved(stack, picked, move) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
next[i + 1],
|
|
43
|
-
next[i]
|
|
44
|
-
];
|
|
45
|
-
}
|
|
46
|
-
} else {
|
|
47
|
-
for(let i = 1; i < next.length; i++){
|
|
48
|
-
if (isPicked(next[i]) && !isPicked(next[i - 1])) [next[i], next[i - 1]] = [
|
|
49
|
-
next[i - 1],
|
|
50
|
-
next[i]
|
|
51
|
-
];
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return next;
|
|
30
|
+
const isPicked = (slot) => picked.has(slot.node.id);
|
|
31
|
+
if (move === "front") return [...stack.filter((s) => !isPicked(s)), ...stack.filter(isPicked)];
|
|
32
|
+
if (move === "back") return [...stack.filter(isPicked), ...stack.filter((s) => !isPicked(s))];
|
|
33
|
+
const next = [...stack];
|
|
34
|
+
// One step: each picked card trades places with the unpicked card beside it.
|
|
35
|
+
if (move === "forward") {
|
|
36
|
+
for (let i = next.length - 2; i >= 0; i--) {
|
|
37
|
+
if (isPicked(next[i]) && !isPicked(next[i + 1])) [next[i], next[i + 1]] = [next[i + 1], next[i]];
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
for (let i = 1; i < next.length; i++) {
|
|
41
|
+
if (isPicked(next[i]) && !isPicked(next[i - 1])) [next[i], next[i - 1]] = [next[i - 1], next[i]];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return next;
|
|
55
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* The board after a stacking move, or null when nothing changes. Only a stack holding a
|
|
48
|
+
* picked card is touched, and only cards whose layer changed are rewritten.
|
|
49
|
+
*/
|
|
56
50
|
export function reorderStack(nodes, picked, move) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
51
|
+
const layers = new Map();
|
|
52
|
+
for (const stack of stacks(nodes).values()) {
|
|
53
|
+
if (!stack.some((slot) => picked.has(slot.node.id))) continue;
|
|
54
|
+
const next = moved(stack, picked, move);
|
|
55
|
+
if (next.every((slot, i) => slot === stack[i])) continue;
|
|
56
|
+
next.forEach((slot, rank) => {
|
|
57
|
+
if (layerOf(slot.node) !== rank) layers.set(slot.node.id, rank);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (layers.size === 0) return null;
|
|
61
|
+
return nodes.map((node) => {
|
|
62
|
+
const layer = layers.get(node.id);
|
|
63
|
+
return layer === undefined ? node : {
|
|
64
|
+
...node,
|
|
65
|
+
zIndex: layer
|
|
66
|
+
};
|
|
67
|
+
});
|
|
74
68
|
}
|
|
69
|
+
/** The layer a new card needs to land on top of its siblings, or undefined while no card has been raised. */
|
|
75
70
|
export function topLayer(nodes, parentId) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
let top = 0;
|
|
72
|
+
for (const node of nodes) {
|
|
73
|
+
if (INK_TYPES.has(node.type ?? "") || (node.parentId ?? "") !== (parentId ?? "")) continue;
|
|
74
|
+
top = Math.max(top, layerOf(node));
|
|
75
|
+
}
|
|
76
|
+
return top > 0 ? top + 1 : undefined;
|
|
82
77
|
}
|
|
@@ -1,20 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Align nodes horizontally (same row): set all to the topmost Y.
|
|
3
|
+
*/
|
|
1
4
|
export function alignNodesHorizontally(nodes) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
if (nodes.length < 2) return;
|
|
6
|
+
const targetY = Math.min(...nodes.map((n) => n.position.y));
|
|
7
|
+
for (const node of nodes) {
|
|
8
|
+
node.position = {
|
|
9
|
+
...node.position,
|
|
10
|
+
y: targetY
|
|
11
|
+
};
|
|
12
|
+
}
|
|
10
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Align nodes vertically (same column): set all to the leftmost X.
|
|
16
|
+
*/
|
|
11
17
|
export function alignNodesVertically(nodes) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
if (nodes.length < 2) return;
|
|
19
|
+
const targetX = Math.min(...nodes.map((n) => n.position.x));
|
|
20
|
+
for (const node of nodes) {
|
|
21
|
+
node.position = {
|
|
22
|
+
...node.position,
|
|
23
|
+
x: targetX
|
|
24
|
+
};
|
|
25
|
+
}
|
|
20
26
|
}
|