@heyramzi/ui 2.11.1 → 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.
Files changed (266) hide show
  1. package/dist/agents/helpers.js +38 -38
  2. package/dist/agents/page-state.js +49 -50
  3. package/dist/agents/vendor/color.js +146 -127
  4. package/dist/agents/vendor/draw.js +617 -508
  5. package/dist/agents/vendor/engine.js +698 -599
  6. package/dist/agents/vendor/mesh.js +653 -683
  7. package/dist/agents/vendor/plastic.js +3913 -3112
  8. package/dist/agents/vendor/presets.js +163 -164
  9. package/dist/agents/vendor/shapes.js +21 -20
  10. package/dist/agents/vendor/ticker.js +41 -42
  11. package/dist/agents/vendor/types.js +1 -0
  12. package/dist/agents/vendor/wear.js +1421 -1448
  13. package/dist/ai/confirmation/confirmation-context.svelte.js +6 -6
  14. package/dist/ai/confirmation/index.js +3 -1
  15. package/dist/ai/index.js +33 -0
  16. package/dist/ai/prompt-input/index.js +3 -1
  17. package/dist/ai/reasoning/index.js +3 -1
  18. package/dist/ai/reasoning/reasoning-context.svelte.js +6 -6
  19. package/dist/ai/suggestion/index.js +3 -1
  20. package/dist/ai/typing-dots/index.js +3 -1
  21. package/dist/animations/text-swap.js +24 -24
  22. package/dist/brand/index.js +54 -48
  23. package/dist/canvas/card/resize.js +5 -3
  24. package/dist/canvas/edges/edge-path.js +255 -242
  25. package/dist/canvas/editor/context-menu.js +39 -36
  26. package/dist/canvas/editor/dispatch.svelte.js +154 -151
  27. package/dist/canvas/editor/editor-context.js +7 -2
  28. package/dist/canvas/editor/editor-mode.js +1 -0
  29. package/dist/canvas/editor/frame.js +73 -76
  30. package/dist/canvas/editor/hand-context.js +5 -2
  31. package/dist/canvas/editor/history-core.js +163 -191
  32. package/dist/canvas/editor/keymap.js +95 -169
  33. package/dist/canvas/editor/layout-actions.js +143 -144
  34. package/dist/canvas/editor/lock.js +52 -51
  35. package/dist/canvas/editor/rebase.js +217 -240
  36. package/dist/canvas/editor/style.js +132 -137
  37. package/dist/canvas/editor/text-field-context.js +7 -2
  38. package/dist/canvas/editor/z-order.js +65 -70
  39. package/dist/canvas/headless/alignment.js +22 -16
  40. package/dist/canvas/headless/break-apart-find.js +286 -279
  41. package/dist/canvas/headless/break-apart-pieces.js +62 -58
  42. package/dist/canvas/headless/break-apart-plan.js +299 -325
  43. package/dist/canvas/headless/break-apart-style.js +75 -70
  44. package/dist/canvas/headless/break-apart.js +188 -181
  45. package/dist/canvas/headless/canvas-cleanup.js +78 -58
  46. package/dist/canvas/headless/edge-anchors.js +115 -116
  47. package/dist/canvas/headless/edge-memo.js +24 -22
  48. package/dist/canvas/headless/edge-serialization.js +17 -27
  49. package/dist/canvas/headless/figure-geometry.js +232 -264
  50. package/dist/canvas/headless/fit-viewport.js +84 -67
  51. package/dist/canvas/headless/grid.js +88 -86
  52. package/dist/canvas/headless/icon-node.js +44 -36
  53. package/dist/canvas/headless/index.js +1 -0
  54. package/dist/canvas/headless/linkify.js +17 -19
  55. package/dist/canvas/headless/pen-marks.js +101 -95
  56. package/dist/canvas/headless/sketch.js +231 -209
  57. package/dist/canvas/headless/snap-guides.js +99 -83
  58. package/dist/canvas/headless/svg-figure.js +133 -117
  59. package/dist/canvas/headless/table-layout.js +146 -107
  60. package/dist/canvas/index.js +2 -0
  61. package/dist/canvas/lod/lod-mode.svelte.js +20 -18
  62. package/dist/canvas/lod/render-all.svelte.js +36 -39
  63. package/dist/canvas/ops/arrange.js +78 -71
  64. package/dist/canvas/ops/ops.js +260 -255
  65. package/dist/canvas/pen/colors.js +37 -35
  66. package/dist/canvas/pen/eraser.js +28 -27
  67. package/dist/canvas/pen/geometry.js +120 -130
  68. package/dist/canvas/pen/index.js +1 -0
  69. package/dist/canvas/pen/ops.js +11 -11
  70. package/dist/canvas/pen/pen-session.js +150 -159
  71. package/dist/canvas/pen/plugin.js +107 -104
  72. package/dist/canvas/pen/shapes.js +73 -68
  73. package/dist/canvas/pen/stroke-path.js +32 -30
  74. package/dist/canvas/pen/types.js +21 -21
  75. package/dist/canvas/pen/ui.js +10 -8
  76. package/dist/canvas/plugin.js +46 -46
  77. package/dist/canvas/screen/glyphs.js +12 -11
  78. package/dist/canvas/screen/labels.js +22 -22
  79. package/dist/canvas/screen/parts.js +98 -111
  80. package/dist/canvas/screen/plugin.js +47 -56
  81. package/dist/canvas/screen/types.js +30 -35
  82. package/dist/canvas/screen/ui.js +7 -7
  83. package/dist/canvas/test-utils.js +14 -14
  84. package/dist/canvas/types.js +1 -0
  85. package/dist/canvas/ui/forward-wheel.js +24 -25
  86. package/dist/canvas/ui/icons.js +64 -131
  87. package/dist/canvas/ui/place-panel.js +58 -49
  88. package/dist/canvas/ui/shortcut-tip.js +14 -12
  89. package/dist/canvas/ui/tools.js +300 -385
  90. package/dist/charts/dashboard/chart.js +4 -0
  91. package/dist/charts/dashboard/data-table.js +11 -0
  92. package/dist/charts/dashboard/windows.js +8 -3
  93. package/dist/charts/edge-fade.js +10 -5
  94. package/dist/charts/hover-band.js +16 -11
  95. package/dist/charts/index.js +0 -1
  96. package/dist/charts/motion.js +11 -7
  97. package/dist/charts/primitives/chart-utils.js +12 -12
  98. package/dist/components/copy/clipboard.js +32 -32
  99. package/dist/components/copy/copied.svelte.js +31 -23
  100. package/dist/components/data-table/data-table.js +39 -39
  101. package/dist/components/docs/index.js +4 -0
  102. package/dist/components/docs/scroll-spy.svelte.js +73 -68
  103. package/dist/components/list-page/filter-section.js +4 -1
  104. package/dist/components/list-page/index.js +2 -0
  105. package/dist/components/list-page/list-table.js +7 -2
  106. package/dist/components/list-page/queue-rail.js +14 -0
  107. package/dist/components/list-page/section-host.js +4 -2
  108. package/dist/components/list-page/step.js +4 -3
  109. package/dist/components/list-page/types.js +1 -0
  110. package/dist/components/picker/trigger.js +48 -30
  111. package/dist/components/picker/types.js +1 -0
  112. package/dist/components/segmented/collapse.js +38 -27
  113. package/dist/components/segmented/index.js +8 -0
  114. package/dist/components/segmented/segmented.js +67 -42
  115. package/dist/components/star-rating-input/index.js +3 -1
  116. package/dist/components/table-view/types.js +1 -0
  117. package/dist/components/tags-input/tags.js +81 -69
  118. package/dist/components/theme/index.js +4 -0
  119. package/dist/components/toolbar/index.js +4 -0
  120. package/dist/components/toolbar/toolbar-trigger.js +14 -1
  121. package/dist/editor/anchors.js +17 -13
  122. package/dist/editor/block-id.js +52 -51
  123. package/dist/editor/block-ops.js +108 -80
  124. package/dist/editor/doc-blocks.js +155 -166
  125. package/dist/editor/extensions.js +139 -180
  126. package/dist/editor/index.js +4 -0
  127. package/dist/editor/markdown-test-helpers.js +4 -2
  128. package/dist/editor/markdown.js +420 -408
  129. package/dist/editor/serializer.js +204 -200
  130. package/dist/editor/slash-items.js +89 -101
  131. package/dist/editor/youtube-url.js +25 -20
  132. package/dist/effects/animated-beam/path-calculator.svelte.js +43 -38
  133. package/dist/effects/animated-beam/types.js +1 -0
  134. package/dist/effects/border-beam/css.js +92 -78
  135. package/dist/effects/border-beam/presets.js +1705 -1720
  136. package/dist/effects/border-beam/register-properties.js +43 -33
  137. package/dist/effects/border-beam/types.js +1 -0
  138. package/dist/effects/image-comparison/compare.js +3 -2
  139. package/dist/effects/image-reveal/types.js +1 -0
  140. package/dist/effects/magnetic/magnetic.js +58 -52
  141. package/dist/effects/reveal/observe.js +50 -40
  142. package/dist/effects/reveal/types.js +1 -0
  143. package/dist/effects/shader-gradient/color.js +36 -29
  144. package/dist/effects/shader-gradient/renderer.js +384 -295
  145. package/dist/effects/shader-gradient/shaders.js +31 -0
  146. package/dist/effects/shader-gradient/types.js +1 -0
  147. package/dist/icons/apple-symbol-exports.js +99 -124
  148. package/dist/icons/sf-symbols.js +357 -461
  149. package/dist/icons/trades.js +43 -28
  150. package/dist/inbox/index.js +1 -0
  151. package/dist/inbox/logic.js +126 -122
  152. package/dist/inbox/types.js +43 -43
  153. package/dist/lib/arrive.js +19 -12
  154. package/dist/lib/icon-types.js +1 -0
  155. package/dist/lib/initials.js +16 -10
  156. package/dist/lib/layout.js +5 -0
  157. package/dist/lib/panel.js +13 -0
  158. package/dist/lib/result.js +22 -22
  159. package/dist/lib/sliding-pill.js +59 -44
  160. package/dist/lib/theme-transition.js +43 -43
  161. package/dist/lib/tone.js +31 -24
  162. package/dist/lib/utils.js +3 -1
  163. package/dist/onboarding/define-tours.js +24 -23
  164. package/dist/onboarding/onboarding.svelte.js +16 -12
  165. package/dist/onboarding/pick.js +10 -6
  166. package/dist/onboarding/stores.js +40 -41
  167. package/dist/onboarding/wait.js +24 -23
  168. package/dist/panel/side-panel-types.js +1 -0
  169. package/dist/record/demo-data.js +459 -486
  170. package/dist/record/fields.js +129 -131
  171. package/dist/record/format.js +70 -82
  172. package/dist/record/gutter.js +1 -0
  173. package/dist/record/kinds.js +95 -105
  174. package/dist/record/logic.js +238 -219
  175. package/dist/record/types.js +49 -48
  176. package/dist/shadcn/accordion/index.js +3 -1
  177. package/dist/shadcn/alert/index.js +3 -1
  178. package/dist/shadcn/alert-dialog/index.js +3 -1
  179. package/dist/shadcn/attachment/index.js +3 -1
  180. package/dist/shadcn/avatar/index.js +3 -1
  181. package/dist/shadcn/breadcrumb/index.js +3 -1
  182. package/dist/shadcn/bubble/index.js +3 -1
  183. package/dist/shadcn/button/index.js +3 -1
  184. package/dist/shadcn/calendar/index.js +3 -1
  185. package/dist/shadcn/card/index.js +3 -1
  186. package/dist/shadcn/checkbox/index.js +3 -1
  187. package/dist/shadcn/code-block/index.js +3 -1
  188. package/dist/shadcn/collapsible/index.js +3 -1
  189. package/dist/shadcn/command/index.js +4 -1
  190. package/dist/shadcn/context-menu/index.js +3 -1
  191. package/dist/shadcn/dialog/index.js +3 -1
  192. package/dist/shadcn/dropdown-menu/menu-item.js +40 -20
  193. package/dist/shadcn/empty/index.js +3 -1
  194. package/dist/shadcn/field/index.js +3 -1
  195. package/dist/shadcn/hooks/highlighter.js +77 -75
  196. package/dist/shadcn/hooks/is-mobile.svelte.js +3 -3
  197. package/dist/shadcn/hooks/use-highlighted-code.svelte.js +62 -62
  198. package/dist/shadcn/input/index.js +3 -1
  199. package/dist/shadcn/kbd/index.js +3 -1
  200. package/dist/shadcn/label/index.js +3 -1
  201. package/dist/shadcn/marker/index.js +3 -1
  202. package/dist/shadcn/message/index.js +3 -1
  203. package/dist/shadcn/message-scroller/index.js +3 -1
  204. package/dist/shadcn/popover/index.js +3 -1
  205. package/dist/shadcn/progress/index.js +3 -1
  206. package/dist/shadcn/progress/tone.js +8 -7
  207. package/dist/shadcn/radio-group/index.js +3 -1
  208. package/dist/shadcn/scroll-area/index.js +3 -1
  209. package/dist/shadcn/select/index.js +3 -1
  210. package/dist/shadcn/separator/index.js +3 -1
  211. package/dist/shadcn/sheet/index.js +3 -1
  212. package/dist/shadcn/sidebar/context.svelte.js +42 -28
  213. package/dist/shadcn/sidebar/index.js +3 -1
  214. package/dist/shadcn/skeleton/index.js +3 -1
  215. package/dist/shadcn/slider/index.js +3 -1
  216. package/dist/shadcn/switch/index.js +3 -1
  217. package/dist/shadcn/table/index.js +3 -1
  218. package/dist/shadcn/tabs/index.js +3 -1
  219. package/dist/shadcn/textarea/index.js +3 -1
  220. package/dist/shadcn/toggle/index.js +3 -1
  221. package/dist/shadcn/toggle-group/index.js +3 -1
  222. package/dist/shadcn/tooltip/context.js +7 -2
  223. package/dist/shadcn/tooltip/index.js +3 -1
  224. package/dist/shadcn/trace/index.js +3 -1
  225. package/dist/slides/bridges.js +65 -59
  226. package/dist/slides/deck-controller.svelte.js +210 -207
  227. package/dist/slides/export/capture.js +66 -71
  228. package/dist/slides/export/ffmpeg.js +76 -72
  229. package/dist/slides/export/index.js +3 -0
  230. package/dist/slides/export/launch.js +9 -6
  231. package/dist/slides/export/pdf.js +60 -54
  232. package/dist/slides/export/types.js +1 -0
  233. package/dist/slides/labels.js +24 -24
  234. package/dist/slides/layout.js +39 -41
  235. package/dist/slides/model.js +9 -7
  236. package/dist/slides/navigation.js +78 -73
  237. package/dist/slides/types.js +2 -2
  238. package/dist/status/define-statuses.js +18 -14
  239. package/dist/status/status-types.js +1 -0
  240. package/dist/test-setup.js +24 -20
  241. package/dist/thread/logic.js +73 -77
  242. package/dist/thread/types.js +21 -21
  243. package/dist/work/board-order.js +94 -90
  244. package/dist/work/dates.js +16 -9
  245. package/dist/work/detail/detail-types.js +18 -18
  246. package/dist/work/docs/edited.js +32 -29
  247. package/dist/work/docs/index.js +4 -0
  248. package/dist/work/docs/labels.js +34 -34
  249. package/dist/work/docs/menu.js +113 -106
  250. package/dist/work/docs/outline.js +39 -29
  251. package/dist/work/gantt/logic.js +211 -235
  252. package/dist/work/inbox/inbox-logic.js +71 -75
  253. package/dist/work/inbox/inbox-statuses.js +75 -72
  254. package/dist/work/inbox/inbox-types.js +1 -0
  255. package/dist/work/kanban-drag.js +27 -22
  256. package/dist/work/kanban-types.js +1 -0
  257. package/dist/work/presets/sales.js +36 -32
  258. package/dist/work/reorder.js +9 -8
  259. package/dist/work/task-types.js +1 -0
  260. package/dist/work/time/duration.js +51 -46
  261. package/dist/work/time/time-types.js +23 -23
  262. package/dist/work/use-kanban-dnd.svelte.js +126 -125
  263. package/package.json +3 -1
  264. package/src/components/list-page/master-detail.svelte +3 -1
  265. package/src/components/list-page/rail-row.svelte +4 -4
  266. package/src/editor/markdown.ts +30 -35
