@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,284 +1,297 @@
1
+ // The path and arrowhead placement for one link, chosen by its route. Pure, so the choice is testable.
1
2
  import { getBezierPath, getSmoothStepPath, getStraightPath, Position } from "@xyflow/svelte";
2
3
  import { bestAnchors, sideDetour, sideFromHandle } from "../headless/edge-anchors.js";
3
4
  import { parseBox } from "../headless/edge-memo.js";
5
+ /** The corner radius a stepped link shares with the cards it joins. */
4
6
  const CORNER = 8;
7
+ /** How far a same-side link runs past the cards, and the least it keeps once bent. */
5
8
  const DETOUR = 40;
6
9
  const DETOUR_FLOOR = 8;
7
10
  const OUT = {
8
- top: {
9
- x: 0,
10
- y: -1
11
- },
12
- right: {
13
- x: 1,
14
- y: 0
15
- },
16
- bottom: {
17
- x: 0,
18
- y: 1
19
- },
20
- left: {
21
- x: -1,
22
- y: 0
23
- }
11
+ top: {
12
+ x: 0,
13
+ y: -1
14
+ },
15
+ right: {
16
+ x: 1,
17
+ y: 0
18
+ },
19
+ bottom: {
20
+ x: 0,
21
+ y: 1
22
+ },
23
+ left: {
24
+ x: -1,
25
+ y: 0
26
+ }
24
27
  };
28
+ /** The bend an edge stores in its data: pixels the movable run sits off its unbent place. */
25
29
  export function readBend(data) {
26
- const raw = data && typeof data === "object" ? data.bend : null;
27
- return typeof raw === "number" && Number.isFinite(raw) ? raw : 0;
30
+ const raw = data && typeof data === "object" ? data.bend : null;
31
+ return typeof raw === "number" && Number.isFinite(raw) ? raw : 0;
28
32
  }
33
+ /** The bend that puts a handle's run under the pointer, kept inside the handle's limits. */
29
34
  export function bendFromPointer(handle, pointer) {
30
- const at = handle.axis === "x" ? pointer.x : pointer.y;
31
- return Math.round(Math.min(handle.max, Math.max(handle.min, at)) - handle.base);
35
+ const at = handle.axis === "x" ? pointer.x : pointer.y;
36
+ return Math.round(Math.min(handle.max, Math.max(handle.min, at)) - handle.base);
32
37
  }
33
38
  function mid(a, b) {
34
- return (a + b) / 2;
39
+ return (a + b) / 2;
35
40
  }
36
41
  function clamp(value, a, b) {
37
- return Math.min(Math.max(a, b), Math.max(Math.min(a, b), value));
42
+ return Math.min(Math.max(a, b), Math.max(Math.min(a, b), value));
38
43
  }
44
+ /** Out from `s` to the run at `at`, across it, then in to `t`. */
39
45
  function runPoints(s, t, horizontal, at) {
40
- return horizontal ? [
41
- s,
42
- {
43
- x: at,
44
- y: s.y
45
- },
46
- {
47
- x: at,
48
- y: t.y
49
- },
50
- t
51
- ] : [
52
- s,
53
- {
54
- x: s.x,
55
- y: at
56
- },
57
- {
58
- x: t.x,
59
- y: at
60
- },
61
- t
62
- ];
46
+ return horizontal ? [
47
+ s,
48
+ {
49
+ x: at,
50
+ y: s.y
51
+ },
52
+ {
53
+ x: at,
54
+ y: t.y
55
+ },
56
+ t
57
+ ] : [
58
+ s,
59
+ {
60
+ x: s.x,
61
+ y: at
62
+ },
63
+ {
64
+ x: t.x,
65
+ y: at
66
+ },
67
+ t
68
+ ];
63
69
  }
