@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,331 +1,299 @@
1
1
  const FALLBACK_FONT = 16;
2
2
  const ORIGIN = {
3
- x: 0,
4
- y: 0
3
+ x: 0,
4
+ y: 0
5
5
  };
6
6
  export function isEl(child) {
7
- return typeof child !== "string";
7
+ return typeof child !== "string";
8
8
  }
9
9
  export function num(value, fallback = 0) {
10
- const parsed = Number.parseFloat(value ?? "");
11
- return Number.isFinite(parsed) ? parsed : fallback;
10
+ const parsed = Number.parseFloat(value ?? "");
11
+ return Number.isFinite(parsed) ? parsed : fallback;
12
12
  }
13
+ /** A paint that draws: set, and not `none`. */
13
14
  export function solid(value) {
14
- return Boolean(value) && value !== "none";
15
+ return Boolean(value) && value !== "none";
15
16
  }
16
17
  export function plus(a, b) {
17
- return {
18
- x: a.x + b.x,
19
- y: a.y + b.y
20
- };
18
+ return {
19
+ x: a.x + b.x,
20
+ y: a.y + b.y
21
+ };
21
22
  }
23
+ /** `translate(a b)` and nothing else. Any other transform makes the geometry unreadable: null. */
22
24
  export function translateOf(el) {
23
- const raw = el.attrs.transform?.trim();
24
- if (!raw) return {
25
- x: 0,
26
- y: 0
27
- };
28
- const match = raw.match(/^translate\(\s*(-?[\d.]+)[\s,]*(-?[\d.]+)?\s*\)$/);
29
- return match ? {
30
- x: Number(match[1]),
31
- y: Number(match[2] ?? 0)
32
- } : null;
25
+ const raw = el.attrs.transform?.trim();
26
+ if (!raw) return {
27
+ x: 0,
28
+ y: 0
29
+ };
30
+ const match = raw.match(/^translate\(\s*(-?[\d.]+)[\s,]*(-?[\d.]+)?\s*\)$/);
31
+ return match ? {
32
+ x: Number(match[1]),
33
+ y: Number(match[2] ?? 0)
34
+ } : null;
33
35
  }
34
36
  export function union(a, b) {
35
- if (!a) return b;
36
- if (!b) return a;
37
- return {
38
- x1: Math.min(a.x1, b.x1),
39
- y1: Math.min(a.y1, b.y1),
40
- x2: Math.max(a.x2, b.x2),
41
- y2: Math.max(a.y2, b.y2)
42
- };
37
+ if (!a) return b;
38
+ if (!b) return a;
39
+ return {
40
+ x1: Math.min(a.x1, b.x1),
41
+ y1: Math.min(a.y1, b.y1),
42
+ x2: Math.max(a.x2, b.x2),
43
+ y2: Math.max(a.y2, b.y2)
44
+ };
43
45
  }
44
46
  export function boxOf(points) {
45
- if (points.length === 0) return null;
46
- return {
47
- x1: Math.min(...points.map((p)=>p.x)),
48
- y1: Math.min(...points.map((p)=>p.y)),
49
- x2: Math.max(...points.map((p)=>p.x)),
50
- y2: Math.max(...points.map((p)=>p.y))
51
- };
47
+ if (points.length === 0) return null;
48
+ return {
49
+ x1: Math.min(...points.map((p) => p.x)),
50
+ y1: Math.min(...points.map((p) => p.y)),
51
+ x2: Math.max(...points.map((p) => p.x)),
52
+ y2: Math.max(...points.map((p) => p.y))
53
+ };
52
54
  }
53
55
  export function within(inner, outer, tolerance = 1) {
54
- return inner.x1 >= outer.x1 - tolerance && inner.y1 >= outer.y1 - tolerance && inner.x2 <= outer.x2 + tolerance && inner.y2 <= outer.y2 + tolerance;
56
+ return inner.x1 >= outer.x1 - tolerance && inner.y1 >= outer.y1 - tolerance && inner.x2 <= outer.x2 + tolerance && inner.y2 <= outer.y2 + tolerance;
55
57
  }
56
58
  export function contains(box, point, tolerance) {
57
- return point.x >= box.x1 - tolerance && point.x <= box.x2 + tolerance && point.y >= box.y1 - tolerance && point.y <= box.y2 + tolerance;
59
+ return point.x >= box.x1 - tolerance && point.x <= box.x2 + tolerance && point.y >= box.y1 - tolerance && point.y <= box.y2 + tolerance;
58
60
  }