@@ -1,140 +1,127 @@
1
+ // Pure edits on a screen's parts, so the card and the CLI op change a screen the same way.
2
+ // Each function returns a new list.
1
3
  import { MAX_LABEL, MAX_LIST_ITEMS, MAX_PARTS, PART_DEFAULTS, PART_KINDS, SCREEN_MODES, SCREEN_NODE, SCREEN_WIDTH } from "./types.js";
2
- const isKind = (value)=>typeof value === "string" && PART_KINDS.includes(value);
3
- const text = (value, fallback = "")=>typeof value === "string" ? value.slice(0, MAX_LABEL) : fallback;
4
+ const isKind = (value) => typeof value === "string" && PART_KINDS.includes(value);
5
+ const text = (value, fallback = "") => typeof value === "string" ? value.slice(0, MAX_LABEL) : fallback;
6
+ /** The next id no part of this screen holds: p1, p2, and so on. */
4
7
  export function nextPartId(parts) {
5
- const taken = new Set(parts.map((part)=>part.id));
6
- let n = parts.length + 1;
7
- while(taken.has(`p${n}`))n += 1;
8
- return `p${n}`;
8
+ const taken = new Set(parts.map((part) => part.id));
9
+ let n = parts.length + 1;
10
+ while (taken.has(`p${n}`)) n += 1;
11
+ return `p${n}`;
9
12
  }
