@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,35 +1,36 @@
1
+ // The eraser hits whole strokes only, so a swipe across a big shape never wipes it.
1
2
  import { distanceToStroke } from "./geometry.js";
2
3
  import { STROKE_NODE } from "./types.js";
3
4
  function isStrokeData(data) {
4
- return Array.isArray(data.points) && typeof data.size === "number";
5
+ return Array.isArray(data.points) && typeof data.size === "number";
5
6
  }
7
+ /** Ids of the strokes whose line passes within `radius` of `at`, a flow-space point. */
6
8
  export function strokesUnder(nodes, at, radius) {
7
- const hits = [];
8
- for (const node of nodes){
9
- if (node.type !== STROKE_NODE || !isStrokeData(node.data)) continue;
10
- const local = {
11
- x: at.x - node.position.x,
12
- y: at.y - node.position.y
13
- };
14
- if (distanceToStroke(node.data.points, local) <= radius + node.data.size / 2) {
15
- hits.push(node.id);
16
- }
17
- }
18
- return hits;
9
+ const hits = [];
10
+ for (const node of nodes) {
11
+ if (node.type !== STROKE_NODE || !isStrokeData(node.data)) continue;
12
+ const local = {
13
+ x: at.x - node.position.x,
14
+ y: at.y - node.position.y
15
+ };
16
+ if (distanceToStroke(node.data.points, local) <= radius + node.data.size / 2) {
17
+ hits.push(node.id);
18
+ }
19
+ }
20
+ return hits;
19
21
  }
22
+ /** The same test along a swipe, so a fast pointer can't skip over a thin line. */
20
23
  export function strokesAlong(nodes, from, to, radius) {
21
- const length = Math.hypot(to.x - from.x, to.y - from.y);
22
- const steps = Math.max(1, Math.ceil(length / Math.max(radius / 2, 1)));
23
- const hits = new Set();
24
- for(let i = 0; i <= steps; i++){
25
- const t = i / steps;
26
- const at = {
27
- x: from.x + (to.x - from.x) * t,
28
- y: from.y + (to.y - from.y) * t
29
- };
30
- for (const id of strokesUnder(nodes, at, radius))hits.add(id);
31
- }
32
- return [
33
- ...hits
34
- ];
24
+ const length = Math.hypot(to.x - from.x, to.y - from.y);
25
+ const steps = Math.max(1, Math.ceil(length / Math.max(radius / 2, 1)));
26
+ const hits = new Set();
27
+ for (let i = 0; i <= steps; i++) {
28
+ const t = i / steps;
29
+ const at = {
30
+ x: from.x + (to.x - from.x) * t,
31
+ y: from.y + (to.y - from.y) * t
32
+ };
33
+ for (const id of strokesUnder(nodes, at, radius)) hits.add(id);
34
+ }
35
+ return [...hits];
35
36
  }
@@ -1,143 +1,133 @@
1
1
  import { PEN_DEFAULTS, STROKE_NODE } from "./types.js";
2
- const SIMPLIFY_TOLERANCE = 0.6;
2
+ /** How far, in screen pixels, a saved stroke may stray from what was drawn. */
3
+ const SIMPLIFY_TOLERANCE = .6;
3
4
  function round(value, places) {
4
- const factor = 10 ** places;
5
- return Math.round(value * factor) / factor;
5
+ const factor = 10 ** places;
6
+ return Math.round(value * factor) / factor;
6
7
  }
8
+ /** Distance from p to the segment a-b. */
7
9
  export function distanceToSegment(p, a, b) {
8
- const dx = b.x - a.x;
9
- const dy = b.y - a.y;
10
- const lengthSquared = dx * dx + dy * dy;
11
- if (lengthSquared === 0) return Math.hypot(p.x - a.x, p.y - a.y);
12
- const t = Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / lengthSquared));
13
- return Math.hypot(p.x - (a.x + t * dx), p.y - (a.y + t * dy));
10
+ const dx = b.x - a.x;
11
+ const dy = b.y - a.y;
12
+ const lengthSquared = dx * dx + dy * dy;
13
+ if (lengthSquared === 0) return Math.hypot(p.x - a.x, p.y - a.y);
14
+ const t = Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / lengthSquared));
15
+ return Math.hypot(p.x - (a.x + t * dx), p.y - (a.y + t * dy));
14
16
  }