70
+ /** The handle on the run at `at`, or none when the two ends line up and there is nothing to slide. */
64
71
  function runHandle({ source: s, target: t }, horizontal, at, limits) {
65
- const span = horizontal ? t.y - s.y : t.x - s.x;
66
- if (!(Math.abs(span) > 1)) return null;
67
- return {
68
- axis: horizontal ? "x" : "y",
69
- x: horizontal ? at : mid(s.x, t.x),
70
- y: horizontal ? mid(s.y, t.y) : at,
71
- ...limits
72
- };
72
+ const span = horizontal ? t.y - s.y : t.x - s.x;
73
+ if (!(Math.abs(span) > 1)) return null;
74
+ return {
75
+ axis: horizontal ? "x" : "y",
76
+ x: horizontal ? at : mid(s.x, t.x),
77
+ y: horizontal ? mid(s.y, t.y) : at,
78
+ ...limits
79
+ };
73
80
  }
81
+ /** Same side: out past both cards, along, back in. The run keeps a margin outside them. */
74
82
  function sameSideElbow(anchors, bend) {
75
- const { source: s, target: t } = anchors;
76
- const out = OUT[s.side];
77
- const horizontal = out.x !== 0;
78
- const base = sideDetour(anchors, DETOUR);
79
- const edge = sideDetour(anchors, 0);
80
- const outward = horizontal ? out.x : out.y;
81
- const at = clamp(base + bend, edge + outward * DETOUR_FLOOR, outward > 0 ? Infinity : -Infinity);
82
- const handle = runHandle(anchors, horizontal, at, {
83
- base,
84
- min: outward > 0 ? edge + DETOUR_FLOOR : -Infinity,
85
- max: outward > 0 ? Infinity : edge - DETOUR_FLOOR
86
- });
87
- return {
88
- points: runPoints(s, t, horizontal, at),
89
- handle
90
- };
83
+ const { source: s, target: t } = anchors;
84
+ const out = OUT[s.side];
85
+ const horizontal = out.x !== 0;
86
+ const base = sideDetour(anchors, DETOUR);
87
+ const edge = sideDetour(anchors, 0);
88
+ const outward = horizontal ? out.x : out.y;
89
+ const at = clamp(base + bend, edge + outward * DETOUR_FLOOR, outward > 0 ? Infinity : -Infinity);
90
+ const handle = runHandle(anchors, horizontal, at, {
91
+ base,
92
+ min: outward > 0 ? edge + DETOUR_FLOOR : -Infinity,
93
+ max: outward > 0 ? Infinity : edge - DETOUR_FLOOR
94
+ });
95
+ return {
96
+ points: runPoints(s, t, horizontal, at),
97
+ handle
98
+ };
91
99
  }
100
+ /** Opposite sides: out, across at the middle, in. The across run is what a bend moves. */
92
101
  function acrossElbow(anchors, bend) {
93
- const { source: s, target: t } = anchors;
94
- const horizontal = OUT[s.side].x !== 0;
95
- const base = horizontal ? mid(s.x, t.x) : mid(s.y, t.y);
96
- const lo = horizontal ? Math.min(s.x, t.x) : Math.min(s.y, t.y);
97
- const hi = horizontal ? Math.max(s.x, t.x) : Math.max(s.y, t.y);
98
- const at = clamp(base + bend, lo, hi);
99
- const handle = runHandle(anchors, horizontal, at, {
100
- base,
101
- min: lo,
102
- max: hi
103
- });
104
- return {
105
- points: runPoints(s, t, horizontal, at),
106
- handle
107
- };
102
+ const { source: s, target: t } = anchors;
103
+ const horizontal = OUT[s.side].x !== 0;
104
+ const base = horizontal ? mid(s.x, t.x) : mid(s.y, t.y);
105
+ const lo = horizontal ? Math.min(s.x, t.x) : Math.min(s.y, t.y);
106
+ const hi = horizontal ? Math.max(s.x, t.x) : Math.max(s.y, t.y);
107
+ const at = clamp(base + bend, lo, hi);
108
+ const handle = runHandle(anchors, horizontal, at, {
109
+ base,
110
+ min: lo,
111
+ max: hi
112
+ });
113
+ return {
114
+ points: runPoints(s, t, horizontal, at),
115
+ handle
116
+ };
108
117
  }
