@heyramzi/ui 2.9.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. package/dist/agents/helpers.js +52 -0
  2. package/dist/agents/index.js +3 -0
  3. package/dist/agents/page-state.js +65 -0
  4. package/dist/agents/types.js +1 -0
  5. package/dist/agents/vendor/color.js +149 -0
  6. package/dist/agents/vendor/draw.js +548 -0
  7. package/dist/agents/vendor/engine.js +632 -0
  8. package/dist/agents/vendor/mesh.js +727 -0
  9. package/dist/agents/vendor/plastic.js +3273 -0
  10. package/dist/agents/vendor/presets.js +171 -0
  11. package/dist/agents/vendor/shapes.js +24 -0
  12. package/dist/agents/vendor/ticker.js +56 -0
  13. package/dist/agents/vendor/types.js +0 -0
  14. package/dist/agents/vendor/wear.js +1525 -0
  15. package/dist/ai/ai-button/index.js +2 -0
  16. package/dist/ai/confirmation/confirmation-context.svelte.js +12 -0
  17. package/dist/ai/confirmation/index.js +9 -0
  18. package/dist/ai/generation-progress/index.js +2 -0
  19. package/dist/ai/index.js +11 -0
  20. package/dist/ai/loading-state/index.js +3 -0
  21. package/dist/ai/prompt-input/index.js +6 -0
  22. package/dist/ai/reasoning/index.js +4 -0
  23. package/dist/ai/reasoning/reasoning-context.svelte.js +12 -0
  24. package/dist/ai/response/index.js +3 -0
  25. package/dist/ai/suggestion/index.js +3 -0
  26. package/dist/ai/thinking-dots/index.js +3 -0
  27. package/dist/ai/typing-dots/index.js +2 -0
  28. package/dist/ai/voice-waveform/index.js +3 -0
  29. package/dist/animations/text-swap.js +30 -0
  30. package/dist/brand/index.js +65 -0
  31. package/dist/canvas/card/resize.js +10 -0
  32. package/dist/canvas/edges/edge-path.js +284 -0
  33. package/dist/canvas/editor/context-menu.js +42 -0
  34. package/dist/canvas/editor/dispatch.svelte.js +157 -0
  35. package/dist/canvas/editor/editor-context.js +8 -0
  36. package/dist/canvas/editor/editor-mode.js +0 -0
  37. package/dist/canvas/editor/frame.js +87 -0
  38. package/dist/canvas/editor/hand-context.js +8 -0
  39. package/dist/canvas/editor/history-core.js +221 -0
  40. package/dist/canvas/editor/keymap.js +193 -0
  41. package/dist/canvas/editor/layout-actions.js +170 -0
  42. package/dist/canvas/editor/lock.js +65 -0
  43. package/dist/canvas/editor/rebase.js +279 -0
  44. package/dist/canvas/editor/style.js +174 -0
  45. package/dist/canvas/editor/text-field-context.js +8 -0
  46. package/dist/canvas/editor/z-order.js +82 -0
  47. package/dist/canvas/headless/alignment.js +20 -0
  48. package/dist/canvas/headless/break-apart-find.js +324 -0
  49. package/dist/canvas/headless/break-apart-pieces.js +74 -0
  50. package/dist/canvas/headless/break-apart-plan.js +378 -0
  51. package/dist/canvas/headless/break-apart-style.js +93 -0
  52. package/dist/canvas/headless/break-apart.js +206 -0
  53. package/dist/canvas/headless/canvas-cleanup.js +70 -0
  54. package/dist/canvas/headless/edge-anchors.js +134 -0
  55. package/dist/canvas/headless/edge-memo.js +28 -0
  56. package/dist/canvas/headless/edge-serialization.js +31 -0
  57. package/dist/canvas/headless/figure-geometry.js +331 -0
  58. package/dist/canvas/headless/fit-viewport.js +82 -0
  59. package/dist/canvas/headless/grid.js +96 -0
  60. package/dist/canvas/headless/icon-node.js +45 -0
  61. package/dist/canvas/headless/index.js +1 -0
  62. package/dist/canvas/headless/linkify.js +25 -0
  63. package/dist/canvas/headless/pen-marks.js +115 -0
  64. package/dist/canvas/headless/sketch.js +250 -0
  65. package/dist/canvas/headless/snap-guides.js +100 -0
  66. package/dist/canvas/headless/svg-figure.js +137 -0
  67. package/dist/canvas/headless/table-layout.js +161 -0
  68. package/dist/canvas/index.js +25 -0
  69. package/dist/canvas/lod/lod-mode.svelte.js +22 -0
  70. package/dist/canvas/lod/render-all.svelte.js +45 -0
  71. package/dist/canvas/ops/arrange.js +83 -0
  72. package/dist/canvas/ops/ops.js +318 -0
  73. package/dist/canvas/pen/colors.js +41 -0
  74. package/dist/canvas/pen/eraser.js +35 -0
  75. package/dist/canvas/pen/geometry.js +143 -0
  76. package/dist/canvas/pen/index.js +9 -0
  77. package/dist/canvas/pen/ops.js +15 -0
  78. package/dist/canvas/pen/pen-session.js +171 -0
  79. package/dist/canvas/pen/plugin.js +129 -0
  80. package/dist/canvas/pen/shapes.js +80 -0
  81. package/dist/canvas/pen/stroke-path.js +37 -0
  82. package/dist/canvas/pen/types.js +30 -0
  83. package/dist/canvas/pen/ui.js +20 -0
  84. package/dist/canvas/plugin.js +51 -0
  85. package/dist/canvas/screen/glyphs.js +24 -0
  86. package/dist/canvas/screen/labels.js +24 -0
  87. package/dist/canvas/screen/parts.js +140 -0
  88. package/dist/canvas/screen/plugin.js +71 -0
  89. package/dist/canvas/screen/types.js +44 -0
  90. package/dist/canvas/screen/ui.js +13 -0
  91. package/dist/canvas/test-utils.js +18 -0
  92. package/dist/canvas/types.js +0 -0
  93. package/dist/canvas/ui/forward-wheel.js +27 -0
  94. package/dist/canvas/ui/icons.js +133 -0
  95. package/dist/canvas/ui/place-panel.js +57 -0
  96. package/dist/canvas/ui/shortcut-tip.js +18 -0
  97. package/dist/canvas/ui/tools.js +411 -0
  98. package/dist/charts/dashboard/chart.js +1 -0
  99. package/dist/charts/dashboard/data-table.js +7 -0
  100. package/dist/charts/dashboard/index.js +13 -0
  101. package/dist/charts/dashboard/windows.js +5 -0
  102. package/dist/charts/edge-fade.js +7 -0
  103. package/dist/charts/hover-band.js +13 -0
  104. package/dist/charts/index.js +19 -0
  105. package/dist/charts/motion.js +15 -0
  106. package/dist/charts/primitives/chart-utils.js +22 -0
  107. package/dist/charts/primitives/index.js +4 -0
  108. package/dist/components/copy/clipboard.js +38 -0
  109. package/dist/components/copy/copied.svelte.js +26 -0
  110. package/dist/components/copy/index.js +3 -0
  111. package/dist/components/data-table/data-table.js +55 -0
  112. package/dist/components/data-table/index.js +7 -0
  113. package/dist/components/docs/index.js +3 -0
  114. package/dist/components/docs/scroll-spy.svelte.js +71 -0
  115. package/dist/components/field-row/index.js +1 -0
  116. package/dist/components/hold-to-confirm/index.js +1 -0
  117. package/dist/components/icon/index.js +1 -0
  118. package/dist/components/language-flag/index.js +1 -0
  119. package/dist/components/list-page/filter-section.js +4 -0
  120. package/dist/components/list-page/index.js +25 -0
  121. package/dist/components/list-page/list-table.js +5 -0
  122. package/dist/components/list-page/queue-rail.js +3 -0
  123. package/dist/components/list-page/section-host.js +8 -0
  124. package/dist/components/list-page/step.js +5 -0
  125. package/dist/components/list-page/types.js +0 -0
  126. package/dist/components/locale-switch/index.js +1 -0
  127. package/dist/components/mark/index.js +1 -0
  128. package/dist/components/open-in/index.js +1 -0
  129. package/dist/components/picker/index.js +3 -0
  130. package/dist/components/picker/trigger.js +33 -0
  131. package/dist/components/picker/types.js +0 -0
  132. package/dist/components/section-card/index.js +1 -0
  133. package/dist/components/section-header/index.js +2 -0
  134. package/dist/components/segmented/collapse.js +32 -0
  135. package/dist/components/segmented/index.js +8 -0
  136. package/dist/components/segmented/segmented.js +50 -0
  137. package/dist/components/star-rating-input/index.js +2 -0
  138. package/dist/components/svg/index.js +1 -0
  139. package/dist/components/table-view/index.js +1 -0
  140. package/dist/components/table-view/types.js +0 -0
  141. package/dist/components/tags-input/index.js +2 -0
  142. package/dist/components/tags-input/tags.js +90 -0
  143. package/dist/components/theme/index.js +3 -0
  144. package/dist/components/toolbar/index.js +3 -0
  145. package/dist/components/toolbar/toolbar-trigger.js +4 -0
  146. package/dist/editor/anchors.js +17 -0
  147. package/dist/editor/block-id.js +62 -0
  148. package/dist/editor/block-ops.js +105 -0
  149. package/dist/editor/doc-blocks.js +181 -0
  150. package/dist/editor/extensions.js +200 -0
  151. package/dist/editor/index.js +4 -0
  152. package/dist/editor/markdown-test-helpers.js +6 -0
  153. package/dist/editor/markdown.js +486 -0
  154. package/dist/editor/serializer.js +268 -0
  155. package/dist/editor/slash-items.js +104 -0
  156. package/dist/editor/youtube-url.js +27 -0
  157. package/dist/effects/animated-beam/index.js +1 -0
  158. package/dist/effects/animated-beam/path-calculator.svelte.js +42 -0
  159. package/dist/effects/animated-beam/types.js +0 -0
  160. package/dist/effects/border-beam/css.js +420 -0
  161. package/dist/effects/border-beam/presets.js +1792 -0
  162. package/dist/effects/border-beam/register-properties.js +39 -0
  163. package/dist/effects/border-beam/types.js +0 -0
  164. package/dist/effects/image-comparison/compare.js +4 -0
  165. package/dist/effects/image-reveal/index.js +1 -0
  166. package/dist/effects/image-reveal/types.js +0 -0
  167. package/dist/effects/magnetic/magnetic.js +54 -0
  168. package/dist/effects/reveal/index.js +4 -0
  169. package/dist/effects/reveal/observe.js +43 -0
  170. package/dist/effects/reveal/types.js +0 -0
  171. package/dist/effects/shader-gradient/color.js +34 -0
  172. package/dist/effects/shader-gradient/index.js +1 -0
  173. package/dist/effects/shader-gradient/renderer.js +320 -0
  174. package/dist/effects/shader-gradient/shaders.js +280 -0
  175. package/dist/effects/shader-gradient/types.js +0 -0
  176. package/dist/icons/apple-symbol-exports.js +126 -0
  177. package/dist/icons/sf-symbols.js +465 -0
  178. package/dist/icons/trades.js +34 -0
  179. package/dist/inbox/index.js +4 -0
  180. package/dist/inbox/logic.js +156 -0
  181. package/dist/inbox/types.js +46 -0
  182. package/dist/index.js +18 -0
  183. package/dist/lib/arrive.js +13 -0
  184. package/dist/lib/icon-types.js +0 -0
  185. package/dist/lib/initials.js +17 -0
  186. package/dist/lib/layout.js +1 -0
  187. package/dist/lib/panel.js +3 -0
  188. package/dist/lib/result.js +26 -0
  189. package/dist/lib/sliding-pill.js +45 -0
  190. package/dist/lib/theme-transition.js +53 -0
  191. package/dist/lib/tone.js +32 -0
  192. package/dist/lib/utils.js +5 -0
  193. package/dist/onboarding/define-tours.js +28 -0
  194. package/dist/onboarding/index.js +4 -0
  195. package/dist/onboarding/onboarding.svelte.js +15 -0
  196. package/dist/onboarding/pick.js +16 -0
  197. package/dist/onboarding/stores.js +50 -0
  198. package/dist/onboarding/types.js +1 -0
  199. package/dist/onboarding/wait.js +25 -0
  200. package/dist/panel/index.js +1 -0
  201. package/dist/panel/side-panel-types.js +0 -0
  202. package/dist/record/demo-data.js +512 -0
  203. package/dist/record/fields.js +148 -0
  204. package/dist/record/format.js +97 -0
  205. package/dist/record/gutter.js +1 -0
  206. package/dist/record/index.js +15 -0
  207. package/dist/record/kinds.js +110 -0
  208. package/dist/record/logic.js +255 -0
  209. package/dist/record/types.js +52 -0
  210. package/dist/shadcn/accordion/index.js +5 -0
  211. package/dist/shadcn/alert/index.js +5 -0
  212. package/dist/shadcn/alert-dialog/index.js +12 -0
  213. package/dist/shadcn/attachment/index.js +10 -0
  214. package/dist/shadcn/avatar/index.js +7 -0
  215. package/dist/shadcn/badge/index.js +2 -0
  216. package/dist/shadcn/breadcrumb/index.js +8 -0
  217. package/dist/shadcn/bubble/index.js +5 -0
  218. package/dist/shadcn/button/index.js +2 -0
  219. package/dist/shadcn/calendar/index.js +19 -0
  220. package/dist/shadcn/card/index.js +8 -0
  221. package/dist/shadcn/checkbox/index.js +2 -0
  222. package/dist/shadcn/code-block/index.js +9 -0
  223. package/dist/shadcn/collapsible/index.js +4 -0
  224. package/dist/shadcn/command/index.js +13 -0
  225. package/dist/shadcn/context-menu/index.js +17 -0
  226. package/dist/shadcn/dialog/index.js +11 -0
  227. package/dist/shadcn/dropdown-menu/index.js +19 -0
  228. package/dist/shadcn/dropdown-menu/menu-item.js +23 -0
  229. package/dist/shadcn/empty/index.js +7 -0
  230. package/dist/shadcn/field/index.js +12 -0
  231. package/dist/shadcn/hooks/highlighter.js +92 -0
  232. package/dist/shadcn/hooks/is-mobile.svelte.js +7 -0
  233. package/dist/shadcn/hooks/use-highlighted-code.svelte.js +65 -0
  234. package/dist/shadcn/hover-card/index.js +5 -0
  235. package/dist/shadcn/input/index.js +3 -0
  236. package/dist/shadcn/input-otp/index.js +5 -0
  237. package/dist/shadcn/kbd/index.js +3 -0
  238. package/dist/shadcn/label/index.js +2 -0
  239. package/dist/shadcn/marker/index.js +4 -0
  240. package/dist/shadcn/message/index.js +7 -0
  241. package/dist/shadcn/message-scroller/index.js +8 -0
  242. package/dist/shadcn/popover/index.js +9 -0
  243. package/dist/shadcn/progress/index.js +2 -0
  244. package/dist/shadcn/progress/tone.js +11 -0
  245. package/dist/shadcn/radio-group/index.js +3 -0
  246. package/dist/shadcn/scroll-area/index.js +3 -0
  247. package/dist/shadcn/select/index.js +12 -0
  248. package/dist/shadcn/separator/index.js +2 -0
  249. package/dist/shadcn/sheet/index.js +11 -0
  250. package/dist/shadcn/sidebar/constants.js +6 -0
  251. package/dist/shadcn/sidebar/context.svelte.js +38 -0
  252. package/dist/shadcn/sidebar/index.js +25 -0
  253. package/dist/shadcn/skeleton/index.js +2 -0
  254. package/dist/shadcn/slider/index.js +2 -0
  255. package/dist/shadcn/sonner/index.js +1 -0
  256. package/dist/shadcn/spinner/index.js +1 -0
  257. package/dist/shadcn/switch/index.js +2 -0
  258. package/dist/shadcn/table/index.js +9 -0
  259. package/dist/shadcn/tabs/index.js +5 -0
  260. package/dist/shadcn/textarea/index.js +2 -0
  261. package/dist/shadcn/toggle/index.js +3 -0
  262. package/dist/shadcn/toggle-group/index.js +3 -0
  263. package/dist/shadcn/tooltip/context.js +8 -0
  264. package/dist/shadcn/tooltip/index.js +6 -0
  265. package/dist/shadcn/trace/index.js +9 -0
  266. package/dist/slides/bridges.js +66 -0
  267. package/dist/slides/deck-controller.svelte.js +221 -0
  268. package/dist/slides/export/capture.js +81 -0
  269. package/dist/slides/export/ffmpeg.js +85 -0
  270. package/dist/slides/export/index.js +4 -0
  271. package/dist/slides/export/launch.js +8 -0
  272. package/dist/slides/export/pdf.js +78 -0
  273. package/dist/slides/export/types.js +0 -0
  274. package/dist/slides/index.js +7 -0
  275. package/dist/slides/labels.js +26 -0
  276. package/dist/slides/layout.js +47 -0
  277. package/dist/slides/model.js +9 -0
  278. package/dist/slides/navigation.js +89 -0
  279. package/dist/slides/types.js +6 -0
  280. package/dist/status/define-statuses.js +16 -0
  281. package/dist/status/index.js +4 -0
  282. package/dist/status/status-types.js +0 -0
  283. package/dist/test-setup.js +26 -0
  284. package/dist/thread/index.js +3 -0
  285. package/dist/thread/logic.js +94 -0
  286. package/dist/thread/types.js +23 -0
  287. package/dist/work/board-order.js +109 -0
  288. package/dist/work/dates.js +19 -0
  289. package/dist/work/detail/detail-types.js +20 -0
  290. package/dist/work/docs/edited.js +39 -0
  291. package/dist/work/docs/index.js +7 -0
  292. package/dist/work/docs/labels.js +38 -0
  293. package/dist/work/docs/menu.js +121 -0
  294. package/dist/work/docs/outline.js +39 -0
  295. package/dist/work/gantt/logic.js +260 -0
  296. package/dist/work/inbox/inbox-logic.js +94 -0
  297. package/dist/work/inbox/inbox-statuses.js +86 -0
  298. package/dist/work/inbox/inbox-types.js +0 -0
  299. package/dist/work/inbox/index.js +1 -0
  300. package/dist/work/index.js +21 -0
  301. package/dist/work/kanban-drag.js +25 -0
  302. package/dist/work/kanban-types.js +0 -0
  303. package/dist/work/presets/sales.js +35 -0
  304. package/dist/work/reorder.js +10 -0
  305. package/dist/work/task-types.js +0 -0
  306. package/dist/work/time/duration.js +60 -0
  307. package/dist/work/time/time-types.js +25 -0
  308. package/dist/work/use-kanban-dnd.svelte.js +128 -0
  309. package/package.json +45 -3
  310. package/src/components/toolbar/toolbar-trigger.ts +8 -2
  311. package/src/record/demo-data.ts +4 -4
  312. package/src/record/record-demo.svelte +2 -2
