@heyramzi/ui 2.0.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/package.json +48 -24
  2. package/scripts/sync-shadcn.mjs +3 -4
  3. package/src/agents/agent-avatar.svelte +604 -575
  4. package/src/agents/agent-cast.svelte +179 -183
  5. package/src/agents/demo.svelte +125 -113
  6. package/src/agents/helpers.ts +23 -17
  7. package/src/agents/index.ts +4 -4
  8. package/src/agents/page-state.ts +6 -6
  9. package/src/agents/types.ts +6 -6
  10. package/src/ai/ai-button/AiButton.svelte +4 -12
  11. package/src/ai/generation-progress/GenerationProgress.svelte +10 -3
  12. package/src/ai/prompt-input/PromptInputTextarea.svelte +1 -2
  13. package/src/ai/response/Response.css +2 -3
  14. package/src/animations/avatar-group-hover.css +2 -16
  15. package/src/animations/card-tilt.css +3 -6
  16. package/src/animations/digit-pop-in.css +2 -15
  17. package/src/animations/dropdown.css +4 -17
  18. package/src/animations/input-clear-dissolve.css +5 -18
  19. package/src/animations/input-shake.css +9 -41
  20. package/src/animations/learn-more-hover.css +17 -9
  21. package/src/animations/like-button.css +2 -4
  22. package/src/animations/page-side-by-side.css +2 -10
  23. package/src/animations/plus-menu-morph.css +2 -5
  24. package/src/animations/shimmer-text.css +5 -18
  25. package/src/animations/spinning-counter.css +2 -6
  26. package/src/animations/success-check.css +2 -15
  27. package/src/animations/thinking-states.css +2 -7
  28. package/src/brand/brand.test.ts +21 -5
  29. package/src/brand/index.ts +4 -10
  30. package/src/canvas/README.md +9 -12
  31. package/src/canvas/card/card-frame.svelte +43 -39
  32. package/src/canvas/card/resize-handles.svelte +89 -80
  33. package/src/canvas/chrome/chrome-zoom.svelte +101 -100
  34. package/src/canvas/chrome/lock-badge.svelte +8 -8
  35. package/src/canvas/chrome/side-handles.svelte +24 -19
  36. package/src/canvas/chrome/size-chip.svelte +30 -30
  37. package/src/canvas/chrome/snap-guides.svelte +20 -20
  38. package/src/canvas/components/icons/ToolIcon.svelte +8 -8
  39. package/src/canvas/components/shared/svg/PreviewSvg.svelte +19 -19
  40. package/src/canvas/components/shared/svg/ShapeOutline.svelte +71 -48
  41. package/src/canvas/components/shared/svg/StrokeNode.svelte +21 -27
  42. package/src/canvas/components/shared/svg/TextRule.svelte +25 -17
  43. package/src/canvas/edges/bend-handle.svelte +46 -46
  44. package/src/canvas/edges/edge-gradient.svelte +10 -10
  45. package/src/canvas/edges/gradient-edge.svelte +45 -29
  46. package/src/canvas/editor/lock.test.ts +6 -1
  47. package/src/canvas/editor/style.ts +7 -1
  48. package/src/canvas/headless/svg-figure.test.ts +5 -1
  49. package/src/canvas/lod/lod-switch.svelte +111 -106
  50. package/src/canvas/pen/PenField.svelte +87 -81
  51. package/src/canvas/pen/PenOverlay.svelte +127 -127
  52. package/src/canvas/pen/ShapeNode.svelte +31 -32
  53. package/src/canvas/pen/TextNode.svelte +54 -53
  54. package/src/canvas/pen/host-field.test.svelte +7 -7
  55. package/src/canvas/pen/shapes.ts +7 -1
  56. package/src/canvas/screen/GlyphIcon.svelte +22 -17
  57. package/src/canvas/screen/PartView.svelte +138 -72
  58. package/src/canvas/screen/ScreenBody.svelte +81 -60
  59. package/src/canvas/screen/ScreenCard.svelte +20 -20
  60. package/src/canvas/ui/CanvasToolbar.svelte +173 -85
  61. package/src/canvas/ui/FrameLayer.svelte +59 -59
  62. package/src/canvas/ui/PenLayer.svelte +39 -30
  63. package/src/canvas/ui/StylePanel.svelte +119 -102
  64. package/src/canvas/ui/canvas-grid.svelte +137 -129
  65. package/src/charts/animated-value.svelte +1 -1
  66. package/src/charts/area-chart.css +2 -5
  67. package/src/charts/area-chart.svelte +1 -1
  68. package/src/charts/bar-chart.css +2 -3
  69. package/src/charts/bar-chart.svelte +1 -1
  70. package/src/charts/charts.css +5 -17
  71. package/src/charts/crosshair.svelte +1 -1
  72. package/src/charts/dashboard/dashboard-empty.svelte +25 -25
  73. package/src/charts/dashboard/dashboard-section.svelte +24 -24
  74. package/src/charts/dashboard/data-panel.svelte +50 -50
  75. package/src/charts/dashboard/data-sort-head.svelte +56 -56
  76. package/src/charts/dashboard/data-table.svelte +138 -138
  77. package/src/charts/dashboard/panel-grid.svelte +30 -30
  78. package/src/charts/dashboard/period-filter.svelte +25 -25
  79. package/src/charts/dashboard/rating-chip.svelte +19 -19
  80. package/src/charts/dashboard/stat-band.svelte +32 -32
  81. package/src/charts/dashboard/stat-tile.svelte +106 -99
  82. package/src/charts/donut-chart.svelte +1 -1
  83. package/src/charts/edge-fade.svelte +1 -1
  84. package/src/charts/figure.svelte +1 -1
  85. package/src/charts/gauge-chart.css +4 -7
  86. package/src/charts/gauge-chart.svelte +1 -1
  87. package/src/charts/hover-focus.svelte +1 -1
  88. package/src/charts/legend.css +1 -3
  89. package/src/charts/legend.svelte +1 -1
  90. package/src/charts/line-chart.svelte +1 -1
  91. package/src/charts/number-chart.css +6 -9
  92. package/src/charts/number-chart.svelte +1 -1
  93. package/src/charts/reference-line.svelte +19 -19
  94. package/src/charts/reveal.svelte +1 -1
  95. package/src/charts/ring-chart.css +2 -4
  96. package/src/charts/ring-chart.svelte +1 -1
  97. package/src/charts/sparkline.svelte +5 -2
  98. package/src/charts/stat-card.svelte +1 -1
  99. package/src/charts/time-series-chart.css +2 -5
  100. package/src/charts/trend-pill.css +2 -4
  101. package/src/charts/trend-pill.svelte +1 -1
  102. package/src/components/copy/copy-button.svelte +93 -98
  103. package/src/components/copy/copy-button.test.ts +10 -2
  104. package/src/components/data-table/infinite-scroll.svelte +42 -42
  105. package/src/components/data-table/pagination.svelte +34 -22
  106. package/src/components/data-table/row-arrow.svelte +19 -16
  107. package/src/components/data-table/row-context-menu.svelte +52 -52
  108. package/src/components/data-table/sortable-head.svelte +25 -25
  109. package/src/components/data-table/table-skeleton.svelte +41 -36
  110. package/src/components/docs/doc-page.svelte +18 -9
  111. package/src/components/docs/on-this-page.svelte +16 -3
  112. package/src/components/docs/scroll-spy.svelte.ts +2 -3
  113. package/src/components/field-row/field-row.svelte +10 -8
  114. package/src/components/hold-to-confirm/hold-to-confirm.svelte +5 -1
  115. package/src/components/icon/icon.svelte +14 -14
  116. package/src/components/language-flag/language-flag.svelte +3 -1
  117. package/src/components/list-page/detail-empty.svelte +34 -34
  118. package/src/components/list-page/detail-header.svelte +55 -47
  119. package/src/components/list-page/detail-panel.svelte +51 -59
  120. package/src/components/list-page/detail-row.svelte +19 -19
  121. package/src/components/list-page/detail-stack.svelte +21 -21
  122. package/src/components/list-page/empty-state.svelte +30 -30
  123. package/src/components/list-page/filter-item.svelte +20 -20
  124. package/src/components/list-page/filter-popover.svelte +60 -55
  125. package/src/components/list-page/grouped-list.svelte +4 -2
  126. package/src/components/list-page/index.ts +8 -4
  127. package/src/components/list-page/list-page-shell.svelte +2 -5
  128. package/src/components/list-page/master-detail.svelte +87 -88
  129. package/src/components/list-page/notice-bar.svelte +38 -38
  130. package/src/components/list-page/prev-next.svelte +63 -63
  131. package/src/components/list-page/rail-body.svelte +18 -18
  132. package/src/components/list-page/rail-empty.svelte +23 -30
  133. package/src/components/list-page/rail-head.svelte +24 -24
  134. package/src/components/list-page/rail-row.svelte +77 -73
  135. package/src/components/list-page/section-host.ts +2 -3
  136. package/src/components/locale-switch/locale-switch.svelte +41 -41
  137. package/src/components/mark/mark.svelte +34 -38
  138. package/src/components/open-in/index.ts +1 -5
  139. package/src/components/open-in/open-in.svelte +40 -40
  140. package/src/components/picker/mark-picker.svelte +49 -49
  141. package/src/components/picker/picker.svelte +5 -3
  142. package/src/components/section-header/index.ts +1 -0
  143. package/src/components/section-header/section-header.svelte +1 -1
  144. package/src/components/section-header/section-header.test.ts +7 -1
  145. package/src/components/section-header/section-label.svelte +39 -0
  146. package/src/components/segmented/animated-tabs.svelte +31 -2
  147. package/src/components/segmented/collapse.test.ts +2 -1
  148. package/src/components/segmented/index.ts +2 -0
  149. package/src/components/segmented/segment.svelte +52 -49
  150. package/src/components/segmented/segmented-filter.svelte +79 -80
  151. package/src/components/segmented/segmented-nav.svelte +34 -40
  152. package/src/components/segmented/segmented-overflow.svelte +53 -50
  153. package/src/components/segmented/segmented-track.svelte +62 -46
  154. package/src/components/segmented/segmented.ts +2 -3
  155. package/src/components/star-rating-input/star-rating-input.svelte +103 -103
  156. package/src/components/svg/svg.svelte +4 -4
  157. package/src/components/table-view/table-view.svelte +17 -2
  158. package/src/components/table-view/table-view.test.ts +7 -1
  159. package/src/components/table-view/types.ts +11 -11
  160. package/src/components/tags-input/index.ts +13 -0
  161. package/src/components/tags-input/tags-input.svelte +305 -0
  162. package/src/components/tags-input/tags.test.ts +64 -0
  163. package/src/components/tags-input/tags.ts +142 -0
  164. package/src/components/theme/index.ts +2 -4
  165. package/src/components/theme/theme-provider.svelte +1 -3
  166. package/src/components/toolbar/index.ts +2 -0
  167. package/src/components/{list-page → toolbar}/toolbar-search.svelte +25 -25
  168. package/src/components/toolbar/toolbar.svelte +13 -9
  169. package/src/components/toolbar/toolbar.test.ts +10 -1
  170. package/src/design/index.css +21 -78
  171. package/src/design/polish.css +26 -35
  172. package/src/editor/editor-toolbar.svelte +104 -99
  173. package/src/editor/editor.svelte +296 -266
  174. package/src/editor/image-toolbar.svelte +20 -22
  175. package/src/editor/index.ts +1 -4
  176. package/src/editor/inline-editor.svelte +280 -238
  177. package/src/editor/markdown.ts +15 -15
  178. package/src/editor/renderer.svelte +71 -71
  179. package/src/editor/slash-menu.svelte +24 -27
  180. package/src/effects/animated-beam/diagrams/BeamSvg.svelte +1 -1
  181. package/src/effects/image-comparison/ImageComparison.svelte +11 -1
  182. package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +59 -46
  183. package/src/effects/magic-card/MagicCard.css +14 -7
  184. package/src/effects/marquee/Marquee.svelte +3 -5
  185. package/src/effects/reveal/observe.ts +0 -3
  186. package/src/effects/spotlight/Spotlight.svelte +1 -1
  187. package/src/effects/theme-toggle/ThemeToggle.css +25 -22
  188. package/src/effects/theme-toggle/ThemeToggle.svelte +6 -7
  189. package/src/gallery.test.ts +14 -4
  190. package/src/inbox/README.md +27 -0
  191. package/src/inbox/inbox.test.ts +214 -0
  192. package/src/inbox/index.ts +31 -0
  193. package/src/inbox/logic.ts +169 -0
  194. package/src/inbox/thread-inbox.svelte +439 -0
  195. package/src/inbox/types.ts +161 -0
  196. package/src/lib/theme-transition.ts +2 -4
  197. package/src/lib/tone.ts +2 -4
  198. package/src/lib/utils.ts +2 -2
  199. package/src/modules.test.ts +105 -0
  200. package/src/onboarding/define-tours.test.ts +55 -40
  201. package/src/onboarding/define-tours.ts +23 -23
  202. package/src/onboarding/demo.svelte +24 -5
  203. package/src/onboarding/index.ts +1 -8
  204. package/src/onboarding/onboarding-provider.svelte +19 -7
  205. package/src/onboarding/onboarding.svelte.ts +16 -16
  206. package/src/onboarding/pick.test.ts +61 -52
  207. package/src/onboarding/pick.ts +16 -13
  208. package/src/onboarding/stores.test.ts +80 -80
  209. package/src/onboarding/stores.ts +41 -39
  210. package/src/onboarding/tour-card.svelte +30 -5
  211. package/src/onboarding/tour-runner.svelte +12 -3
  212. package/src/onboarding/types.ts +20 -12
  213. package/src/onboarding/wait.ts +22 -22
  214. package/src/panel/README.md +5 -0
  215. package/src/panel/index.ts +2 -0
  216. package/src/panel/side-panel.svelte +194 -0
  217. package/src/record/README.md +3 -0
  218. package/src/record/demo-data.ts +352 -0
  219. package/src/record/field-section.svelte +57 -0
  220. package/src/record/fields.ts +194 -0
  221. package/src/record/format.ts +94 -0
  222. package/src/{tasks/record → record}/index.ts +49 -35
  223. package/src/{tasks/record → record}/info-list.svelte +145 -114
  224. package/src/record/kinds.ts +42 -0
  225. package/src/record/logic.ts +326 -0
  226. package/src/record/next-up.svelte +81 -0
  227. package/src/{tasks/record → record}/project-list.svelte +56 -50
  228. package/src/{tasks/record → record}/record-demo.svelte +130 -110
  229. package/src/{tasks/record → record}/record-header.svelte +37 -28
  230. package/src/{tasks/record → record}/record-shell.svelte +54 -54
  231. package/src/record/record-stats.svelte +48 -0
  232. package/src/record/record-timeline.svelte +251 -0
  233. package/src/record/record.test.ts +471 -0
  234. package/src/{tasks/record → record}/steps-rail.svelte +225 -216
  235. package/src/record/types.ts +299 -0
  236. package/src/record/where-we-are.svelte +125 -0
  237. package/src/shadcn/button/button.svelte +1 -1
  238. package/src/shadcn/card/card-title.svelte +1 -5
  239. package/src/shadcn/hooks/use-highlighted-code.svelte.ts +2 -13
  240. package/src/shadcn/sheet/sheet-content.svelte +2 -4
  241. package/src/shadcn/table/table-cell.svelte +2 -3
  242. package/src/shadcn/utilities.css +3 -8
  243. package/src/slides/Controls.svelte +150 -124
  244. package/src/slides/Deck.svelte +243 -238
  245. package/src/slides/Fragment.svelte +64 -57
  246. package/src/slides/Overview.svelte +106 -101
  247. package/src/slides/Presenter.svelte +300 -266
  248. package/src/slides/Slide.svelte +185 -170
  249. package/src/slides/SlideList.svelte +16 -12
  250. package/src/slides/ambient.d.ts +1 -1
  251. package/src/slides/bridges.ts +42 -23
  252. package/src/slides/deck-controller.svelte.ts +47 -35
  253. package/src/slides/demo-slides.svelte +330 -306
  254. package/src/slides/demo.svelte +164 -160
  255. package/src/slides/export/capture.ts +20 -16
  256. package/src/slides/export/ffmpeg.ts +43 -38
  257. package/src/slides/export/index.ts +5 -5
  258. package/src/slides/export/launch.ts +3 -1
  259. package/src/slides/export/pdf.ts +30 -27
  260. package/src/slides/export/types.ts +10 -8
  261. package/src/slides/index.ts +11 -11
  262. package/src/slides/labels.ts +22 -19
  263. package/src/slides/layout.ts +9 -2
  264. package/src/slides/model.ts +4 -4
  265. package/src/slides/navigation.ts +43 -31
  266. package/src/slides/theme.css +5 -7
  267. package/src/slides/types.ts +9 -10
  268. package/src/status/README.md +18 -0
  269. package/src/status/define-statuses.ts +25 -0
  270. package/src/status/index.ts +11 -0
  271. package/src/{tasks → status}/status-badge.svelte +3 -1
  272. package/src/{tasks → status}/status-dot.svelte +1 -3
  273. package/src/{tasks → status}/status-icon.svelte +1 -1
  274. package/src/status/status-types.ts +40 -0
  275. package/src/tasks/README.md +1 -1
  276. package/src/tasks/board-order.ts +2 -4
  277. package/src/tasks/demo.svelte +192 -34
  278. package/src/tasks/detail/detail-demo.svelte +75 -15
  279. package/src/tasks/detail/detail-types.ts +45 -45
  280. package/src/tasks/detail/task-detail.svelte +40 -10
  281. package/src/tasks/detail/task-property.svelte +8 -2
  282. package/src/tasks/detail/task-thread.svelte +53 -12
  283. package/src/tasks/gantt/gantt-bar.svelte +17 -6
  284. package/src/tasks/gantt/gantt-grid.svelte +40 -9
  285. package/src/tasks/gantt/gantt-group-row.svelte +8 -2
  286. package/src/tasks/gantt/gantt-header.svelte +9 -3
  287. package/src/tasks/gantt/gantt-task-row.svelte +26 -6
  288. package/src/tasks/gantt/gantt.css +2 -1
  289. package/src/tasks/gantt/gantt.test.ts +4 -2
  290. package/src/tasks/gantt/logic.test.ts +110 -20
  291. package/src/tasks/gantt/logic.ts +42 -6
  292. package/src/tasks/inbox/inbox-card.svelte +15 -7
  293. package/src/tasks/inbox/inbox-draft.svelte +1 -1
  294. package/src/tasks/inbox/inbox-logic.ts +6 -40
  295. package/src/tasks/inbox/inbox-statuses.ts +24 -24
  296. package/src/tasks/inbox/inbox-trace.svelte +9 -3
  297. package/src/tasks/inbox/inbox-types.ts +54 -58
  298. package/src/tasks/inbox/index.ts +22 -21
  299. package/src/tasks/index.ts +52 -53
  300. package/src/tasks/kanban-board.svelte +16 -12
  301. package/src/tasks/kanban-types.ts +2 -3
  302. package/src/tasks/presets/sales.ts +7 -7
  303. package/src/tasks/task-gantt.svelte +28 -8
  304. package/src/tasks/task-list.svelte +41 -17
  305. package/src/tasks/time/duration.ts +40 -40
  306. package/src/tasks/time/time-chip.svelte +9 -2
  307. package/src/tasks/time/time-dot.svelte +1 -1
  308. package/src/tasks/time/time-ring.svelte +11 -3
  309. package/src/tasks/time/time-tracker.svelte +57 -15
  310. package/src/tasks/time/time-types.ts +57 -57
  311. package/src/tasks/use-kanban-dnd.svelte.ts +2 -3
  312. package/src/thread/README.md +31 -0
  313. package/src/thread/index.ts +12 -0
  314. package/src/thread/logic.ts +61 -0
  315. package/src/thread/thread.svelte +432 -0
  316. package/src/thread/thread.test.ts +73 -0
  317. package/src/thread/types.ts +93 -0
  318. package/src/tokens/craft.css +17 -53
  319. package/src/tokens/index.css +3 -13
  320. package/src/tokens/palette.css +13 -11
  321. package/src/tokens/primitives.css +10 -23
  322. package/src/components/list-page/section-label.svelte +0 -39
  323. package/src/tasks/define-statuses.ts +0 -32
  324. package/src/tasks/inbox/inbox.svelte +0 -203
  325. package/src/tasks/record/demo-data.ts +0 -286
  326. package/src/tasks/record/field-section.svelte +0 -53
  327. package/src/tasks/record/fields.ts +0 -142
  328. package/src/tasks/record/format.ts +0 -87
  329. package/src/tasks/record/kinds.ts +0 -42
  330. package/src/tasks/record/logic.ts +0 -324
  331. package/src/tasks/record/next-up.svelte +0 -70
  332. package/src/tasks/record/record-stats.svelte +0 -48
  333. package/src/tasks/record/record-timeline.svelte +0 -231
  334. package/src/tasks/record/record.test.ts +0 -350
  335. package/src/tasks/record/types.ts +0 -280
  336. package/src/tasks/record/where-we-are.svelte +0 -121
  337. package/src/tasks/side-panel.svelte +0 -193
  338. package/src/tasks/status-types.ts +0 -40
  339. /package/src/components/{list-page → toolbar}/toolbar-trigger.ts +0 -0
  340. /package/src/{tasks → panel}/side-panel-types.ts +0 -0
  341. /package/src/{tasks/record → record}/gutter.ts +0 -0