13
+ /** A part of this kind with its starting words. */
10
14
  export function createPart(kind, parts, seed = {}) {
11
- const base = PART_DEFAULTS[kind];
12
- const part = {
13
- ...base,
14
- ...seed,
15
- id: nextPartId(parts),
16
- kind
17
- };
18
- if (part.items) part.items = [
19
- ...part.items
20
- ];
21
- return part;
15
+ const base = PART_DEFAULTS[kind];
16
+ const part = {
17
+ ...base,
18
+ ...seed,
19
+ id: nextPartId(parts),
20
+ kind
21
+ };
22
+ if (part.items) part.items = [...part.items];
23
+ return part;
22
24
  }
25
+ /** A stored id kept when it is a new string, else the next free one. */
23
26
  function uniquePartId(raw, parts, seen) {
24
- const id = typeof raw === "string" && raw ? raw : "";
25
- const unique = !id || seen.has(id) ? nextPartId(parts) : id;
26
- seen.add(unique);
27
- return unique;
27
+ const id = typeof raw === "string" && raw ? raw : "";
28
+ const unique = !id || seen.has(id) ? nextPartId(parts) : id;
29
+ seen.add(unique);
30
+ return unique;
28
31
  }
32
+ /** What only one kind of part carries: a list's rows, a modal's body, a button's weight. */
29
33
  function kindFields(kind, part) {
30
- if (kind === "list") {
31
- const items = Array.isArray(part.items) ? part.items : PART_DEFAULTS.list.items;
32
- return {
33
- items: (items ?? []).slice(0, MAX_LIST_ITEMS).map((item)=>text(item))
34
- };
35
- }
36
- if (kind === "modal") return {
37
- text: text(part.text, PART_DEFAULTS.modal.text)
38
- };
39
- if (kind === "button") return {
40
- variant: part.variant === "secondary" ? "secondary" : "primary"
41
- };
42
- return {};
34
+ if (kind === "list") {
35
+ const items = Array.isArray(part.items) ? part.items : PART_DEFAULTS.list.items;
36
+ return { items: (items ?? []).slice(0, MAX_LIST_ITEMS).map((item) => text(item)) };
37
+ }
38
+ if (kind === "modal") return { text: text(part.text, PART_DEFAULTS.modal.text) };
39
+ if (kind === "button") return { variant: part.variant === "secondary" ? "secondary" : "primary" };
40
+ return {};
43
41
  }