59
- export const areaOf = (b)=>(b.x2 - b.x1) * (b.y2 - b.y1);
60
- export const centerOf = (b)=>({
61
- x: (b.x1 + b.x2) / 2,
62
- y: (b.y1 + b.y2) / 2
63
- });
61
+ export const areaOf = (b) => (b.x2 - b.x1) * (b.y2 - b.y1);
62
+ export const centerOf = (b) => ({
63
+ x: (b.x1 + b.x2) / 2,
64
+ y: (b.y1 + b.y2) / 2
65
+ });
64
66
  export function distanceToBox(box, p) {
65
- return Math.hypot(Math.max(box.x1 - p.x, 0, p.x - box.x2), Math.max(box.y1 - p.y, 0, p.y - box.y2));
67
+ return Math.hypot(Math.max(box.x1 - p.x, 0, p.x - box.x2), Math.max(box.y1 - p.y, 0, p.y - box.y2));
66
68
  }
67
69
  export function distanceToSegment(a, b, p) {
68
- const dx = b.x - a.x;
69
- const dy = b.y - a.y;
70
- const len = dx * dx + dy * dy;
71
- const t = len === 0 ? 0 : Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / len));
72
- return Math.hypot(p.x - (a.x + t * dx), p.y - (a.y + t * dy));
70
+ const dx = b.x - a.x;
71
+ const dy = b.y - a.y;
72
+ const len = dx * dx + dy * dy;
73
+ const t = len === 0 ? 0 : Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / len));
74
+ return Math.hypot(p.x - (a.x + t * dx), p.y - (a.y + t * dy));
73
75
  }
76
+ // Numbers per path command; the last two (or the one for H and V) are the end point.
74
77
  const PATH_ARITY = {
75
- M: 2,
76
- L: 2,
77
- H: 1,
78
- V: 1,
79
- C: 6,
80
- S: 4,
81
- Q: 4,
82
- T: 2,
83
- A: 7,
84
- Z: 0
78
+ M: 2,
79
+ L: 2,
80
+ H: 1,
81
+ V: 1,
82
+ C: 6,
83
+ S: 4,
84
+ Q: 4,
85
+ T: 2,
86
+ A: 7,
87
+ Z: 0
85
88
  };
89
+ /** Where one command ends, given its arguments and where the pen was. */
86
90
  function pathEnd(upper, rel, args, cur) {
87
- const at = (from, value)=>rel ? from + value : value;
88
- if (upper === "H") return {
89
- x: at(cur.x, args[0]),
90
- y: cur.y
91
- };
92
- if (upper === "V") return {
93
- x: cur.x,
94
- y: at(cur.y, args[0])
95
- };
96
- return {
97
- x: at(cur.x, args[args.length - 2]),
98
- y: at(cur.y, args[args.length - 1])
99
- };
91
+ const at = (from, value) => rel ? from + value : value;
92
+ if (upper === "H") return {
93
+ x: at(cur.x, args[0]),
94
+ y: cur.y
95
+ };
96
+ if (upper === "V") return {
97
+ x: cur.x,
98
+ y: at(cur.y, args[0])
99
+ };
100
+ return {
101
+ x: at(cur.x, args[args.length - 2]),
102
+ y: at(cur.y, args[args.length - 1])
103
+ };
100
104
  }