118
+ /** Square sides: one corner, when both ends are on the way there. */
109
119
  function cornerElbow(anchors) {
110
- const { source: s, target: t } = anchors;
111
- const inward = OUT[t.side];
112
- const horizontalOut = OUT[s.side].x !== 0;
113
- if (horizontalOut === (inward.x !== 0)) return null;
114
- const corner = horizontalOut ? {
115
- x: t.x,
116
- y: s.y
117
- } : {
118
- x: s.x,
119
- y: t.y
120
- };
121
- const arriving = horizontalOut ? Math.sign(t.y - s.y) : Math.sign(t.x - s.x);
122
- const wanted = horizontalOut ? -inward.y : -inward.x;
123
- return arriving === wanted ? {
124
- points: [
125
- s,
126
- corner,
127
- t
128
- ],
129
- handle: null
130
- } : null;
120
+ const { source: s, target: t } = anchors;
121
+ const inward = OUT[t.side];
122
+ const horizontalOut = OUT[s.side].x !== 0;
123
+ if (horizontalOut === (inward.x !== 0)) return null;
124
+ const corner = horizontalOut ? {
125
+ x: t.x,
126
+ y: s.y
127
+ } : {
128
+ x: s.x,
129
+ y: t.y
130
+ };
131
+ const arriving = horizontalOut ? Math.sign(t.y - s.y) : Math.sign(t.x - s.x);
132
+ const wanted = horizontalOut ? -inward.y : -inward.x;
133
+ return arriving === wanted ? {
134
+ points: [
135
+ s,
136
+ corner,
137
+ t
138
+ ],
139
+ handle: null
140
+ } : null;
131
141
  }
142
+ /** The corners of an elbow between two anchors and the run a bend moves. Null when it must turn back, which getSmoothStepPath routes. */
132
143
  function elbowPoints(anchors, bend) {
133
- const { source: s, target: t } = anchors;
134
- if (s.side === t.side) return sameSideElbow(anchors, bend);
135
- const out = OUT[s.side];
136
- const inward = OUT[t.side];
137
- const ahead = out.x * (t.x - s.x) + out.y * (t.y - s.y);
138
- if (ahead <= 0) return null;
139
- if (out.x === -inward.x && out.y === -inward.y) return acrossElbow(anchors, bend);
140
- return cornerElbow(anchors);
144
+ const { source: s, target: t } = anchors;
145
+ if (s.side === t.side) return sameSideElbow(anchors, bend);
146
+ const out = OUT[s.side];
147
+ const inward = OUT[t.side];
148
+ const ahead = out.x * (t.x - s.x) + out.y * (t.y - s.y);
149
+ if (ahead <= 0) return null;
150
+ if (out.x === -inward.x && out.y === -inward.y) return acrossElbow(anchors, bend);
151
+ return cornerElbow(anchors);
141
152
  }