42
+ /** One stored part as a part that draws, or null when its kind is not one we know. */
44
43
  function normalizePart(entry, parts, seen) {
45
- const part = entry ?? {};
46
- if (!isKind(part.kind)) return null;
47
- const kind = part.kind;
48
- const id = uniquePartId(part.id, parts, seen);
49
- return {
50
- id,
51
- kind,
52
- label: text(part.label, PART_DEFAULTS[kind].label),
53
- ...kindFields(kind, part)
54
- };
44
+ const part = entry ?? {};
45
+ if (!isKind(part.kind)) return null;
46
+ const kind = part.kind;
47
+ const id = uniquePartId(part.id, parts, seen);
48
+ return {
49
+ id,
50
+ kind,
51
+ label: text(part.label, PART_DEFAULTS[kind].label),
52
+ ...kindFields(kind, part)
53
+ };
55
54
  }
55
+ /** A screen as stored may be old, hand-written or half-typed: this one always draws. */
56
56
  export function normalizeScreen(data) {
57
- const raw = data ?? {};
58
- const seen = new Set();
59
- const parts = [];
60
- const rawParts = Array.isArray(raw.parts) ? raw.parts : [];
61
- for (const entry of rawParts.slice(0, MAX_PARTS)){
62
- const next = normalizePart(entry, parts, seen);
63
- if (next) parts.push(next);
64
- }
65
- return {
66
- label: text(raw.label),
67
- mode: SCREEN_MODES.includes(raw.mode) ? raw.mode : "wireframe",
68
- parts
69
- };
57
+ const raw = data ?? {};
58
+ const seen = new Set();
59
+ const parts = [];
60
+ const rawParts = Array.isArray(raw.parts) ? raw.parts : [];
61
+ for (const entry of rawParts.slice(0, MAX_PARTS)) {
62
+ const next = normalizePart(entry, parts, seen);
63
+ if (next) parts.push(next);
64
+ }
65
+ return {
66
+ label: text(raw.label),
67
+ mode: SCREEN_MODES.includes(raw.mode) ? raw.mode : "wireframe",
68
+ parts
69
+ };
70
70
  }
