@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,250 +1,272 @@
1
+ // Hand-drawn layer, server-safe: palette, geometry, seeding. The seed comes from
2
+ // the node id, so server SVG and Svelte draw the same wobble.
3
+ // Look and authoring: see the package README.
1
4
  import rough from "roughjs";
2
5
  import { createMemo } from "./edge-memo.js";
6
+ // =========================
7
+ // PALETTE
8
+ // =========================
9
+ /** Accent names a board author writes. Excalidraw's own stroke colors. */
3
10
  export const SKETCH_ACCENTS = [
4
- "ink",
5
- "red",
6
- "green",
7
- "blue",
8
- "violet",
9
- "amber",
10
- "teal",
11
- "indigo",
12
- "terra"
11
+ "ink",
12
+ "red",
13
+ "green",
14
+ "blue",
15
+ "violet",
16
+ "amber",
17
+ "teal",
18
+ "indigo",
19
+ "terra"
13
20
  ];
21
+ /** Excalidraw's strokes plus its lightest tint per hue; brand colors would read as app, not whiteboard. */
14
22
  const PALETTE = {
15
- ink: {
16
- stroke: "#1e1e1e",
17
- fill: "#ffffff",
18
- heading: "#1e1e1e",
19
- body: "#343a40"
20
- },
21
- red: {
22
- stroke: "#c92a2a",
23
- fill: "#fff5f5",
24
- heading: "#a61e4d",
25
- body: "#3b3b46"
26
- },
27
- green: {
28
- stroke: "#2f9e44",
29
- fill: "#f4fce3",
30
- heading: "#2b8a3e",
31
- body: "#3b3b46"
32
- },
33
- blue: {
34
- stroke: "#1971c2",
35
- fill: "#e7f5ff",
36
- heading: "#1864ab",
37
- body: "#3b3b46"
38
- },
39
- violet: {
40
- stroke: "#6741d9",
41
- fill: "#f3f0ff",
42
- heading: "#5f3dc4",
43
- body: "#3b3b46"
44
- },
45
- amber: {
46
- stroke: "#e8a33d",
47
- fill: "#fff9db",
48
- heading: "#b8860b",
49
- body: "#3b3b46"
50
- },
51
- teal: {
52
- stroke: "#0c8599",
53
- fill: "#e3fafc",
54
- heading: "#0b7285",
55
- body: "#3b3b46"
56
- },
57
- indigo: {
58
- stroke: "#414fd2",
59
- fill: "#ffffff",
60
- heading: "#414fd2",
61
- body: "#414fd2"
62
- },
63
- terra: {
64
- stroke: "#f0503d",
65
- fill: "#ffffff",
66
- heading: "#f0503d",
67
- body: "#f0503d"
68
- }
23
+ ink: {
24
+ stroke: "#1e1e1e",
25
+ fill: "#ffffff",
26
+ heading: "#1e1e1e",
27
+ body: "#343a40"
28
+ },
29
+ red: {
30
+ stroke: "#c92a2a",
31
+ fill: "#fff5f5",
32
+ heading: "#a61e4d",
33
+ body: "#3b3b46"
34
+ },
35
+ green: {
36
+ stroke: "#2f9e44",
37
+ fill: "#f4fce3",
38
+ heading: "#2b8a3e",
39
+ body: "#3b3b46"
40
+ },
41
+ blue: {
42
+ stroke: "#1971c2",
43
+ fill: "#e7f5ff",
44
+ heading: "#1864ab",
45
+ body: "#3b3b46"
46
+ },
47
+ violet: {
48
+ stroke: "#6741d9",
49
+ fill: "#f3f0ff",
50
+ heading: "#5f3dc4",
51
+ body: "#3b3b46"
52
+ },
53
+ amber: {
54
+ stroke: "#e8a33d",
55
+ fill: "#fff9db",
56
+ heading: "#b8860b",
57
+ body: "#3b3b46"
58
+ },
59
+ teal: {
60
+ stroke: "#0c8599",
61
+ fill: "#e3fafc",
62
+ heading: "#0b7285",
63
+ body: "#3b3b46"
64
+ },
65
+ // The brand pair the email figures are drawn in: tools/whiteboard/src/scene.ts INK and HIGHLIGHT.
66
+ indigo: {
67
+ stroke: "#414fd2",
68
+ fill: "#ffffff",
69
+ heading: "#414fd2",
70
+ body: "#414fd2"
71
+ },
72
+ terra: {
73
+ stroke: "#f0503d",
74
+ fill: "#ffffff",
75
+ heading: "#f0503d",
76
+ body: "#f0503d"
77
+ }
69
78
  };