105
+ /** The vertices a path passes through. Curve control points are skipped: the ends bound it well enough. */
101
106
  export function pathPoints(d) {
102
- const out = [];
103
- let cur = {
104
- x: 0,
105
- y: 0
106
- };
107
- let start = {
108
- x: 0,
109
- y: 0
110
- };
111
- for (const part of d.matchAll(/([a-zA-Z])([^a-zA-Z]*)/g)){
112
- const cmd = part[1];
113
- const upper = cmd.toUpperCase();
114
- const size = PATH_ARITY[upper];
115
- if (size === undefined) continue;
116
- const nums = (part[2].match(/-?(?:\d+\.?\d*|\.\d+)(?:e-?\d+)?/gi) ?? []).map(Number);
117
- if (upper === "Z") {
118
- cur = start;
119
- out.push(cur);
120
- continue;
121
- }
122
- for(let i = 0; i + size <= nums.length; i += size){
123
- cur = pathEnd(upper, cmd !== upper, nums.slice(i, i + size), cur);
124
- if (upper === "M" && i === 0) start = cur;
125
- out.push(cur);
126
- }
127
- }
128
- return out;
107
+ const out = [];
108
+ let cur = {
109
+ x: 0,
110
+ y: 0
111
+ };
112
+ let start = {
113
+ x: 0,
114
+ y: 0
115
+ };
116
+ for (const part of d.matchAll(/([a-zA-Z])([^a-zA-Z]*)/g)) {
117
+ const cmd = part[1];
118
+ const upper = cmd.toUpperCase();
119
+ const size = PATH_ARITY[upper];
120
+ if (size === undefined) continue;
121
+ const nums = (part[2].match(/-?(?:\d+\.?\d*|\.\d+)(?:e-?\d+)?/gi) ?? []).map(Number);
122
+ if (upper === "Z") {
123
+ cur = start;
124
+ out.push(cur);
125
+ continue;
126
+ }
127
+ for (let i = 0; i + size <= nums.length; i += size) {
128
+ cur = pathEnd(upper, cmd !== upper, nums.slice(i, i + size), cur);
129
+ if (upper === "M" && i === 0) start = cur;
130
+ out.push(cur);
131
+ }
132
+ }
133
+ return out;
129
134
  }
130
135
  export function pointList(raw) {
131
- const nums = (raw ?? "").match(/-?(?:\d+\.?\d*|\.\d+)/g)?.map(Number) ?? [];
132
- const out = [];
133
- for(let i = 0; i + 1 < nums.length; i += 2)out.push({
134
- x: nums[i],
135
- y: nums[i + 1]
136
- });
137
- return out;
136
+ const nums = (raw ?? "").match(/-?(?:\d+\.?\d*|\.\d+)/g)?.map(Number) ?? [];
137
+ const out = [];
138
+ for (let i = 0; i + 1 < nums.length; i += 2) out.push({
139
+ x: nums[i],
140
+ y: nums[i + 1]
141
+ });
142
+ return out;
138
143
  }
139
144
  export function textLines(el) {
140
- const lines = [];
141
- let line = "";
142
- const flush = ()=>{
143
- const clean = line.replace(/\s+/g, " ").trim();
144
- if (clean) lines.push(clean);
145
- line = "";
146
- };
147
- for (const child of el.children){
148
- if (typeof child === "string") line += child;
149
- else if (child.tag === "tspan") {
150
- if ("dy" in child.attrs || "y" in child.attrs) flush();
151
- line += child.children.map((c)=>typeof c === "string" ? c : "").join("");
152
- }
153
- }
154
- flush();
155
- return lines;
145
+ const lines = [];
146
+ let line = "";
147
+ const flush = () => {
148
+ const clean = line.replace(/\s+/g, " ").trim();
149
+ if (clean) lines.push(clean);
150
+ line = "";
151
+ };
152
+ for (const child of el.children) {
153
+ if (typeof child === "string") line += child;
154
+ else if (child.tag === "tspan") {
155
+ if ("dy" in child.attrs || "y" in child.attrs) flush();
156
+ line += child.children.map((c) => typeof c === "string" ? c : "").join("");
157
+ }
158
+ }
159
+ flush();
160
+ return lines;
156
161
  }
157
162
  export function isBold(el) {
158
- const weight = el.attrs["font-weight"];
159
- return num(weight) >= 600 || weight === "bold";
163
+ const weight = el.attrs["font-weight"];
164
+ return num(weight) >= 600 || weight === "bold";
160
165
  }
161
166
  export function fontSize(el) {
162
- return num(el.attrs["font-size"], FALLBACK_FONT);
167
+ return num(el.attrs["font-size"], FALLBACK_FONT);
163
168
  }
164
169
  function rectBox({ attrs: a }) {
165
- return {
166
- x1: num(a.x),
167
- y1: num(a.y),
168
- x2: num(a.x) + num(a.width),
169
- y2: num(a.y) + num(a.height)
170
- };
170
+ return {
171
+ x1: num(a.x),
172
+ y1: num(a.y),
173
+ x2: num(a.x) + num(a.width),
174
+ y2: num(a.y) + num(a.height)
175
+ };
171
176
  }