@@ -1,38 +1,32 @@
1
1
  <script lang="ts">
2
- // =========================
3
- // IMPORTS
4
- // =========================
5
- import type { NodeProps } from "@xyflow/svelte";
6
- import "../../../pen/pen.css";
7
- import { penColorVar } from "../../../pen/colors.js";
8
- import { strokePath } from "../../../pen/stroke-path.js";
9
- import { HIGHLIGHTER_OPACITY, type StrokeData } from "../../../pen/types.js";
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import type { NodeProps } from "@xyflow/svelte";
6
+ import "../../../pen/pen.css";
7
+ import { penColorVar } from "../../../pen/colors.js";
8
+ import { strokePath } from "../../../pen/stroke-path.js";
9
+ import { HIGHLIGHTER_OPACITY, type StrokeData } from "../../../pen/types.js";
10
10
 
11
- // =========================
12
- // PROPS
13
- // =========================
14
- let { data, selected, width, height }: NodeProps = $props();
11
+ // =========================
12
+ // PROPS
13
+ // =========================
14
+ let { data, selected, width, height }: NodeProps = $props();
15
15
 
16
- // =========================
17
- // DERIVED
18
- // =========================
19
- let stroke = $derived(data as StrokeData);
20
- let path = $derived(strokePath(stroke.points, stroke));
21
- // A wide, invisible line along the centre so a thin stroke is easy to click.
22
- let hitPoints = $derived(stroke.points.map((point) => `${point[0]},${point[1]}`).join(" "));
23
- let hitWidth = $derived(Math.max(stroke.size, 14));
16
+ // =========================
17
+ // DERIVED
18
+ // =========================
19
+ let stroke = $derived(data as StrokeData);
20
+ let path = $derived(strokePath(stroke.points, stroke));
21
+ // A wide, invisible line along the centre so a thin stroke is easy to click.
22
+ let hitPoints = $derived(stroke.points.map((point) => `${point[0]},${point[1]}`).join(" "));
23
+ let hitWidth = $derived(Math.max(stroke.size, 14));
24
24
  </script>