153
+ /** Corners drawn as the same quadratic arcs getSmoothStepPath draws, so the two routes match. */
142
154
  function roundedPath(points) {
143
- const pts = points.filter((p, i)=>i === 0 || p.x !== points[i - 1].x || p.y !== points[i - 1].y);
144
- let d = `M ${pts[0].x} ${pts[0].y}`;
145
- for(let i = 1; i < pts.length - 1; i++){
146
- const a = pts[i - 1];
147
- const b = pts[i];
148
- const c = pts[i + 1];
149
- const r = Math.min(CORNER, Math.hypot(b.x - a.x, b.y - a.y) / 2, Math.hypot(c.x - b.x, c.y - b.y) / 2);
150
- const collinear = a.x === b.x && b.x === c.x || a.y === b.y && b.y === c.y;
151
- if (collinear || !(r > 0.5)) {
152
- d += ` L ${b.x} ${b.y}`;
153
- continue;
154
- }
155
- const before = {
156
- x: b.x - Math.sign(b.x - a.x) * r,
157
- y: b.y - Math.sign(b.y - a.y) * r
158
- };
159
- const after = {
160
- x: b.x + Math.sign(c.x - b.x) * r,
161
- y: b.y + Math.sign(c.y - b.y) * r
162
- };
163
- d += ` L ${before.x} ${before.y} Q ${b.x} ${b.y} ${after.x} ${after.y}`;
164
- }
165
- const last = pts[pts.length - 1];
166
- return `${d} L ${last.x} ${last.y}`;
155
+ const pts = points.filter((p, i) => i === 0 || p.x !== points[i - 1].x || p.y !== points[i - 1].y);
156
+ let d = `M ${pts[0].x} ${pts[0].y}`;
157
+ for (let i = 1; i < pts.length - 1; i++) {
158
+ const a = pts[i - 1];
159
+ const b = pts[i];
160
+ const c = pts[i + 1];
161
+ const r = Math.min(CORNER, Math.hypot(b.x - a.x, b.y - a.y) / 2, Math.hypot(c.x - b.x, c.y - b.y) / 2);
162
+ const collinear = a.x === b.x && b.x === c.x || a.y === b.y && b.y === c.y;
163
+ if (collinear || !(r > .5)) {
164
+ d += ` L ${b.x} ${b.y}`;
165
+ continue;
166
+ }
167
+ const before = {
168
+ x: b.x - Math.sign(b.x - a.x) * r,
169
+ y: b.y - Math.sign(b.y - a.y) * r
170
+ };
171
+ const after = {
172
+ x: b.x + Math.sign(c.x - b.x) * r,
173
+ y: b.y + Math.sign(c.y - b.y) * r
174
+ };
175
+ d += ` L ${before.x} ${before.y} Q ${b.x} ${b.y} ${after.x} ${after.y}`;
176
+ }
177
+ const last = pts[pts.length - 1];
178
+ return `${d} L ${last.x} ${last.y}`;
167
179
  }
180
+ /** The middle of the longest run, where a label sits when the link has no bend handle. */
168
181
  function middleOf(points) {
169
- let best = {
170
- length: -1,
171
- at: points[0]
172
- };
173
- for(let i = 1; i < points.length; i++){
174
- const length = Math.hypot(points[i].x - points[i - 1].x, points[i].y - points[i - 1].y);
175
- if (length > best.length) best = {
176
- length,
177
- at: {
178
- x: mid(points[i].x, points[i - 1].x),
179
- y: mid(points[i].y, points[i - 1].y)
180
- }
181
- };
182
- }
183
- return best.at;
182
+ let best = {
183
+ length: -1,
184
+ at: points[0]
185
+ };
186
+ for (let i = 1; i < points.length; i++) {
187
+ const length = Math.hypot(points[i].x - points[i - 1].x, points[i].y - points[i - 1].y);
188
+ if (length > best.length) best = {
189
+ length,
190
+ at: {
191
+ x: mid(points[i].x, points[i - 1].x),
192
+ y: mid(points[i].y, points[i - 1].y)
193
+ }
194
+ };
195
+ }
196
+ return best.at;
184
197
  }
198
+ /** The corners an elbow turns at, for a hand-ruled drawing to follow. Null for any other route. */
185
199
  export function elbowCorners(route, anchors, bend = 0) {
186
- if (route !== "elbow" || !anchors) return null;
187
- return elbowPoints(anchors, bend)?.points ?? null;
200
+ if (route !== "elbow" || !anchors) return null;
201
+ return elbowPoints(anchors, bend)?.points ?? null;
188
202
  }