71
71
  export function addPart(parts, kind, seed, index = parts.length) {
72
- if (parts.length >= MAX_PARTS) return [
73
- ...parts
74
- ];
75
- const at = Math.max(0, Math.min(index, parts.length));
76
- return [
77
- ...parts.slice(0, at),
78
- createPart(kind, parts, seed),
79
- ...parts.slice(at)
80
- ];
72
+ if (parts.length >= MAX_PARTS) return [...parts];
73
+ const at = Math.max(0, Math.min(index, parts.length));
74
+ return [
75
+ ...parts.slice(0, at),
76
+ createPart(kind, parts, seed),
77
+ ...parts.slice(at)
78
+ ];
81
79
  }
82
80
  export function removePart(parts, id) {
83
- return parts.filter((part)=>part.id !== id);
81
+ return parts.filter((part) => part.id !== id);
84
82
  }
83
+ /** One step up (-1) or down (1). The ends stay put. */
85
84
  export function movePart(parts, id, step) {
86
- const from = parts.findIndex((part)=>part.id === id);
87
- const to = from + step;
88
- if (from < 0 || to < 0 || to >= parts.length) return [
89
- ...parts
90
- ];
91
- const next = [
92
- ...parts
93
- ];
94
- [next[from], next[to]] = [
95
- next[to],
96
- next[from]
97
- ];
98
- return next;
85
+ const from = parts.findIndex((part) => part.id === id);
86
+ const to = from + step;
87
+ if (from < 0 || to < 0 || to >= parts.length) return [...parts];
88
+ const next = [...parts];
89
+ [next[from], next[to]] = [next[to], next[from]];
90
+ return next;
99
91
  }