25
25
 
26
26
  <!-- =========================== -->
27
27
  <!-- MARKUP -->
28
28
  <!-- =========================== -->
29
- <svg
30
- class="pen-stroke"
31
- {width}
32
- {height}
33
- viewBox="0 0 {width} {height}"
34
- aria-hidden="true"
35
- >
29
+ <svg class="pen-stroke" {width} {height} viewBox="0 0 {width} {height}" aria-hidden="true">
36
30
  <polyline
37
31
  class="hit"
38
32
  points={hitPoints}
@@ -1,22 +1,22 @@
1
1
  <script lang="ts">
2
- // =========================
3
- // IMPORTS
4
- // =========================
5
- import type { SketchPath } from "../../../headless/sketch.js";
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import type { SketchPath } from "../../../headless/sketch.js";
6
6
 
7
- // =========================
8
- // TYPES
9
- // =========================
10
- interface Props {
11
- rule: SketchPath[];
12
- ink: string;
13
- width: number;
14
- }
7
+ // =========================
8
+ // TYPES
9
+ // =========================
10
+ interface Props {
11
+ rule: SketchPath[];
12
+ ink: string;
13
+ width: number;
14
+ }
15
15
 
16
- // =========================
17
- // PROPS
18
- // =========================
19
- let { rule, ink, width }: Props = $props();
16
+ // =========================
17
+ // PROPS
18
+ // =========================
19
+ let { rule, ink, width }: Props = $props();
20
20
  </script>