189
203
  export function routeEdgePath(route, geometry, anchors, bend = 0) {
190
- if (route === "straight") {
191
- const [path, labelX, labelY] = getStraightPath(geometry);
192
- return {
193
- path,
194
- labelX,
195
- labelY,
196
- bend: null
197
- };
198
- }
199
- if (route === "curved") {
200
- const [path, labelX, labelY] = getBezierPath(geometry);
201
- return {
202
- path,
203
- labelX,
204
- labelY,
205
- bend: null
206
- };
207
- }
208
- const plan = anchors ? elbowPoints(anchors, bend) : null;
209
- if (plan) {
210
- const label = plan.handle ?? middleOf(plan.points);
211
- return {
212
- path: roundedPath(plan.points),
213
- labelX: label.x,
214
- labelY: label.y,
215
- bend: plan.handle
216
- };
217
- }
218
- const [path, labelX, labelY] = getSmoothStepPath({
219
- ...geometry,
220
- borderRadius: CORNER
221
- });
222
- return {
223
- path,
224
- labelX,
225
- labelY,
226
- bend: null
227
- };
204
+ if (route === "straight") {
205
+ const [path, labelX, labelY] = getStraightPath(geometry);
206
+ return {
207
+ path,
208
+ labelX,
209
+ labelY,
210
+ bend: null
211
+ };
212
+ }
213
+ if (route === "curved") {
214
+ const [path, labelX, labelY] = getBezierPath(geometry);
215
+ return {
216
+ path,
217
+ labelX,
218
+ labelY,
219
+ bend: null
220
+ };
221
+ }
222
+ const plan = anchors ? elbowPoints(anchors, bend) : null;
223
+ if (plan) {
224
+ const label = plan.handle ?? middleOf(plan.points);
225
+ return {
226
+ path: roundedPath(plan.points),
227
+ labelX: label.x,
228
+ labelY: label.y,
229
+ bend: plan.handle
230
+ };
231
+ }
232
+ const [path, labelX, labelY] = getSmoothStepPath({
233
+ ...geometry,
234
+ borderRadius: CORNER
235
+ });
236
+ return {
237
+ path,
238
+ labelX,
239
+ labelY,
240
+ bend: null
241
+ };
228
242
  }
243
+ /** Everything one link draws: its sides, path, bend handle and arrowheads, from where its cards sit. */
229
244
  export function planLink(input) {
230
- const from = parseBox(input.fromBox);
231
- const to = parseBox(input.toBox);
232
- let anchors = null;
233
- let geometry = input.fallback;
234
- if (from && to) {
235
- anchors = bestAnchors(from, to, {
236
- source: sideFromHandle(input.sourceHandle),
237
- target: sideFromHandle(input.targetHandle)
238
- });
239
- geometry = {
240
- sourceX: anchors.source.x,
241
- sourceY: anchors.source.y,
242
- sourcePosition: anchors.source.side,
243
- targetX: anchors.target.x,
244
- targetY: anchors.target.y,
245
- targetPosition: anchors.target.side
246
- };
247
- }
248
- return {
249
- ...routeEdgePath(input.route, geometry, anchors, input.bend),
250
- anchors,
251
- geometry,
252
- tips: arrowTips(input.route, geometry, anchors)
253
- };
245
+ const from = parseBox(input.fromBox);
246
+ const to = parseBox(input.toBox);
247
+ let anchors = null;
248
+ let geometry = input.fallback;
249
+ if (from && to) {
250
+ anchors = bestAnchors(from, to, {
251
+ source: sideFromHandle(input.sourceHandle),
252
+ target: sideFromHandle(input.targetHandle)
253
+ });
254
+ geometry = {
255
+ sourceX: anchors.source.x,
256
+ sourceY: anchors.source.y,
257
+ sourcePosition: anchors.source.side,
258
+ targetX: anchors.target.x,
259
+ targetY: anchors.target.y,
260
+ targetPosition: anchors.target.side
261
+ };
262
+ }
263
+ return {
264
+ ...routeEdgePath(input.route, geometry, anchors, input.bend),
265
+ anchors,
266
+ geometry,
267
+ tips: arrowTips(input.route, geometry, anchors)
268
+ };
254
269
  }
270
+ /** The direction a link travels when it meets a box on `side`: straight into it. */
255
271
  function into(side) {
256
- switch(side){
257
- case "left":
258
- return 0;
259
- case "right":
260
- return Math.PI;
261
- case "top":
262
- return Math.PI / 2;
263
- case "bottom":
264
- return -Math.PI / 2;
265
- }
272
+ switch (side) {
273
+ case "left": return 0;
274
+ case "right": return Math.PI;
275
+ case "top": return Math.PI / 2;
276
+ case "bottom": return -Math.PI / 2;
277
+ }
266
278
  }