100
92
  export function patchPart(parts, id, patch) {
101
- return parts.map((part)=>part.id === id ? {
102
- ...part,
103
- ...patch
104
- } : part);
93
+ return parts.map((part) => part.id === id ? {
94
+ ...part,
95
+ ...patch
96
+ } : part);
105
97
  }
98
+ /** A list row's words. Rows are added and cut at the end, never reordered. */
106
99
  export function setItem(items, index, value) {
107
- return items.map((item, i)=>i === index ? value : item);
100
+ return items.map((item, i) => i === index ? value : item);
108
101
  }
109
102
  export function addItem(items) {
110
- return items.length >= MAX_LIST_ITEMS ? [
111
- ...items
112
- ] : [
113
- ...items,
114
- "Item"
115
- ];
103
+ return items.length >= MAX_LIST_ITEMS ? [...items] : [...items, "Item"];
116
104
  }
117
105
  export function removeItem(items, index) {
118
- return items.filter((_, i)=>i !== index);
106
+ return items.filter((_, i) => i !== index);
119
107
  }
108
+ /** A ready node for a board, as the CLI and the palette both build it. */
120
109
  export function buildScreenNode(options) {
121
- let parts = [];
122
- for (const entry of options.parts ?? []){
123
- const { kind, ...seed } = entry;
124
- parts = addPart(parts, kind, seed);
125
- }
126
- const data = normalizeScreen({
127
- label: options.label,
128
- mode: options.mode,
129
- parts
130
- });
131
- return {
132
- id: options.id,
133
- type: SCREEN_NODE,
134
- position: options.position,
135
- data,
136
- style: {
137
- width: options.width ?? SCREEN_WIDTH
138
- }
139
- };
110
+ let parts = [];
111
+ for (const entry of options.parts ?? []) {
112
+ const { kind, ...seed } = entry;
113
+ parts = addPart(parts, kind, seed);
114
+ }
115
+ const data = normalizeScreen({
116
+ label: options.label,
117
+ mode: options.mode,
118
+ parts
119
+ });
120
+ return {
121
+ id: options.id,
122
+ type: SCREEN_NODE,
123
+ position: options.position,
124
+ data,
125
+ style: { width: options.width ?? SCREEN_WIDTH }
126
+ };
140
127
  }
@@ -1,71 +1,62 @@
1
+ // The Screen card's kind and its add op, with no DOM, so the CLI can put a screen on a board.
2
+ // ui.ts adds the renderer.
1
3
  import { z } from "zod";
2
4
  import { CanvasOpError } from "../ops/ops.js";
3
5
  import { definePlugin } from "../plugin.js";
4
6
  import { buildScreenNode } from "./parts.js";
5
7
  import { MAX_LABEL, MAX_LIST_ITEMS, MAX_PARTS, PART_KINDS, SCREEN_MODES, SCREEN_NODE, SCREEN_WIDTH } from "./types.js";
6
8
  const partSchema = z.object({
7
- kind: z.enum(PART_KINDS),
8
- label: z.string().max(MAX_LABEL).optional(),
9
- items: z.array(z.string().max(MAX_LABEL)).max(MAX_LIST_ITEMS).optional(),
10
- text: z.string().max(MAX_LABEL).optional(),
11
- variant: z.enum([
12
- "primary",
13
- "secondary"
14
- ]).optional()
9
+ kind: z.enum(PART_KINDS),
10
+ label: z.string().max(MAX_LABEL).optional(),
11
+ items: z.array(z.string().max(MAX_LABEL)).max(MAX_LIST_ITEMS).optional(),
12
+ text: z.string().max(MAX_LABEL).optional(),
13
+ variant: z.enum(["primary", "secondary"]).optional()
15
14
  });