172
177
  function ellipseBox({ attrs: a }) {
173
- const rx = num(a.rx, num(a.r));
174
- const ry = num(a.ry, num(a.r));
175
- return {
176
- x1: num(a.cx) - rx,
177
- y1: num(a.cy) - ry,
178
- x2: num(a.cx) + rx,
179
- y2: num(a.cy) + ry
180
- };
178
+ const rx = num(a.rx, num(a.r));
179
+ const ry = num(a.ry, num(a.r));
180
+ return {
181
+ x1: num(a.cx) - rx,
182
+ y1: num(a.cy) - ry,
183
+ x2: num(a.cx) + rx,
184
+ y2: num(a.cy) + ry
185
+ };
181
186
  }
182
187
  function lineBox({ attrs: a }) {
183
- return boxOf([
184
- {
185
- x: num(a.x1),
186
- y: num(a.y1)
187
- },
188
- {
189
- x: num(a.x2),
190
- y: num(a.y2)
191
- }
192
- ]);
188
+ return boxOf([{
189
+ x: num(a.x1),
190
+ y: num(a.y1)
191
+ }, {
192
+ x: num(a.x2),
193
+ y: num(a.y2)
194
+ }]);
193
195
  }
194
196
  function polyBox({ attrs: a }) {
195
- return boxOf(pointList(a.points));
197
+ return boxOf(pointList(a.points));
196
198
  }
197
199
  function pathBox({ attrs: a }) {
198
- return boxOf(pathPoints(a.d ?? ""));
200
+ return boxOf(pathPoints(a.d ?? ""));
199
201
  }
200
202
  function textLeft(x, width, anchor) {
201
- if (anchor === "middle") return x - width / 2;
202
- return anchor === "end" ? x - width : x;
203
+ if (anchor === "middle") return x - width / 2;
204
+ return anchor === "end" ? x - width : x;
203
205
  }
204
206
  function textBox(el) {
205
- const lines = textLines(el);
206
- const size = fontSize(el);
207
- const width = Math.max(0, ...lines.map((l)=>l.length)) * size * (isBold(el) ? 0.6 : 0.55);
208
- const left = textLeft(num(el.attrs.x), width, el.attrs["text-anchor"]);
209
- const y = num(el.attrs.y);
210
- return {
211
- x1: left,
212
- y1: y - size * 0.8,
213
- x2: left + width,
214
- y2: y + size * 0.2 + Math.max(0, lines.length - 1) * size * 1.2
215
- };
207
+ const lines = textLines(el);
208
+ const size = fontSize(el);
209
+ const width = Math.max(0, ...lines.map((l) => l.length)) * size * (isBold(el) ? .6 : .55);
210
+ const left = textLeft(num(el.attrs.x), width, el.attrs["text-anchor"]);
211
+ const y = num(el.attrs.y);
212
+ return {
213
+ x1: left,
214
+ y1: y - size * .8,
215
+ x2: left + width,
216
+ y2: y + size * .2 + Math.max(0, lines.length - 1) * size * 1.2
217
+ };
216
218
  }
217
219
  function groupBox(el) {
218
- let box = null;
219
- for (const child of el.children){
220
- if (isEl(child)) box = union(box, boxOfEl(child, ORIGIN));
221
- }
222
- return box;
220
+ let box = null;
221
+ for (const child of el.children) {
222
+ if (isEl(child)) box = union(box, boxOfEl(child, ORIGIN));
223
+ }
224
+ return box;
223
225
  }
224
226
  const MEASURE = new Map([
225
- [
226
- "rect",
227
- rectBox
228
- ],
229
- [
230
- "circle",
231
- ellipseBox
232
- ],
233
- [
234
- "ellipse",
235
- ellipseBox
236
- ],
237
- [
238
- "line",
239
- lineBox
240
- ],
241
- [
242
- "polyline",
243
- polyBox
244
- ],
245
- [
246
- "polygon",
247
- polyBox
248
- ],
249
- [
250
- "path",
251
- pathBox
252
- ],
253
- [
254
- "text",
255
- textBox
256
- ],
257
- [
258
- "g",
259
- groupBox
260
- ],
261
- [
262
- "svg",
263
- groupBox
264
- ]
227
+ ["rect", rectBox],
228
+ ["circle", ellipseBox],
229
+ ["ellipse", ellipseBox],
230
+ ["line", lineBox],
231
+ ["polyline", polyBox],
232
+ ["polygon", polyBox],
233
+ ["path", pathBox],
234
+ ["text", textBox],
235
+ ["g", groupBox],
236
+ ["svg", groupBox]
265
237
  ]);