17
+ /**
18
+ * Ramer-Douglas-Peucker over x and y, run on an index stack so a long scribble
19
+ * can't overflow the call stack. The first and last samples always stay.
20
+ */
15
21
  export function simplifyPoints(points, tolerance) {
16
- if (points.length <= 2) return [
17
- ...points
18
- ];
19
- const keep = new Uint8Array(points.length);
20
- keep[0] = 1;
21
- keep[points.length - 1] = 1;
22
- const stack = [
23
- [
24
- 0,
25
- points.length - 1
26
- ]
27
- ];
28
- while(stack.length > 0){
29
- const [start, end] = stack.pop();
30
- const a = {
31
- x: points[start][0],
32
- y: points[start][1]
33
- };
34
- const b = {
35
- x: points[end][0],
36
- y: points[end][1]
37
- };
38
- let farthest = -1;
39
- let farthestDistance = tolerance;
40
- for(let i = start + 1; i < end; i++){
41
- const distance = distanceToSegment({
42
- x: points[i][0],
43
- y: points[i][1]
44
- }, a, b);
45
- if (distance > farthestDistance) {
46
- farthest = i;
47
- farthestDistance = distance;
48
- }
49
- }
50
- if (farthest === -1) continue;
51
- keep[farthest] = 1;
52
- stack.push([
53
- start,
54
- farthest
55
- ], [
56
- farthest,
57
- end
58
- ]);
59
- }
60
- return points.filter((_, i)=>keep[i] === 1);
22
+ if (points.length <= 2) return [...points];
23
+ const keep = new Uint8Array(points.length);
24
+ keep[0] = 1;
25
+ keep[points.length - 1] = 1;
26
+ const stack = [[0, points.length - 1]];
27
+ while (stack.length > 0) {
28
+ const [start, end] = stack.pop();
29
+ const a = {
30
+ x: points[start][0],
31
+ y: points[start][1]
32
+ };
33
+ const b = {
34
+ x: points[end][0],
35
+ y: points[end][1]
36
+ };
37
+ let farthest = -1;
38
+ let farthestDistance = tolerance;
39
+ for (let i = start + 1; i < end; i++) {
40
+ const distance = distanceToSegment({
41
+ x: points[i][0],
42
+ y: points[i][1]
43
+ }, a, b);
44
+ if (distance > farthestDistance) {
45
+ farthest = i;
46
+ farthestDistance = distance;
47
+ }
48
+ }
49
+ if (farthest === -1) continue;
50
+ keep[farthest] = 1;
51
+ stack.push([start, farthest], [farthest, end]);
52
+ }
53
+ return points.filter((_, i) => keep[i] === 1);
61
54
  }
62
55
  export function pointsBounds(points) {
63
- let minX = Infinity;
64
- let minY = Infinity;
65
- let maxX = -Infinity;
66
- let maxY = -Infinity;
67
- for (const [x, y] of points){
68
- minX = Math.min(minX, x);
69
- minY = Math.min(minY, y);
70
- maxX = Math.max(maxX, x);
71
- maxY = Math.max(maxY, y);
72
- }
73
- return {
74
- x: minX,
75
- y: minY,
76
- width: maxX - minX,
77
- height: maxY - minY
78
- };
56
+ let minX = Infinity;
57
+ let minY = Infinity;
58
+ let maxX = -Infinity;
59
+ let maxY = -Infinity;
60
+ for (const [x, y] of points) {
61
+ minX = Math.min(minX, x);
62
+ minY = Math.min(minY, y);
63
+ maxX = Math.max(maxX, x);
64
+ maxY = Math.max(maxY, y);
65
+ }
66
+ return {
67
+ x: minX,
68
+ y: minY,
69
+ width: maxX - minX,
70
+ height: maxY - minY
71
+ };
79
72
  }