16
15
  const addScreenOp = z.object({
17
- kind: z.literal("addScreen"),
18
- id: z.string().min(1).optional(),
19
- at: z.object({
20
- x: z.number(),
21
- y: z.number()
22
- }),
23
- label: z.string().max(MAX_LABEL).optional(),
24
- mode: z.enum(SCREEN_MODES).optional(),
25
- parts: z.array(partSchema).max(MAX_PARTS).optional(),
26
- width: z.number().positive().optional()
16
+ kind: z.literal("addScreen"),
17
+ id: z.string().min(1).optional(),
18
+ at: z.object({
19
+ x: z.number(),
20
+ y: z.number()
21
+ }),
22
+ label: z.string().max(MAX_LABEL).optional(),
23
+ mode: z.enum(SCREEN_MODES).optional(),
24
+ parts: z.array(partSchema).max(MAX_PARTS).optional(),
25
+ width: z.number().positive().optional()
27
26
  });
28
27
  function applyAddScreen(state, op, opIndex) {
29
- const id = op.id ?? crypto.randomUUID();
30
- if (state.nodes.some((node)=>node.id === id)) {
31
- throw new CanvasOpError(`Node id already exists: ${id}`, opIndex);
32
- }
33
- const node = buildScreenNode({
34
- id,
35
- position: op.at,
36
- label: op.label,
37
- mode: op.mode,
38
- parts: op.parts,
39
- width: op.width
40
- });
41
- state.nodes = [
42
- ...state.nodes,
43
- node
44
- ];
28
+ const id = op.id ?? crypto.randomUUID();
29
+ if (state.nodes.some((node) => node.id === id)) {
30
+ throw new CanvasOpError(`Node id already exists: ${id}`, opIndex);
31
+ }
32
+ const node = buildScreenNode({
33
+ id,
34
+ position: op.at,
35
+ label: op.label,
36
+ mode: op.mode,
37
+ parts: op.parts,
38
+ width: op.width
39
+ });
40
+ state.nodes = [...state.nodes, node];
45
41
  }
42
+ /** Content-sized: the parts decide the height, so a layout never pins a stale one. */
46
43
  export const screenKind = {
47
- type: SCREEN_NODE,
48
- label: "Screen",
49
- sizing: "content-sized",
50
- size: {
51
- width: SCREEN_WIDTH
52
- },
53
- createData: ()=>({
54
- label: "",
55
- mode: "wireframe",
56
- parts: []
57
- })
44
+ type: SCREEN_NODE,
45
+ label: "Screen",
46
+ sizing: "content-sized",
47
+ size: { width: SCREEN_WIDTH },
48
+ createData: () => ({
49
+ label: "",
50
+ mode: "wireframe",
51
+ parts: []
52
+ })
58
53
  };
59
54
  export const screenPlugin = definePlugin({
60
- id: "screen",
61
- nodes: [
62
- screenKind
63
- ],
64
- ops: [
65
- {
66
- kind: "addScreen",
67
- schema: addScreenOp,
68
- apply: applyAddScreen
69
- }
70
- ]
55
+ id: "screen",
56
+ nodes: [screenKind],
57
+ ops: [{
58
+ kind: "addScreen",
59
+ schema: addScreenOp,
60
+ apply: applyAddScreen
61
+ }]
71
62
  });
@@ -1,44 +1,39 @@
1
+ // The Screen card's data shape: a stack of kit parts drawn as a wireframe or a mockup.
1
2
  export const SCREEN_NODE = "screen";
3
+ /** Card width before anyone resizes it. The height follows the parts. */
2
4
  export const SCREEN_WIDTH = 320;
3
5
  export const PART_KINDS = [
4
- "header",
5
- "button",
6
- "input",
7
- "image",
8
- "list",
9
- "modal"
10
- ];
11
- export const SCREEN_MODES = [
12
- "wireframe",
13
- "mockup"
6
+ "header",
7
+ "button",
8
+ "input",
9
+ "image",
10
+ "list",
11
+ "modal"
14
12
  ];
13
+ export const SCREEN_MODES = ["wireframe", "mockup"];
14
+ /** A board holds screens of a handful of parts. One past this is a paste from a file. */
15
15
  export const MAX_PARTS = 24;
16
16
  export const MAX_LIST_ITEMS = 12;
17
17
  export const MAX_LABEL = 120;
18
+ /** What a new part of each kind starts with. Words are labels, never sentences. */
18
19
  export const PART_DEFAULTS = {
19
- header: {
20
- label: "Title"
21
- },
22
- button: {
23
- label: "Button",
24
- variant: "primary"
25
- },
26
- input: {
27
- label: "Label"
28
- },
29
- image: {
30
- label: "Image"
31
- },
32
- list: {
33
- label: "List",
34
- items: [
35
- "Item",
36
- "Item",
37
- "Item"
38
- ]
39
- },
40
- modal: {
41
- label: "Title",
42
- text: "Text"
43
- }
20
+ header: { label: "Title" },
21
+ button: {
22
+ label: "Button",
23
+ variant: "primary"
24
+ },
25
+ input: { label: "Label" },
26
+ image: { label: "Image" },
27
+ list: {
28
+ label: "List",
29
+ items: [
30
+ "Item",
31
+ "Item",
32
+ "Item"
33
+ ]
34
+ },
35
+ modal: {
36
+ label: "Title",
37
+ text: "Text"
38
+ }
44
39
  };