79
+ /** The same hues lifted for the Ink board: light strokes, a dark wash, and text that stays readable on it. */
70
80
  const DARK_PALETTE = {
71
- ink: {
72
- stroke: "#e9ecef",
73
- fill: "#151b30",
74
- heading: "#f1f3f5",
75
- body: "#ced4da"
76
- },
77
- red: {
78
- stroke: "#ff8787",
79
- fill: "#2a1822",
80
- heading: "#ffa8c5",
81
- body: "#ced4da"
82
- },
83
- green: {
84
- stroke: "#69db7c",
85
- fill: "#132a20",
86
- heading: "#8ce99a",
87
- body: "#ced4da"
88
- },
89
- blue: {
90
- stroke: "#74c0fc",
91
- fill: "#12253d",
92
- heading: "#a5d8ff",
93
- body: "#ced4da"
94
- },
95
- violet: {
96
- stroke: "#b197fc",
97
- fill: "#211c3d",
98
- heading: "#d0bfff",
99
- body: "#ced4da"
100
- },
101
- amber: {
102
- stroke: "#ffd43b",
103
- fill: "#2b2612",
104
- heading: "#ffe066",
105
- body: "#ced4da"
106
- },
107
- teal: {
108
- stroke: "#66d9e8",
109
- fill: "#112a30",
110
- heading: "#99e9f2",
111
- body: "#ced4da"
112
- },
113
- indigo: {
114
- stroke: "#8b96ff",
115
- fill: "#151b30",
116
- heading: "#a5adff",
117
- body: "#a5adff"
118
- },
119
- terra: {
120
- stroke: "#ff8a78",
121
- fill: "#151b30",
122
- heading: "#ff9d8d",
123
- body: "#ff9d8d"
124
- }
81
+ ink: {
82
+ stroke: "#e9ecef",
83
+ fill: "#151b30",
84
+ heading: "#f1f3f5",
85
+ body: "#ced4da"
86
+ },
87
+ red: {
88
+ stroke: "#ff8787",
89
+ fill: "#2a1822",
90
+ heading: "#ffa8c5",
91
+ body: "#ced4da"
92
+ },
93
+ green: {
94
+ stroke: "#69db7c",
95
+ fill: "#132a20",
96
+ heading: "#8ce99a",
97
+ body: "#ced4da"
98
+ },
99
+ blue: {
100
+ stroke: "#74c0fc",
101
+ fill: "#12253d",
102
+ heading: "#a5d8ff",
103
+ body: "#ced4da"
104
+ },
105
+ violet: {
106
+ stroke: "#b197fc",
107
+ fill: "#211c3d",
108
+ heading: "#d0bfff",
109
+ body: "#ced4da"
110
+ },
111
+ amber: {
112
+ stroke: "#ffd43b",
113
+ fill: "#2b2612",
114
+ heading: "#ffe066",
115
+ body: "#ced4da"
116
+ },
117
+ teal: {
118
+ stroke: "#66d9e8",
119
+ fill: "#112a30",
120
+ heading: "#99e9f2",
121
+ body: "#ced4da"
122
+ },
123
+ indigo: {
124
+ stroke: "#8b96ff",
125
+ fill: "#151b30",
126
+ heading: "#a5adff",
127
+ body: "#a5adff"
128
+ },
129
+ terra: {
130
+ stroke: "#ff8a78",
131
+ fill: "#151b30",
132
+ heading: "#ff9d8d",
133
+ body: "#ff9d8d"
134
+ }
125
135
  };