279
+ /** Where an arrowhead sits and points at each end: along a straight link's line, square on to the box otherwise. */
267
280
  export function arrowTips(route, geometry, anchors) {
268
- const { sourceX, sourceY, targetX, targetY } = geometry;
269
- const straight = Math.atan2(targetY - sourceY, targetX - sourceX);
270
- const startAngle = route === "straight" || !anchors ? straight + Math.PI : into(anchors.source.side);
271
- const endAngle = route === "straight" || !anchors ? straight : into(anchors.target.side);
272
- return {
273
- start: {
274
- x: sourceX,
275
- y: sourceY,
276
- angle: startAngle
277
- },
278
- end: {
279
- x: targetX,
280
- y: targetY,
281
- angle: endAngle
282
- }
283
- };
281
+ const { sourceX, sourceY, targetX, targetY } = geometry;
282
+ const straight = Math.atan2(targetY - sourceY, targetX - sourceX);
283
+ const startAngle = route === "straight" || !anchors ? straight + Math.PI : into(anchors.source.side);
284
+ const endAngle = route === "straight" || !anchors ? straight : into(anchors.target.side);
285
+ return {
286
+ start: {
287
+ x: sourceX,
288
+ y: sourceY,
289
+ angle: startAngle
290
+ },
291
+ end: {
292
+ x: targetX,
293
+ y: targetY,
294
+ angle: endAngle
295
+ }
296
+ };
284
297
  }
@@ -1,42 +1,45 @@
1
1
  function rectOf(el) {
2
- if (!el) return null;
3
- const r = el.getBoundingClientRect();
4
- return {
5
- x: r.x,
6
- y: r.y,
7
- width: r.width,
8
- height: r.height
9
- };
2
+ if (!el) return null;
3
+ const r = el.getBoundingClientRect();
4
+ return {
5
+ x: r.x,
6
+ y: r.y,
7
+ width: r.width,
8
+ height: r.height
9
+ };
10
10
  }
11
11
  function tableCellOf(target) {
12
- const cell = target.closest("[data-table-row]");
13
- if (!cell) return null;
14
- return {
15
- row: Number(cell.dataset.tableRow),
16
- col: Number(cell.dataset.tableCol)
17
- };
12
+ const cell = target.closest("[data-table-row]");
13
+ if (!cell) return null;
14
+ return {
15
+ row: Number(cell.dataset.tableRow),
16
+ col: Number(cell.dataset.tableCol)
17
+ };
18
18
  }
19
+ /** Reads a right-click into an edge hit, or a canvas/node hit with its anchor
20
+ * rect and cell. The edge check runs first, because an arrow also carries
21
+ * `data-id`. */
19
22
  export function resolveContextMenuHit(event, nodes) {
20
- const target = event.target;
21
- const position = {
22
- x: event.clientX,
23
- y: event.clientY
24
- };
25
- const edgeId = target.closest(".svelte-flow__edge")?.getAttribute("data-id");
26
- if (edgeId) return {
27
- kind: "edge",
28
- edgeId,
29
- position
30
- };
31
- const nodeElement = target.closest("[data-id]");
32
- const nodeId = nodeElement?.getAttribute("data-id") ?? null;
33
- const node = nodeId ? nodes.find((n)=>n.id === nodeId) : undefined;
34
- return {
35
- kind: "canvas",
36
- position,
37
- anchorRect: rectOf(nodeElement),
38
- nodeId,
39
- nodeType: node?.type ?? null,
40
- tableCell: tableCellOf(target)
41
- };
23
+ const target = event.target;
24
+ const position = {
25
+ x: event.clientX,
26
+ y: event.clientY
27
+ };
28
+ const edgeId = target.closest(".svelte-flow__edge")?.getAttribute("data-id");
29
+ if (edgeId) return {
30
+ kind: "edge",
31
+ edgeId,
32
+ position
33
+ };
34
+ const nodeElement = target.closest("[data-id]");
35
+ const nodeId = nodeElement?.getAttribute("data-id") ?? null;
36
+ const node = nodeId ? nodes.find((n) => n.id === nodeId) : undefined;
37
+ return {
38
+ kind: "canvas",
39
+ position,
40
+ anchorRect: rectOf(nodeElement),
41
+ nodeId,
42
+ nodeType: node?.type ?? null,
43
+ tableCell: tableCellOf(target)
44
+ };
42
45
  }