@@ -0,0 +1,137 @@
1
+ const ALLOWED_TAGS = new Set([
2
+ "svg",
3
+ "g",
4
+ "defs",
5
+ "title",
6
+ "desc",
7
+ "linearGradient",
8
+ "radialGradient",
9
+ "stop",
10
+ "marker",
11
+ "clipPath",
12
+ "path",
13
+ "rect",
14
+ "circle",
15
+ "ellipse",
16
+ "line",
17
+ "polyline",
18
+ "polygon",
19
+ "text",
20
+ "tspan"
21
+ ]);
22
+ const ALLOWED_ATTRS = new Set([
23
+ "viewBox",
24
+ "width",
25
+ "height",
26
+ "x",
27
+ "y",
28
+ "x1",
29
+ "x2",
30
+ "y1",
31
+ "y2",
32
+ "cx",
33
+ "cy",
34
+ "r",
35
+ "rx",
36
+ "ry",
37
+ "d",
38
+ "points",
39
+ "dx",
40
+ "dy",
41
+ "transform",
42
+ "fill",
43
+ "fill-opacity",
44
+ "fill-rule",
45
+ "stroke",
46
+ "stroke-width",
47
+ "stroke-dasharray",
48
+ "stroke-dashoffset",
49
+ "stroke-linecap",
50
+ "stroke-linejoin",
51
+ "stroke-opacity",
52
+ "opacity",
53
+ "font-size",
54
+ "font-weight",
55
+ "font-style",
56
+ "letter-spacing",
57
+ "text-anchor",
58
+ "dominant-baseline",
59
+ "offset",
60
+ "stop-color",
61
+ "stop-opacity",
62
+ "gradientUnits",
63
+ "gradientTransform",
64
+ "clip-path",
65
+ "clipPathUnits",
66
+ "marker-end",
67
+ "marker-start",
68
+ "markerWidth",
69
+ "markerHeight",
70
+ "refX",
71
+ "refY",
72
+ "orient",
73
+ "id",
74
+ "class",
75
+ "preserveAspectRatio"
76
+ ]);
77
+ export const MAX_FIGURE_CHARS = 16000;
78
+ const TAG = /<\/?([a-zA-Z][\w:-]*)((?:"[^"]*"|'[^']*'|[^>])*?)\/?>/g;
79
+ const ATTR = /([a-zA-Z][\w:-]*)\s*=\s*("([^"]*)"|'([^']*)')/g;
80
+ const FOREIGN_URL = /url\(\s*['"]?(?!#)/i;
81
+ function cleanAttrs(raw) {
82
+ const kept = [];
83
+ for (const match of raw.matchAll(ATTR)){
84
+ const name = match[1];
85
+ const value = match[3] ?? match[4] ?? "";
86
+ if (!ALLOWED_ATTRS.has(name)) continue;
87
+ if (FOREIGN_URL.test(value)) continue;
88
+ kept.push(`${name}="${value.replace(/"/g, "&quot;")}"`);
89
+ }
90
+ return kept.length > 0 ? ` ${kept.join(" ")}` : "";
91
+ }
92
+ export function sanitizeFigureSvg(raw) {
93
+ if (typeof raw !== "string" || raw.length > MAX_FIGURE_CHARS) return null;
94
+ const stripped = raw.replace(/<!--[\s\S]*?-->/g, "").replace(/<!\[CDATA\[[\s\S]*?\]\]>/g, "").replace(/<\?[\s\S]*?\?>/g, "").replace(/<!DOCTYPE[^>]*>/gi, "").replace(/<(script|style|foreignObject|iframe)\b[\s\S]*?<\/\1\s*>/gi, "");
95
+ if (!/<svg\b/i.test(stripped)) return null;
96
+ let out = "";
97
+ let cursor = 0;
98
+ for (const match of stripped.matchAll(TAG)){
99
+ const [tag, name, attrs] = match;
100
+ const start = match.index ?? 0;
101
+ out += stripped.slice(cursor, start);
102
+ cursor = start + tag.length;
103
+ if (!ALLOWED_TAGS.has(name)) continue;
104
+ if (tag.startsWith("</")) {
105
+ out += `</${name}>`;
106
+ continue;
107
+ }
108
+ out += `<${name}${cleanAttrs(attrs)}${tag.endsWith("/>") ? " />" : ">"}`;
109
+ }
110
+ out += stripped.slice(cursor);
111
+ return out.trim();
112
+ }
113
+ function rootAttr(svg, name) {
114
+ const root = svg.match(/<svg\b([^>]*)>/i);
115
+ if (!root) return undefined;
116
+ const found = root[1].match(new RegExp(`${name}\\s*=\\s*"([^"]*)"`, "i"));
117
+ return found?.[1];
118
+ }
119
+ export function figureRatio(svg) {
120
+ const box = rootAttr(svg, "viewBox");
121
+ if (box) {
122
+ const [, , w, h] = box.trim().split(/[\s,]+/).map(Number);
123
+ if (w > 0 && h > 0) return h / w;
124
+ }
125
+ const w = Number.parseFloat(rootAttr(svg, "width") ?? "");
126
+ const h = Number.parseFloat(rootAttr(svg, "height") ?? "");
127
+ return w > 0 && h > 0 ? h / w : null;
128
+ }
129
+ export function figureBoxHeight(svg, width, fallback = 0.4) {
130
+ return Math.round(width * (figureRatio(svg) ?? fallback));
131
+ }
132
+ const LABEL_H = 27;
133
+ const CAPTION_H = 24;
134
+ export function figureNodeHeight(figure, width) {
135
+ const art = figure.height ?? figureBoxHeight(figure.svg ?? "", width);
136
+ return art + (figure.label ? LABEL_H : 0) + (figure.caption ? CAPTION_H : 0);
137
+ }
@@ -0,0 +1,161 @@
1
+ const CELL_CHAR_W = 6.7;
2
+ export const TABLE_CELL_PAD_X = 12;
3
+ const ROW_LINE_H = 18;
4
+ const ROW_BORDER = 1;
5
+ const TABLE_EMPTY_H = 56;
6
+ const SECTION_ROW_H = 29;
7
+ const NOTE_LINE_H = 16;
8
+ export const TABLE_DEPTH_INDENT = 16;
9
+ export const TABLE_TITLE_H = 49;
10
+ export const TABLE_COLHEAD_H = 33;
11
+ const TABLE_ROW_PAD_Y = 20;
12
+ export const TABLE_MIN_W = 360;
13
+ export const TABLE_MAX_W = 760;
14
+ const FILL_COL_CH = 32;
15
+ const HAND_FONT_FACTOR = 1.12;
16
+ export const TABLE_RESIZE_MAX_W = 1600;
17
+ const MIN_COL_CH = 9;
18
+ const MAX_COL_CH = 48;
19
+ export function tableColumnCount(headers, rows) {
20
+ return Math.max(headers.length, rows.reduce((max, row)=>Math.max(max, row.cells?.length ?? 0), 0), 1);
21
+ }
22
+ export function tableColumnWeights(headers, rows, explicit) {
23
+ const count = tableColumnCount(headers, rows);
24
+ if (explicit && explicit.length === count && explicit.every((w)=>w > 0)) {
25
+ return normalize(explicit);
26
+ }
27
+ return normalize(naturalColumnChars(headers, rows, count));
28
+ }
29
+ function naturalColumnChars(headers, rows, count) {
30
+ return Array.from({
31
+ length: count
32
+ }, (_, i)=>{
33
+ const head = headers[i]?.length ?? 0;
34
+ const cells = rows.filter((row)=>!row.section).map((row)=>row.cells?.[i] ?? "");
35
+ const body = cells.reduce((max, cell)=>Math.max(max, cell.length), 0);
36
+ const blank = cells.length > 0 && cells.every(isBlankCell);
37
+ const wants = blank ? Math.max(head, FILL_COL_CH) : Math.max(head, body);
38
+ return Math.min(MAX_COL_CH, Math.max(MIN_COL_CH, wants));
39
+ });
40
+ }
41
+ export function isBlankCell(value) {
42
+ return /^[\s.…?\-–—_]*$/.test(value);
43
+ }
44
+ export const TABLE_COL_MIN_W = MIN_COL_CH * CELL_CHAR_W + TABLE_CELL_PAD_X * 2;
45
+ export function tableGridTemplate(weights, floor = 0) {
46
+ const min = floor > 0 ? `${floor}px` : "0";
47
+ return weights.map((w)=>`minmax(${min}, ${w.toFixed(4)}fr)`).join(" ");
48
+ }
49
+ export function tableColumnPx(weights, width) {
50
+ const out = weights.map(()=>0);
51
+ const pinned = new Set();
52
+ let changed = true;
53
+ while(changed){
54
+ changed = false;
55
+ const free = weights.reduce((sum, w, i)=>sum + (pinned.has(i) ? 0 : w), 0);
56
+ const room = width - pinned.size * TABLE_COL_MIN_W;
57
+ weights.forEach((w, i)=>{
58
+ if (pinned.has(i)) return;
59
+ out[i] = free > 0 ? room * w / free : 0;
60
+ if (out[i] < TABLE_COL_MIN_W && pinned.size < weights.length - 1) {
61
+ pinned.add(i);
62
+ changed = true;
63
+ }
64
+ });
65
+ }
66
+ return out.map((px, i)=>pinned.has(i) ? TABLE_COL_MIN_W : px);
67
+ }
68
+ function charWidth(font) {
69
+ return font === "hand" ? CELL_CHAR_W * HAND_FONT_FACTOR : CELL_CHAR_W;
70
+ }
71
+ export function tableWidth(headers, rows, ceiling = TABLE_MAX_W, font = "plain") {
72
+ const fitted = Math.ceil(naturalWidth(headers, rows, font));
73
+ return Math.min(ceiling, TABLE_MAX_W, Math.max(TABLE_MIN_W, fitted));
74
+ }
75
+ export function tableMinWidth(headers, rows) {
76
+ return tableColumnCount(headers, rows) * TABLE_COL_MIN_W + 2;
77
+ }
78
+ function naturalWidth(headers, rows, font) {
79
+ const count = tableColumnCount(headers, rows);
80
+ return naturalColumnChars(headers, rows, count).reduce((sum, ch)=>sum + ch * charWidth(font) + TABLE_CELL_PAD_X * 2, 0);
81
+ }
82
+ export function tableWeightsAt(headers, rows, width, { explicit, font = "plain" } = {}) {
83
+ if (width >= naturalWidth(headers, rows, font)) return tableColumnWeights(headers, rows);
84
+ return tableColumnWeights(headers, rows, explicit);
85
+ }
86
+ export function tableNumericColumns(rows, count) {
87
+ return Array.from({
88
+ length: count
89
+ }, (_, i)=>{
90
+ const values = rows.filter((row)=>!row.section).map((row)=>row.cells?.[i]?.trim() ?? "").filter(Boolean);
91
+ return values.length > 0 && values.every(isFigure);
92
+ });
93
+ }
94
+ function isFigure(value) {
95
+ return /^[-+]?[$€£]?\s?\d[\d\s.,]*\s?[%x×]?$/.test(value);
96
+ }
97
+ function wrappedLines(text, columnWidth, charW = CELL_CHAR_W) {
98
+ const inner = Math.max(charW, columnWidth - TABLE_CELL_PAD_X * 2);
99
+ const perLine = Math.max(1, Math.floor(inner / charW));
100
+ return Math.max(1, Math.ceil(text.length / perLine));
101
+ }
102
+ export function tableColumnsAt(headers, rows, width, { sizing, weights }) {
103
+ const count = tableColumnCount(headers, rows);
104
+ const inner = Math.max(count * TABLE_COL_MIN_W, width - 2);
105
+ const pinned = sizing.columnWidths;
106
+ if (pinned && pinned.length === count && pinned.every((w)=>w > 0)) {
107
+ return tableColumnPx(pinned, inner);
108
+ }
109
+ const split = sizing.userWidth != null ? tableColumnWeights(headers, rows, weights) : tableWeightsAt(headers, rows, width, {
110
+ explicit: weights,
111
+ font: sizing.font
112
+ });
113
+ return tableColumnPx(split, inner);
114
+ }
115
+ export function tableColumns(headers, rows, sizing = {}, weights) {
116
+ const count = tableColumnCount(headers, rows);
117
+ const pinned = sizing.columnWidths;
118
+ const hasPinned = pinned && pinned.length === count && pinned.every((w)=>w > 0);
119
+ const width = sizing.userWidth ?? (hasPinned ? Math.round(pinned.reduce((sum, w)=>sum + w, 0)) + 2 : tableWidth(headers, rows, TABLE_MAX_W, sizing.font));
120
+ return {
121
+ width,
122
+ columns: tableColumnsAt(headers, rows, width, {
123
+ sizing,
124
+ weights
125
+ })
126
+ };
127
+ }
128
+ export function tableRowHeights(rows, columns, sizing = {}) {
129
+ const charW = charWidth(sizing.font ?? "plain");
130
+ const full = columns.reduce((sum, px)=>sum + px, 0);
131
+ return rows.map((row, i)=>{
132
+ if (row.section) return Math.max(SECTION_ROW_H, sizing.rowHeights?.[i] ?? 0);
133
+ const indent = (row.depth ?? 0) * TABLE_DEPTH_INDENT;
134
+ const lines = columns.reduce((max, px, c)=>Math.max(max, wrappedLines(row.cells?.[c] ?? "", c === 0 ? px - indent : px, charW)), 1);
135
+ const note = row.note ? wrappedLines(row.note, full - indent) * NOTE_LINE_H : 0;
136
+ const content = TABLE_ROW_PAD_Y + lines * ROW_LINE_H + ROW_BORDER + note;
137
+ return Math.max(content, sizing.rowHeights?.[i] ?? 0);
138
+ });
139
+ }
140
+ export function tableHeight(headers, rows, width, { explicit, sizing = {} } = {}) {
141
+ const head = headers.length > 0 ? TABLE_COLHEAD_H : 0;
142
+ if (rows.length === 0) return TABLE_TITLE_H + head + TABLE_EMPTY_H;
143
+ const columns = tableColumnsAt(headers, rows, width, {
144
+ sizing,
145
+ weights: explicit
146
+ });
147
+ const body = tableRowHeights(rows, columns, sizing).reduce((sum, h)=>sum + h, 0);
148
+ return Math.max(sizing.userHeight ?? 0, TABLE_TITLE_H + head + body);
149
+ }
150
+ export function tableColumnFit(headers, rows, col, font = "plain") {
151
+ const longest = [
152
+ headers[col] ?? "",
153
+ ...rows.filter((row)=>!row.section).map((row)=>row.cells?.[col] ?? "")
154
+ ].reduce((max, text)=>Math.max(max, text.length), 0);
155
+ const px = Math.ceil(longest * charWidth(font)) + TABLE_CELL_PAD_X * 2;
156
+ return Math.max(TABLE_COL_MIN_W, Math.min(px, TABLE_RESIZE_MAX_W));
157
+ }
158
+ function normalize(weights) {
159
+ const total = weights.reduce((sum, w)=>sum + w, 0);
160
+ return total > 0 ? weights.map((w)=>w / total) : weights.map(()=>1 / weights.length);
161
+ }
@@ -0,0 +1,25 @@
1
+ export * from "./types.js";
2
+ export * from "./plugin.js";
3
+ export { tryCatch, tryCatchAsync } from "../lib/result.js";
4
+ export * from "./ops/ops.js";
5
+ export * from "./headless/alignment.js";
6
+ export * from "./headless/canvas-cleanup.js";
7
+ export * from "./headless/edge-anchors.js";
8
+ export * from "./headless/edge-serialization.js";
9
+ export * from "./headless/fit-viewport.js";
10
+ export * from "./headless/grid.js";
11
+ export * from "./headless/icon-node.js";
12
+ export * from "./headless/linkify.js";
13
+ export * from "./headless/sketch.js";
14
+ export * from "./headless/snap-guides.js";
15
+ export * from "./headless/svg-figure.js";
16
+ export * from "./headless/table-layout.js";
17
+ export { resolveContextMenuHit } from "./editor/context-menu.js";
18
+ export * from "./editor/editor-context.js";
19
+ export * from "./editor/dispatch.svelte.js";
20
+ export * from "./editor/editor-mode.js";
21
+ export * from "./editor/history-core.js";
22
+ export * from "./editor/keymap.js";
23
+ export * from "./editor/layout-actions.js";
24
+ export * from "./editor/rebase.js";
25
+ export * from "./editor/text-field-context.js";
@@ -0,0 +1,22 @@
1
+ import { untrack } from "svelte";
2
+ export const LOW_BELOW = 0.4;
3
+ export const FULL_ABOVE = 0.46;
4
+ const modes = new WeakMap();
5
+ export function lodMode(store) {
6
+ const known = modes.get(store);
7
+ if (known) return known;
8
+ const mode = $state({
9
+ low: store.viewport.zoom < LOW_BELOW
10
+ });
11
+ modes.set(store, mode);
12
+ $effect.root(()=>{
13
+ $effect(()=>{
14
+ const zoom = store.viewport.zoom;
15
+ untrack(()=>{
16
+ if (mode.low && zoom > FULL_ABOVE) mode.low = false;
17
+ else if (!mode.low && zoom < LOW_BELOW) mode.low = true;
18
+ });
19
+ });
20
+ });
21
+ return mode;
22
+ }
@@ -0,0 +1,45 @@
1
+ import { tick } from "svelte";
2
+ const hold = $state({
3
+ count: 0
4
+ });
5
+ export const renderAll = {
6
+ get on () {
7
+ return hold.count > 0;
8
+ }
9
+ };
10
+ const frame = ()=>new Promise((resolve)=>requestAnimationFrame(()=>resolve()));
11
+ const DRAWN = ".svelte-flow__node, .svelte-flow__edge";
12
+ const SETTLE_FRAMES = 8;
13
+ const GIVE_UP_MS = 4000;
14
+ export const EVERY_CARD_ATTR = "data-cv-every-card";
15
+ export async function withEveryCard(root, use) {
16
+ hold.count += 1;
17
+ const marked = root instanceof Element ? root : null;
18
+ marked?.setAttribute(EVERY_CARD_ATTR, "");
19
+ try {
20
+ await tick();
21
+ const start = performance.now();
22
+ let last = -1;
23
+ let still = 0;
24
+ while(still < SETTLE_FRAMES && performance.now() - start < GIVE_UP_MS){
25
+ await frame();
26
+ const now = root.querySelectorAll(DRAWN).length;
27
+ still = now === last ? still + 1 : 0;
28
+ last = now;
29
+ }
30
+ if ("getAnimations" in root) {
31
+ const running = root.getAnimations({
32
+ subtree: true
33
+ });
34
+ await Promise.race([
35
+ Promise.allSettled(running.map((animation)=>animation.finished)),
36
+ new Promise((resolve)=>setTimeout(resolve, 1000))
37
+ ]);
38
+ }
39
+ await frame();
40
+ return await use();
41
+ } finally{
42
+ hold.count -= 1;
43
+ if (hold.count === 0) marked?.removeAttribute(EVERY_CARD_ATTR);
44
+ }
45
+ }
@@ -0,0 +1,83 @@
1
+ export const ALIGNMENTS = [
2
+ "left",
3
+ "right",
4
+ "top",
5
+ "bottom",
6
+ "center-horizontal",
7
+ "center-vertical"
8
+ ];
9
+ export function alignPositions(items, alignment) {
10
+ const moved = new Map();
11
+ if (items.length < 2) return moved;
12
+ const left = Math.min(...items.map((item)=>item.position.x));
13
+ const top = Math.min(...items.map((item)=>item.position.y));
14
+ const right = Math.max(...items.map((item)=>item.position.x + item.width));
15
+ const bottom = Math.max(...items.map((item)=>item.position.y + item.height));
16
+ for (const item of items){
17
+ const { x, y } = item.position;
18
+ const next = {
19
+ x,
20
+ y
21
+ };
22
+ if (alignment === "left") next.x = left;
23
+ else if (alignment === "right") next.x = right - item.width;
24
+ else if (alignment === "top") next.y = top;
25
+ else if (alignment === "bottom") next.y = bottom - item.height;
26
+ else if (alignment === "center-horizontal") next.x = (left + right) / 2 - item.width / 2;
27
+ else next.y = (top + bottom) / 2 - item.height / 2;
28
+ if (next.x !== x || next.y !== y) moved.set(item.id, next);
29
+ }
30
+ return moved;
31
+ }
32
+ function along(axis) {
33
+ const horizontal = axis === "horizontal";
34
+ return {
35
+ start: (item)=>horizontal ? item.position.x : item.position.y,
36
+ size: (item)=>horizontal ? item.width : item.height,
37
+ place: (item, at)=>horizontal ? {
38
+ x: at,
39
+ y: item.position.y
40
+ } : {
41
+ x: item.position.x,
42
+ y: at
43
+ }
44
+ };
45
+ }
46
+ function inOrder(items, axis) {
47
+ const { start } = along(axis);
48
+ return [
49
+ ...items
50
+ ].sort((a, b)=>start(a) - start(b));
51
+ }
52
+ export function distributePositions(items, axis) {
53
+ const moved = new Map();
54
+ if (items.length < 3) return moved;
55
+ const { start, size, place } = along(axis);
56
+ const sorted = inOrder(items, axis);
57
+ const first = sorted[0];
58
+ const last = sorted[sorted.length - 1];
59
+ if (!first || !last) return moved;
60
+ const span = start(last) + size(last) - start(first);
61
+ const used = sorted.reduce((sum, item)=>sum + size(item), 0);
62
+ const gap = (span - used) / (sorted.length - 1);
63
+ let cursor = start(first);
64
+ for (const item of sorted){
65
+ if (cursor !== start(item)) moved.set(item.id, place(item, cursor));
66
+ cursor += size(item) + gap;
67
+ }
68
+ return moved;
69
+ }
70
+ export function stackPositions(items, axis, gap) {
71
+ const moved = new Map();
72
+ if (items.length < 2) return moved;
73
+ const { start, size, place } = along(axis);
74
+ const sorted = inOrder(items, axis);
75
+ const first = sorted[0];
76
+ if (!first) return moved;
77
+ let cursor = start(first);
78
+ for (const item of sorted){
79
+ if (cursor !== start(item)) moved.set(item.id, place(item, cursor));
80
+ cursor += size(item) + gap;
81
+ }
82
+ return moved;
83
+ }