73
+ /** Points are saved relative to the node, padded by the brush so the selection box holds the whole outline. */
80
74
  export function buildStrokeNode(samples, options = {}) {
81
- if (samples.length === 0) return null;
82
- const tool = options.tool ?? "pen";
83
- const size = options.size ?? PEN_DEFAULTS[tool].size;
84
- const tolerance = SIMPLIFY_TOLERANCE / Math.max(options.zoom ?? 1, 0.1);
85
- const source = samples.length === 1 ? [
86
- samples[0],
87
- samples[0]
88
- ] : samples;
89
- const simplified = simplifyPoints(source, tolerance);
90
- const hasPressure = simplified.some((point)=>point[2] !== undefined);
91
- const pad = Math.ceil(size / 2) + 2;
92
- const box = pointsBounds(simplified);
93
- const origin = {
94
- x: box.x - pad,
95
- y: box.y - pad
96
- };
97
- const points = simplified.map(([x, y, pressure])=>{
98
- const px = round(x - origin.x, 1);
99
- const py = round(y - origin.y, 1);
100
- return hasPressure ? [
101
- px,
102
- py,
103
- round(pressure ?? 0.5, 2)
104
- ] : [
105
- px,
106
- py
107
- ];
108
- });
109
- return {
110
- id: options.id,
111
- type: STROKE_NODE,
112
- position: {
113
- x: round(origin.x, 1),
114
- y: round(origin.y, 1)
115
- },
116
- data: {
117
- points,
118
- color: options.color ?? PEN_DEFAULTS.color,
119
- size,
120
- tool,
121
- simulatePressure: !hasPressure
122
- },
123
- width: Math.ceil(box.width + pad * 2),
124
- height: Math.ceil(box.height + pad * 2)
125
- };
75
+ if (samples.length === 0) return null;
76
+ const tool = options.tool ?? "pen";
77
+ const size = options.size ?? PEN_DEFAULTS[tool].size;
78
+ const tolerance = SIMPLIFY_TOLERANCE / Math.max(options.zoom ?? 1, .1);
79
+ // A tap is one sample. Doubling it gives the outline a segment, so it draws as a dot.
80
+ const source = samples.length === 1 ? [samples[0], samples[0]] : samples;
81
+ const simplified = simplifyPoints(source, tolerance);
82
+ const hasPressure = simplified.some((point) => point[2] !== undefined);
83
+ const pad = Math.ceil(size / 2) + 2;
84
+ const box = pointsBounds(simplified);
85
+ const origin = {
86
+ x: box.x - pad,
87
+ y: box.y - pad
88
+ };
89
+ const points = simplified.map(([x, y, pressure]) => {
90
+ const px = round(x - origin.x, 1);
91
+ const py = round(y - origin.y, 1);
92
+ return hasPressure ? [
93
+ px,
94
+ py,
95
+ round(pressure ?? .5, 2)
96
+ ] : [px, py];
97
+ });
98
+ return {
99
+ id: options.id,
100
+ type: STROKE_NODE,
101
+ position: {
102
+ x: round(origin.x, 1),
103
+ y: round(origin.y, 1)
104
+ },
105
+ data: {
106
+ points,
107
+ color: options.color ?? PEN_DEFAULTS.color,
108
+ size,
109
+ tool,
110
+ simulatePressure: !hasPressure
111
+ },
112
+ width: Math.ceil(box.width + pad * 2),
113
+ height: Math.ceil(box.height + pad * 2)
114
+ };
126
115
  }
116
+ /** Smallest distance from p to the stroke's centre line, in the stroke's own coordinates. */
127
117
  export function distanceToStroke(points, p) {
128
- if (points.length === 0) return Infinity;
129
- if (points.length === 1) return Math.hypot(p.x - points[0][0], p.y - points[0][1]);
130
- let best = Infinity;
131
- for(let i = 1; i < points.length; i++){
132
- const a = {
133
- x: points[i - 1][0],
134
- y: points[i - 1][1]
135
- };
136
- const b = {
137
- x: points[i][0],
138
- y: points[i][1]
139
- };
140
- best = Math.min(best, distanceToSegment(p, a, b));
141
- }
142
- return best;
118
+ if (points.length === 0) return Infinity;
119
+ if (points.length === 1) return Math.hypot(p.x - points[0][0], p.y - points[0][1]);
120
+ let best = Infinity;
121
+ for (let i = 1; i < points.length; i++) {
122
+ const a = {
123
+ x: points[i - 1][0],
124
+ y: points[i - 1][1]
125
+ };
126
+ const b = {
127
+ x: points[i][0],
128
+ y: points[i][1]
129
+ };
130
+ best = Math.min(best, distanceToSegment(p, a, b));
131
+ }
132
+ return best;
143
133
  }
@@ -1,3 +1,4 @@
1
+ // The pen layer, server-safe. Svelte parts are in ./ui.js.
1
2
  export { PEN_HEX, penColorVar } from "./colors.js";
2
3
  export { strokesAlong, strokesUnder } from "./eraser.js";
3
4
  export { buildStrokeNode, distanceToStroke, pointsBounds, simplifyPoints } from "./geometry.js";
@@ -1,15 +1,15 @@
1
1
  export function addPenNode(node) {
2
- return {
3
- kind: "addNode",
4
- node: {
5
- ...node,
6
- id: node.id ?? crypto.randomUUID()
7
- }
8
- };
2
+ return {
3
+ kind: "addNode",
4
+ node: {
5
+ ...node,
6
+ id: node.id ?? crypto.randomUUID()
7
+ }
8
+ };
9
9
  }
10
10
  export function removePenNode(nodeId) {
11
- return {
12
- kind: "removeNode",
13
- nodeId
14
- };
11
+ return {
12
+ kind: "removeNode",
13
+ nodeId
14
+ };
15
15
  }