21
21
 
22
22
  <!-- =========================== -->
@@ -24,7 +24,15 @@ let { rule, ink, width }: Props = $props();
24
24
  <!-- =========================== -->
25
25
  <svg class="pen-rule" {width} height="10" aria-hidden="true">
26
26
  {#each rule as path, i (i)}
27
- <path class="pen-line" style:--sw={path.strokeWidth} d={path.d} fill="none" stroke={ink} stroke-width={path.strokeWidth} stroke-linecap="round" />
27
+ <path
28
+ class="pen-line"
29
+ style:--sw={path.strokeWidth}
30
+ d={path.d}
31
+ fill="none"
32
+ stroke={ink}
33
+ stroke-width={path.strokeWidth}
34
+ stroke-linecap="round"
35
+ />
28
36
  {/each}
29
37
  </svg>
30
38
 
@@ -1,41 +1,41 @@
1
1
  <script lang="ts">
2
- // =========================
3
- // IMPORTS
4
- // =========================
5
- import { useStore } from "@xyflow/svelte";
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import { useStore } from "@xyflow/svelte";
6
6
 
7
- // The grab dot on a selected elbow, one size on screen. Only the edge showing it reads the zoom; a root value restyles every card per frame.
7
+ // The grab dot on a selected elbow, one size on screen. Only the edge showing it reads the zoom; a root value restyles every card per frame.
8
8
 
9
- // =========================
10
- // CONSTANTS
11
- // =========================
12
- const MIN_ZOOM = 0.05;
9
+ // =========================
10
+ // CONSTANTS
11
+ // =========================
12
+ const MIN_ZOOM = 0.05;
13
13
 
14
- // =========================
15
- // TYPES
16
- // =========================
17
- interface Props {
18
- /** The way the run moves: x slides it sideways, y up and down. */
19
- axis: "x" | "y";
20
- title: string;
21
- onpointerdown: (event: PointerEvent) => void;
22
- ondblclick: () => void;
23
- }
14
+ // =========================
15
+ // TYPES
16
+ // =========================
17
+ interface Props {
18
+ /** The way the run moves: x slides it sideways, y up and down. */
19
+ axis: "x" | "y";
20
+ title: string;
21
+ onpointerdown: (event: PointerEvent) => void;
22
+ ondblclick: () => void;
23
+ }
24
24
 
25
- // =========================
26
- // PROPS
27
- // =========================
28
- let { axis, title, onpointerdown, ondblclick }: Props = $props();
25
+ // =========================
26
+ // PROPS
27
+ // =========================
28
+ let { axis, title, onpointerdown, ondblclick }: Props = $props();
29
29
 
30
- // =========================
31
- // STATE
32
- // =========================
33
- const store = useStore();
30
+ // =========================
31
+ // STATE
32
+ // =========================
33
+ const store = useStore();
34
34
 
35
- // =========================
36
- // DERIVED
37
- // =========================
38
- let unzoom = $derived(1 / Math.max(store.viewport.zoom, MIN_ZOOM));
35
+ // =========================
36
+ // DERIVED
37
+ // =========================
38
+ let unzoom = $derived(1 / Math.max(store.viewport.zoom, MIN_ZOOM));
39
39
  </script>
40
40
 
41
41
  <!-- =========================== -->
@@ -57,20 +57,20 @@ let unzoom = $derived(1 / Math.max(store.viewport.zoom, MIN_ZOOM));
57
57
  <!-- STYLES -->
58
58
  <!-- =========================== -->
59
59
  <style>
60
- .cv-bend-handle {
61
- display: block;
62
- box-sizing: border-box;
63
- width: 12px;
64
- height: 12px;
65
- padding: 0;
66
- border: 2px solid var(--cv-chrome-surface, var(--background, #fff));
67
- border-radius: 9999px;
68
- background: var(--cv-chrome-ring, var(--ring, #4a4ad8));
69
- cursor: row-resize;
70
- touch-action: none;
71
- }
60
+ .cv-bend-handle {
61
+ display: block;
62
+ box-sizing: border-box;
63
+ width: 12px;
64
+ height: 12px;
65
+ padding: 0;
66
+ border: 2px solid var(--cv-chrome-surface, var(--background, #fff));
67
+ border-radius: 9999px;
68
+ background: var(--cv-chrome-ring, var(--ring, #4a4ad8));
69
+ cursor: row-resize;
70
+ touch-action: none;
71
+ }
72
72
 
73
- .cv-bend-x {
74
- cursor: col-resize;
75
- }
73
+ .cv-bend-x {
74
+ cursor: col-resize;
75
+ }
76
76
  </style>
@@ -1,18 +1,18 @@
1
1
  <svelte:options namespace="svg" />
2
2
 
3
3
  <script lang="ts">
4
- interface Props {
5
- id: string;
6
- from: { x: number; y: number };
7
- to: { x: number; y: number };
8
- fromColor: string;
9
- toColor: string;
10
- }
4
+ interface Props {
5
+ id: string;
6
+ from: { x: number; y: number };
7
+ to: { x: number; y: number };
8
+ fromColor: string;
9
+ toColor: string;
10
+ }
11
11
 
12
- let { id, from, to, fromColor, toColor }: Props = $props();
12
+ let { id, from, to, fromColor, toColor }: Props = $props();
13
13
 
14
- // A zero-length gradient paints nothing, so a link drawn onto itself keeps one pixel of run.
15
- let flat = $derived(Math.abs(from.x - to.x) < 0.5 && Math.abs(from.y - to.y) < 0.5);
14
+ // A zero-length gradient paints nothing, so a link drawn onto itself keeps one pixel of run.
15
+ let flat = $derived(Math.abs(from.x - to.x) < 0.5 && Math.abs(from.y - to.y) < 0.5);
16
16
  </script>
17
17
 
18
18
  <defs>
@@ -1,43 +1,59 @@
1
1
  <svelte:options namespace="svg" />
2
2
 
3
3
  <script lang="ts">
4
- // =========================
5
- // IMPORTS
6
- // =========================
7
- import { BaseEdge } from "@xyflow/svelte";
8
- import EdgeGradient from "./edge-gradient.svelte";
4
+ // =========================
5
+ // IMPORTS
6
+ // =========================
7
+ import { BaseEdge } from "@xyflow/svelte";
8
+ import EdgeGradient from "./edge-gradient.svelte";
9
9
 
10
- // =========================
11
- // TYPES
12
- // =========================
13
- interface Props {
14
- id: string;
15
- path: string;
16
- from: { x: number; y: number };
17
- to: { x: number; y: number };
18
- fromColor: string;
19
- toColor?: string;
20
- markerEnd?: string;
21
- /** The edge's own style. A stroke set here beats the gradient. */
22
- style?: string;
23
- class?: string;
24
- }
10
+ // =========================
11
+ // TYPES
12
+ // =========================
13
+ interface Props {
14
+ id: string;
15
+ path: string;
16
+ from: { x: number; y: number };
17
+ to: { x: number; y: number };
18
+ fromColor: string;
19
+ toColor?: string;
20
+ markerEnd?: string;
21
+ /** The edge's own style. A stroke set here beats the gradient. */
22
+ style?: string;
23
+ class?: string;
24
+ }
25
25
 
26
- // =========================
27
- // PROPS
28
- // =========================
29
- let { id, path, from, to, fromColor, toColor = fromColor, markerEnd, style = "", class: className = "" }: Props = $props();
26
+ // =========================
27
+ // PROPS
28
+ // =========================
29
+ let {
30
+ id,
31
+ path,
32
+ from,
33
+ to,
34
+ fromColor,
35
+ toColor = fromColor,
36
+ markerEnd,
37
+ style = "",
38
+ class: className = "",
39
+ }: Props = $props();
30
40
 
31
- // =========================
32
- // DERIVED
33
- // =========================
34
- let gradientId = $derived(`canvas-gradient-${id.replace(/[^\w-]/g, "_")}`);
41
+ // =========================
42
+ // DERIVED
43
+ // =========================
44
+ let gradientId = $derived(`canvas-gradient-${id.replace(/[^\w-]/g, "_")}`);
35
45
  </script>
36
46
 
37
47
  <!-- =========================== -->
38
48
  <!-- MARKUP -->
39
49
  <!-- =========================== -->
40
50
  <EdgeGradient id={gradientId} {from} {to} {fromColor} {toColor} />
41
- <BaseEdge {id} {path} {markerEnd} class="canvas-edge {className}" style="stroke: url(#{gradientId}); {style}" />
51
+ <BaseEdge
52
+ {id}
53
+ {path}
54
+ {markerEnd}
55
+ class="canvas-edge {className}"
56
+ style="stroke: url(#{gradientId}); {style}"
57
+ />
42
58
  <!-- Hidden until a test run crosses this link; the canvas stylesheet draws the moving dashes. -->
43
59
  <path d={path} class="canvas-edge-flow" fill="none" aria-hidden="true" />
@@ -1,6 +1,11 @@
1
1
  import { describe, expect, it } from "vite-plus/test";
2
2
  import type { Node } from "@xyflow/svelte";
3
- import { deletableIds, refuseLockedOps, toggleLock, withLockFlags } from "./lock.js";
3
+ import {
4
+ deletableIds,
5
+ refuseLockedOps,
6
+ toggleLock,
7
+ withLockFlags,
8
+ } from "./lock.js";
4
9
 
5
10
  function card(id: string, data: Record<string, unknown> = {}, extra: Partial<Node> = {}): Node {
6
11
  return { id, type: "note", position: { x: 0, y: 0 }, data, ...extra };
@@ -2,7 +2,13 @@
2
2
  // A change is one patchNode per card, so it is one undo step.
3
3
 
4
4
  import type { CanvasOp } from "../ops/ops.js";
5
- import { PEN_COLORS, SHAPE_NODE, STROKE_NODE, TEXT_NODE, type PenColor } from "../pen/types.js";
5
+ import {
6
+ PEN_COLORS,
7
+ SHAPE_NODE,
8
+ STROKE_NODE,
9
+ TEXT_NODE,
10
+ type PenColor,
11
+ } from "../pen/types.js";
6
12
 
7
13
  export type FillValue = PenColor | "none";
8
14
  export type FontWeight = "regular" | "bold";
@@ -1,5 +1,9 @@
1
1
  import { describe, expect, it } from "vite-plus/test";
2
- import { figureBoxHeight, figureRatio, sanitizeFigureSvg } from "./svg-figure.js";
2
+ import {
3
+ figureBoxHeight,
4
+ figureRatio,
5
+ sanitizeFigureSvg,
6
+ } from "./svg-figure.js";
3
7
 
4
8
  describe("sanitizeFigureSvg", () => {
5
9
  it("keeps the shapes, the text and the geometry", () => {
@@ -1,81 +1,82 @@
1
1
  <script lang="ts">
2
- // =========================
3
- // IMPORTS
4
- // =========================
5
- import type { Snippet } from "svelte";
6
- import { useStore } from "@xyflow/svelte";
7
- import SideHandles from "../chrome/side-handles.svelte";
8
- import { lodMode } from "./lod-mode.svelte.js";
9
- import { renderAll } from "./render-all.svelte.js";
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import type { Snippet } from "svelte";
6
+ import { useStore } from "@xyflow/svelte";
7
+ import SideHandles from "../chrome/side-handles.svelte";
8
+ import { lodMode } from "./lod-mode.svelte.js";
9
+ import { renderAll } from "./render-all.svelte.js";
10
10
 
11
- // Zoomed out, a card is a box at its measured size, so no arrow moves.
12
- // Never measured, selected, dragged or exported: full.
11
+ // Zoomed out, a card is a box at its measured size, so no arrow moves.
12
+ // Never measured, selected, dragged or exported: full.
13
13
 
14
- // =========================
15
- // TYPES
16
- // =========================
17
- interface Props {
18
- id: string;
19
- selected?: boolean;
20
- dragging?: boolean;
21
- /** A CSS colour: the card's own, for the box's border and icon well. */
22
- tone: string;
23
- title: string;
24
- /** The full card. */
25
- children: Snippet;
26
- }
14
+ // =========================
15
+ // TYPES
16
+ // =========================
17
+ interface Props {
18
+ id: string;
19
+ selected?: boolean;
20
+ dragging?: boolean;
21
+ /** A CSS colour: the card's own, for the box's border and icon well. */
22
+ tone: string;
23
+ title: string;
24
+ /** The full card. */
25
+ children: Snippet;
26
+ }
27
27
 
28
- // =========================
29
- // PROPS
30
- // =========================
31
- let { id, selected = false, dragging = false, tone, title, children }: Props = $props();
28
+ // =========================
29
+ // PROPS
30
+ // =========================
31
+ let { id, selected = false, dragging = false, tone, title, children }: Props = $props();
32
32
 
33
- // =========================
34
- // STATE
35
- // =========================
36
- const store = useStore();
37
- const mode = lodMode(store);
38
- let probe = $state<HTMLElement>();
39
- // xyflow keeps the size of a card that scrolled away, so it comes back as a box.
40
- let size = $state<{ width: number; height: number } | null>(measured());
41
- // Plain on purpose: only the observer below reads it.
42
- let boxed = false;
33
+ // =========================
34
+ // STATE
35
+ // =========================
36
+ const store = useStore();
37
+ const mode = lodMode(store);
38
+ let probe = $state<HTMLElement>();
39
+ // xyflow keeps the size of a card that scrolled away, so it comes back as a box.
40
+ let size = $state<{ width: number; height: number } | null>(measured());
41
+ // Plain on purpose: only the observer below reads it.
42
+ let boxed = false;
43
43
 
44
- // =========================
45
- // DERIVED
46
- // =========================
47
- let simple = $derived(mode.low && size !== null && !selected && !dragging && !renderAll.on);
44
+ // =========================
45
+ // DERIVED
46
+ // =========================
47
+ let simple = $derived(mode.low && size !== null && !selected && !dragging && !renderAll.on);
48
48
 
49
- // =========================
50
- // EFFECTS
51
- // =========================
52
- // Sizes the simple box from the full card. The observer's first call carries it, so a mount forces no layout.
53
- $effect(() => {
54
- const node = probe?.closest<HTMLElement>(".svelte-flow__node");
55
- if (!node) return;
56
- const observer = new ResizeObserver(([entry]) => {
57
- if (boxed) return;
58
- const box = entry.borderBoxSize[0];
59
- const width = Math.round(box.inlineSize);
60
- const height = Math.round(box.blockSize);
61
- if (width && height && (width !== size?.width || height !== size?.height)) size = { width, height };
49
+ // =========================
50
+ // EFFECTS
51
+ // =========================
52
+ // Sizes the simple box from the full card. The observer's first call carries it, so a mount forces no layout.
53
+ $effect(() => {
54
+ const node = probe?.closest<HTMLElement>(".svelte-flow__node");
55
+ if (!node) return;
56
+ const observer = new ResizeObserver(([entry]) => {
57
+ if (boxed) return;
58
+ const box = entry.borderBoxSize[0];
59
+ const width = Math.round(box.inlineSize);
60
+ const height = Math.round(box.blockSize);
61
+ if (width && height && (width !== size?.width || height !== size?.height))
62
+ size = { width, height };
63
+ });
64
+ observer.observe(node);
65
+ return () => observer.disconnect();
62
66
  });
63
- observer.observe(node);
64
- return () => observer.disconnect();
65
- });
66
67
 
67
- // Set after the render that swaps the box in, so the read above never sees the box's own size.
68
- $effect(() => {
69
- boxed = simple;
70
- });
68
+ // Set after the render that swaps the box in, so the read above never sees the box's own size.
69
+ $effect(() => {
70
+ boxed = simple;
71
+ });
71
72
 
72
- // =========================
73
- // FUNCTIONS
74
- // =========================
75
- function measured(): { width: number; height: number } | null {
76
- const known = store.nodeLookup.get(id)?.measured;
77
- return known?.width && known.height ? { width: known.width, height: known.height } : null;
78
- }
73
+ // =========================
74
+ // FUNCTIONS
75
+ // =========================
76
+ function measured(): { width: number; height: number } | null {
77
+ const known = store.nodeLookup.get(id)?.measured;
78
+ return known?.width && known.height ? { width: known.width, height: known.height } : null;
79
+ }
79
80
  </script>
80
81
 
81
82
  <!-- =========================== -->
@@ -83,7 +84,11 @@ function measured(): { width: number; height: number } | null {
83
84
  <!-- =========================== -->
84
85
  <span class="cv-lod-probe" bind:this={probe} hidden></span>
85
86
  {#if simple && size}
86
- <div class="cv-lod-box" style="width: {size.width}px; height: {size.height}px; --cv-lod-tone: {tone}" data-lod="simple">
87
+ <div
88
+ class="cv-lod-box"
89
+ style="width: {size.width}px; height: {size.height}px; --cv-lod-tone: {tone}"
90
+ data-lod="simple"
91
+ >
87
92
  <span class="cv-lod-well"></span>
88
93
  <span class="cv-lod-title">{title}</span>
89
94
  </div>
@@ -96,45 +101,45 @@ function measured(): { width: number; height: number } | null {
96
101
  <!-- STYLES -->
97
102
  <!-- =========================== -->
98
103
  <style>
99
- :global([data-cv-every-card] .svelte-flow__node) {
100
- animation: none;
101
- }
104
+ :global([data-cv-every-card] .svelte-flow__node) {
105
+ animation: none;
106
+ }
102
107
 
103
- /* A dot on a zoomed-out box is too small to link from; unpainted, it keeps its place for the links. */
104
- :global(.cv-lod-handle) {
105
- visibility: hidden;
106
- }
108
+ /* A dot on a zoomed-out box is too small to link from; unpainted, it keeps its place for the links. */
109
+ :global(.cv-lod-handle) {
110
+ visibility: hidden;
111
+ }
107
112
 
108
- /* The architecture card's own frame and layout (architecture-node.svelte), so selecting a card doesn't change how it looks. */
109
- .cv-lod-box {
110
- position: relative;
111
- box-sizing: border-box;
112
- display: flex;
113
- align-items: flex-start;
114
- gap: 10px;
115
- overflow: hidden;
116
- padding: var(--card-pad, 12px);
117
- border: 1px solid color-mix(in oklab, var(--cv-lod-tone) 20%, transparent);
118
- border-radius: var(--card-radius, 12px);
119
- background: var(--card, var(--cv-chrome-surface, #fff));
120
- color: var(--cv-ink, var(--foreground, #1a1a1f));
121
- contain: strict;
122
- }
113
+ /* The architecture card's own frame and layout (architecture-node.svelte), so selecting a card doesn't change how it looks. */
114
+ .cv-lod-box {
115
+ position: relative;
116
+ box-sizing: border-box;
117
+ display: flex;
118
+ align-items: flex-start;
119
+ gap: 10px;
120
+ overflow: hidden;
121
+ padding: var(--card-pad, 12px);
122
+ border: 1px solid color-mix(in oklab, var(--cv-lod-tone) 20%, transparent);
123
+ border-radius: var(--card-radius, 12px);
124
+ background: var(--card, var(--cv-chrome-surface, #fff));
125
+ color: var(--cv-ink, var(--foreground, #1a1a1f));
126
+ contain: strict;
127
+ }
123
128
 
124
- /* The icon well, without the icon. */
125
- .cv-lod-well {
126
- flex: none;
127
- width: 32px;
128
- height: 32px;
129
- border-radius: 9999px;
130
- background: color-mix(in oklab, var(--cv-lod-tone) 10%, transparent);
131
- }
129
+ /* The icon well, without the icon. */
130
+ .cv-lod-well {
131
+ flex: none;
132
+ width: 32px;
133
+ height: 32px;
134
+ border-radius: 9999px;
135
+ background: color-mix(in oklab, var(--cv-lod-tone) 10%, transparent);
136
+ }
132
137
 
133
- .cv-lod-title {
134
- overflow: hidden;
135
- font-size: 14px;
136
- font-weight: 500;
137
- line-height: 1.25;
138
- overflow-wrap: anywhere;
139
- }
138
+ .cv-lod-title {
139
+ overflow: hidden;
140
+ font-size: 14px;
141
+ font-weight: 500;
142
+ line-height: 1.25;
143
+ overflow-wrap: anywhere;
144
+ }
140
145
  </style>