238
+ /** The ink a shape takes, in the figure's own units. Text is estimated: no DOM here to measure it. */
266
239
  export function boxOfEl(el, offset) {
267
- const box = MEASURE.get(el.tag)?.(el);
268
- if (!box) return null;
269
- const at = plus(offset, translateOf(el) ?? ORIGIN);
270
- return {
271
- x1: box.x1 + at.x,
272
- y1: box.y1 + at.y,
273
- x2: box.x2 + at.x,
274
- y2: box.y2 + at.y
275
- };
240
+ const box = MEASURE.get(el.tag)?.(el);
241
+ if (!box) return null;
242
+ const at = plus(offset, translateOf(el) ?? ORIGIN);
243
+ return {
244
+ x1: box.x1 + at.x,
245
+ y1: box.y1 + at.y,
246
+ x2: box.x2 + at.x,
247
+ y2: box.y2 + at.y
248
+ };
276
249
  }
277
250
  export function visible(el) {
278
- const fill = el.attrs.fill;
279
- const stroke = el.attrs.stroke;
280
- return fill !== undefined && fill !== "none" || stroke !== undefined && stroke !== "none";
251
+ const fill = el.attrs.fill;
252
+ const stroke = el.attrs.stroke;
253
+ return fill !== undefined && fill !== "none" || stroke !== undefined && stroke !== "none";
281
254
  }
282
255
  export function viewBoxOf(root) {
283
- const raw = root.attrs.viewBox ?? root.attrs.viewbox;
284
- if (raw) {
285
- const [x, y, w, h] = raw.trim().split(/[\s,]+/).map(Number);
286
- if (w > 0 && h > 0) return {
287
- x1: x,
288
- y1: y,
289
- x2: x + w,
290
- y2: y + h
291
- };
292
- }
293
- const w = num(root.attrs.width);
294
- const h = num(root.attrs.height);
295
- return w > 0 && h > 0 ? {
296
- x1: 0,
297
- y1: 0,
298
- x2: w,
299
- y2: h
300
- } : null;
256
+ const raw = root.attrs.viewBox ?? root.attrs.viewbox;
257
+ if (raw) {
258
+ const [x, y, w, h] = raw.trim().split(/[\s,]+/).map(Number);
259
+ if (w > 0 && h > 0) return {
260
+ x1: x,
261
+ y1: y,
262
+ x2: x + w,
263
+ y2: y + h
264
+ };
265
+ }
266
+ const w = num(root.attrs.width);
267
+ const h = num(root.attrs.height);
268
+ return w > 0 && h > 0 ? {
269
+ x1: 0,
270
+ y1: 0,
271
+ x2: w,
272
+ y2: h
273
+ } : null;
301
274
  }
302
275
  export function hasText(el) {
303
- return el.tag === "text" && textLines(el).length > 0;
276
+ return el.tag === "text" && textLines(el).length > 0;
304
277
  }
278
+ /** Where a line, polyline or path starts and stops, on the figure. Null for one with a transform we can't read. */
305
279
  export function strokeEnds(el, offset) {
306
- const shift = translateOf(el);
307
- if (!shift) return null;
308
- const a = el.attrs;
309
- let pts = [];
310
- if (el.tag === "line") {
311
- pts = [
312
- {
313
- x: num(a.x1),
314
- y: num(a.y1)
315
- },
316
- {
317
- x: num(a.x2),
318
- y: num(a.y2)
319
- }
320
- ];
321
- } else if (el.tag === "polyline") pts = pointList(a.points);
322
- else if (el.tag === "path") pts = pathPoints(a.d ?? "");
323
- if (pts.length < 2) return null;
324
- const at = plus(offset, shift);
325
- const first = pts[0];
326
- const last = pts[pts.length - 1];
327
- return [
328
- plus(first, at),
329
- plus(last, at)
330
- ];
280
+ const shift = translateOf(el);
281
+ if (!shift) return null;
282
+ const a = el.attrs;
283
+ let pts = [];
284
+ if (el.tag === "line") {
285
+ pts = [{
286
+ x: num(a.x1),
287
+ y: num(a.y1)
288
+ }, {
289
+ x: num(a.x2),
290
+ y: num(a.y2)
291
+ }];
292
+ } else if (el.tag === "polyline") pts = pointList(a.points);
293
+ else if (el.tag === "path") pts = pathPoints(a.d ?? "");
294
+ if (pts.length < 2) return null;
295
+ const at = plus(offset, shift);
296
+ const first = pts[0];
297
+ const last = pts[pts.length - 1];
298
+ return [plus(first, at), plus(last, at)];
331
299
  }