136
+ /** Server renders (exports, emails) stay on the light palette; the editor passes its theme. */
126
137
  export function sketchColors(accent, dark = false) {
127
- const palette = dark ? DARK_PALETTE : PALETTE;
128
- return palette[accent ?? "ink"] ?? palette.ink;
138
+ const palette = dark ? DARK_PALETTE : PALETTE;
139
+ return palette[accent ?? "ink"] ?? palette.ink;
129
140
  }
130
141
  export function isSketchAccent(value) {
131
- return typeof value === "string" && SKETCH_ACCENTS.includes(value);
142
+ return typeof value === "string" && SKETCH_ACCENTS.includes(value);
132
143
  }
144
+ // =========================
145
+ // SEEDING
146
+ // =========================
147
+ /** A stable 31-bit seed (FNV-1a): unseeded calls reshuffle the wobble, so cards would redraw each render. */
133
148
  export function seedFrom(id) {
134
- let hash = 2166136261;
135
- for(let i = 0; i < id.length; i += 1){
136
- hash ^= id.charCodeAt(i);
137
- hash = Math.imul(hash, 16777619);
138
- }
139
- return Math.abs(hash) % 2147483647;
149
+ let hash = 2166136261;
150
+ for (let i = 0; i < id.length; i += 1) {
151
+ hash ^= id.charCodeAt(i);
152
+ hash = Math.imul(hash, 16777619);
153
+ }
154
+ return Math.abs(hash) % 2147483647;
140
155
  }
141
156
  const generator = rough.generator();
142
- const MEMO_LIMIT = 4000;
157
+ /** Arrows are redrawn whenever the page repaints them, so a line or head already drawn is handed back. */
158
+ const MEMO_LIMIT = 4e3;
143
159
  const lines = createMemo(MEMO_LIMIT);
144
160
  const heads = createMemo(MEMO_LIMIT);
161
+ /** Shared feel. Low roughness reads as a careful hand; high reads as a scribble. */
145
162
  function baseOptions(seed, colors, overrides) {
146
- return {
147
- seed,
148
- roughness: 1.1,
149
- bowing: 1.4,
150
- stroke: colors.stroke,
151
- strokeWidth: 1.6,
152
- fillStyle: "solid",
153
- ...overrides
154
- };
163
+ return {
164
+ seed,
165
+ roughness: 1.1,
166
+ bowing: 1.4,
167
+ stroke: colors.stroke,
168
+ strokeWidth: 1.6,
169
+ // WHY solid, not hachure: a hatched fill behind three lines of body copy
170
+ // makes the text unreadable at the zoom a card is actually read at.
171
+ fillStyle: "solid",
172
+ ...overrides
173
+ };
155
174
  }
156
175
  const FORMAL = {
157
- roughness: 0,
158
- bowing: 0,
159
- disableMultiStroke: true,
160
- strokeWidth: 1.4
176
+ roughness: 0,
177
+ bowing: 0,
178
+ disableMultiStroke: true,
179
+ strokeWidth: 1.4
161
180
  };
162
181
  function toPaths(drawable) {
163
- return generator.toPaths(drawable).map((p)=>({
164
- d: p.d,
165
- stroke: p.stroke,
166
- fill: p.fill ?? "none",
167
- strokeWidth: p.strokeWidth
168
- }));
182
+ return generator.toPaths(drawable).map((p) => ({
183
+ d: p.d,
184
+ stroke: p.stroke,
185
+ // rough leaves `fill` off a path it did not fill, and an unfilled path is
186
+ // the same thing as one filled with nothing.
187
+ fill: p.fill ?? "none",
188
+ strokeWidth: p.strokeWidth
189
+ }));
169
190
  }