@@ -1,13 +1,13 @@
1
+ // The browser registers `screenUiPlugin`, and a server registers `screenPlugin`.
2
+ // Never both, because a kind has one owner.
1
3
  import { definePlugin } from "../plugin.js";
2
4
  import { screenKind, screenPlugin } from "./plugin.js";
3
5
  import ScreenCard from "../../../src/canvas/screen/ScreenCard.svelte";
4
6
  export { ScreenCard };
5
7
  export const screenUiPlugin = definePlugin({
6
- ...screenPlugin,
7
- nodes: [
8
- {
9
- ...screenKind,
10
- component: ScreenCard
11
- }
12
- ]
8
+ ...screenPlugin,
9
+ nodes: [{
10
+ ...screenKind,
11
+ component: ScreenCard
12
+ }]
13
13
  });
@@ -1,18 +1,18 @@
1
+ /** A node for tests. Overrides win. */
1
2
  export function makeNode(overrides = {}) {
2
- return {
3
- id: overrides.id ?? `node-${Math.random().toString(36).slice(2, 8)}`,
4
- type: "node",
5
- position: {
6
- x: 0,
7
- y: 0
8
- },
9
- data: {
10
- label: "Test Node"
11
- },
12
- ...overrides
13
- };
3
+ return {
4
+ id: overrides.id ?? `node-${Math.random().toString(36).slice(2, 8)}`,
5
+ type: "node",
6
+ position: {
7
+ x: 0,
8
+ y: 0
9
+ },
10
+ data: { label: "Test Node" },
11
+ ...overrides
12
+ };
14
13
  }
14
+ /** Narrows a lookup in a test so a miss fails with a name, not a TypeError. */
15
15
  export function expectDefined(value, what = "value") {
16
- if (value === null || value === undefined) throw new Error(`Expected ${what} to be defined`);
17
- return value;
16
+ if (value === null || value === undefined) throw new Error(`Expected ${what} to be defined`);
17
+ return value;
18
18
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,27 +1,26 @@
1
+ // An overlay above xyflow's zoom pane never sees a wheel or a pinch, so it hands them down.
1
2
  export function forwardWheel(node) {
2
- const handler = (event)=>{
3
- const zoomPane = node.closest(".svelte-flow")?.querySelector(".svelte-flow__zoom");
4
- if (!zoomPane) return;
5
- event.preventDefault();
6
- zoomPane.dispatchEvent(new WheelEvent("wheel", {
7
- deltaX: event.deltaX,
8
- deltaY: event.deltaY,
9
- deltaZ: event.deltaZ,
10
- deltaMode: event.deltaMode,
11
- clientX: event.clientX,
12
- clientY: event.clientY,
13
- screenX: event.screenX,
14
- screenY: event.screenY,
15
- ctrlKey: event.ctrlKey,
16
- shiftKey: event.shiftKey,
17
- altKey: event.altKey,
18
- metaKey: event.metaKey,
19
- bubbles: true,
20
- cancelable: true
21
- }));
22
- };
23
- node.addEventListener("wheel", handler, {
24
- passive: false
25
- });
26
- return ()=>node.removeEventListener("wheel", handler);
3
+ const handler = (event) => {
4
+ const zoomPane = node.closest(".svelte-flow")?.querySelector(".svelte-flow__zoom");
5
+ if (!zoomPane) return;
6
+ event.preventDefault();
7
+ zoomPane.dispatchEvent(new WheelEvent("wheel", {
8
+ deltaX: event.deltaX,
9
+ deltaY: event.deltaY,
10
+ deltaZ: event.deltaZ,
11
+ deltaMode: event.deltaMode,
12
+ clientX: event.clientX,
13
+ clientY: event.clientY,
14
+ screenX: event.screenX,
15
+ screenY: event.screenY,
16
+ ctrlKey: event.ctrlKey,
17
+ shiftKey: event.shiftKey,
18
+ altKey: event.altKey,
19
+ metaKey: event.metaKey,
20
+ bubbles: true,
21
+ cancelable: true
22
+ }));
23
+ };
24
+ node.addEventListener("wheel", handler, { passive: false });
25
+ return () => node.removeEventListener("wheel", handler);
27
26
  }