191
+ /** A card outline: rough.js has no rounded rectangle, so a rounded path instead (square reads as a box). */
170
192
  export function roughCard(width, height, { seed, colors }, { radius = 14, formal = false } = {}) {
171
- const w = Math.max(width, radius * 2 + 2);
172
- const h = Math.max(height, radius * 2 + 2);
173
- const r = Math.min(radius, w / 2 - 1, h / 2 - 1);
174
- const d = [
175
- `M ${r} 0`,
176
- `L ${w - r} 0`,
177
- `Q ${w} 0 ${w} ${r}`,
178
- `L ${w} ${h - r}`,
179
- `Q ${w} ${h} ${w - r} ${h}`,
180
- `L ${r} ${h}`,
181
- `Q 0 ${h} 0 ${h - r}`,
182
- `L 0 ${r}`,
183
- `Q 0 0 ${r} 0`,
184
- "Z"
185
- ].join(" ");
186
- return toPaths(generator.path(d, baseOptions(seed, colors, {
187
- fill: colors.fill,
188
- ...formal ? FORMAL : {}
189
- })));
193
+ const w = Math.max(width, radius * 2 + 2);
194
+ const h = Math.max(height, radius * 2 + 2);
195
+ const r = Math.min(radius, w / 2 - 1, h / 2 - 1);
196
+ const d = [
197
+ `M ${r} 0`,
198
+ `L ${w - r} 0`,
199
+ `Q ${w} 0 ${w} ${r}`,
200
+ `L ${w} ${h - r}`,
201
+ `Q ${w} ${h} ${w - r} ${h}`,
202
+ `L ${r} ${h}`,
203
+ `Q 0 ${h} 0 ${h - r}`,
204
+ `L 0 ${r}`,
205
+ `Q 0 0 ${r} 0`,
206
+ "Z"
207
+ ].join(" ");
208
+ return toPaths(generator.path(d, baseOptions(seed, colors, {
209
+ fill: colors.fill,
210
+ ...formal ? FORMAL : {}
211
+ })));
190
212
  }
213
+ /** An ellipse card is drawn round its text, not through it: this much wider and taller than the box. */
191
214
  export const ELLIPSE_CARD_SCALE = {
192
- x: 1.32,
193
- y: 1.42
215
+ x: 1.32,
216
+ y: 1.42
194
217
  };
218
+ /** The circle-this-bit annotation, drawn as one loose pass. */
195
219
  export function roughEllipse(width, height, { seed, colors }, { formal = false } = {}) {
196
- return toPaths(generator.ellipse(width / 2, height / 2, width, height, baseOptions(seed, colors, {
197
- roughness: 1.6,
198
- strokeWidth: 2.2,
199
- fill: undefined,
200
- ...formal ? FORMAL : {}
201
- })));
220
+ return toPaths(generator.ellipse(width / 2, height / 2, width, height, baseOptions(seed, colors, {
221
+ roughness: 1.6,
222
+ strokeWidth: 2.2,
223
+ fill: undefined,
224
+ ...formal ? FORMAL : {}
225
+ })));
202
226
  }
227
+ /** A box with no rounding: the frame you draw around a whole column. */
203
228
  export function roughRect(width, height, { seed, colors }, { filled = false, formal = false } = {}) {
204
- return toPaths(generator.rectangle(1, 1, Math.max(width - 2, 2), Math.max(height - 2, 2), baseOptions(seed, colors, {
205
- fill: filled ? colors.fill : undefined,
206
- ...formal ? FORMAL : {}
207
- })));
229
+ return toPaths(generator.rectangle(1, 1, Math.max(width - 2, 2), Math.max(height - 2, 2), baseOptions(seed, colors, {
230
+ fill: filled ? colors.fill : undefined,
231
+ ...formal ? FORMAL : {}
232
+ })));
208
233
  }
234
+ /** A closed outline through the given points: the diamond mark, drawn like the box beside it. */
209
235
  export function roughPolygon(points, { seed, colors }, { formal = false } = {}) {
210
- return toPaths(generator.polygon(points.map(([x, y])=>[
211
- x,
212
- y
213
- ]), baseOptions(seed, colors, {
214
- fill: undefined,
215
- ...formal ? FORMAL : {}
216
- })));
236
+ return toPaths(generator.polygon(points.map(([x, y]) => [x, y]), baseOptions(seed, colors, {
237
+ fill: undefined,
238
+ ...formal ? FORMAL : {}
239
+ })));
217
240
  }
241
+ /** The hand-drawn rule under a title, `y` down from the top. */
218
242
  export function roughUnderline(width, { seed, colors }, { y = 4, formal = false } = {}) {
219
- return toPaths(generator.line(0, y, width, y, baseOptions(seed, colors, {
220
- strokeWidth: 2,
221
- bowing: 2.4,
222
- ...formal ? FORMAL : {}
223
- })));
243
+ return toPaths(generator.line(0, y, width, y, baseOptions(seed, colors, {
244
+ strokeWidth: 2,
245
+ bowing: 2.4,
246
+ ...formal ? FORMAL : {}
247
+ })));
224
248
  }
249
+ /** The shaft of a hand-ruled connector, with no head. */
225
250
  export function roughLine(from, to, { seed, colors }, { formal = false } = {}) {
226
- const hand = formal ? FORMAL : {};
227
- return lines(`${seed}|${colors.stroke}|${formal}|${from.x},${from.y}|${to.x},${to.y}`, ()=>toPaths(generator.line(from.x, from.y, to.x, to.y, baseOptions(seed, colors, {
228
- strokeWidth: 1.8,
229
- ...hand
230
- }))));
251
+ const hand = formal ? FORMAL : {};
252
+ // The same line is asked for on every redraw of its arrow, and rough.js is the slow part.
253
+ return lines(`${seed}|${colors.stroke}|${formal}|${from.x},${from.y}|${to.x},${to.y}`, () => toPaths(generator.line(from.x, from.y, to.x, to.y, baseOptions(seed, colors, {
254
+ strokeWidth: 1.8,
255
+ ...hand
256
+ }))));
231
257
  }
258
+ /** Two hand-drawn wings with their tip at `tip`, pointing along `angle` (radians). */
232
259
  export function roughHead(tip, angle, { seed, colors }, { formal = false } = {}) {
233
- const hand = formal ? FORMAL : {};
234
- const head = 11;
235
- const spread = 0.42;
236
- return heads(`${seed}|${colors.stroke}|${formal}|${tip.x},${tip.y}|${angle}`, ()=>[
237
- angle + Math.PI - spread,
238
- angle + Math.PI + spread
239
- ].flatMap((a, i)=>toPaths(generator.line(tip.x, tip.y, tip.x + Math.cos(a) * head, tip.y + Math.sin(a) * head, baseOptions(seed + i + 1, colors, {
240
- strokeWidth: 1.8,
241
- roughness: 0.8,
242
- ...hand
243
- })))));
260
+ const hand = formal ? FORMAL : {};
261
+ const head = 11;
262
+ const spread = .42;
263
+ return heads(`${seed}|${colors.stroke}|${formal}|${tip.x},${tip.y}|${angle}`, () => [angle + Math.PI - spread, angle + Math.PI + spread].flatMap((a, i) => toPaths(generator.line(tip.x, tip.y, tip.x + Math.cos(a) * head, tip.y + Math.sin(a) * head, baseOptions(seed + i + 1, colors, {
264
+ strokeWidth: 1.8,
265
+ roughness: .8,
266
+ ...hand
267
+ })))));
244
268
  }
269
+ /** A straight-ish connector between two canvas points, plus its arrow head. */
245
270
  export function roughArrow(from, to, pen, style = {}) {
246
- return [
247
- ...roughLine(from, to, pen, style),
248
- ...roughHead(to, Math.atan2(to.y - from.y, to.x - from.x), pen, style)
249
- ];
271
+ return [...roughLine(from, to, pen, style), ...roughHead(to, Math.atan2(to.y - from.y, to.x - from.x), pen, style)];
250
272
  }