@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,117 +1,130 @@
1
1
  <script lang="ts">
2
- // =========================
3
- // IMPORTS
4
- // =========================
5
- import { DotsThree, NotePencil } from "phosphor-svelte";
6
- import { SegmentedFilter } from "../../components/segmented/index.js";
7
- import { Button } from "../../shadcn/button/index.js";
8
- import { Input } from "../../shadcn/input/index.js";
9
- import * as Tabs from "../../shadcn/tabs/index.js";
10
- import RecordShell from "./record-shell.svelte";
11
- import RecordHeader from "./record-header.svelte";
12
- import WhereWeAre from "./where-we-are.svelte";
13
- import NextUp from "./next-up.svelte";
14
- import RecordStats from "./record-stats.svelte";
15
- import StepsRail from "./steps-rail.svelte";
16
- import RecordTimeline from "./record-timeline.svelte";
17
- import ProjectList from "./project-list.svelte";
18
- import FieldSection from "./field-section.svelte";
19
- import InfoList from "./info-list.svelte";
20
- import { formatAge, formatMoney, formatRange } from "./format.js";
21
- import {
22
- latestWhereWeAre,
23
- mergeClientEvents,
24
- nextAcrossProjects,
25
- rollupProjects,
26
- stepProgress,
27
- } from "./logic.js";
28
- import type { FieldValue, RecordEvent, StepDef } from "./types.js";
29
- import {
30
- DEMO_NOW,
31
- DEMO_TODAY,
32
- clientFields,
33
- clientOnlyEvents,
34
- clientProjects,
35
- clientSections,
36
- clientValues,
37
- projectFields,
38
- projectSections,
39
- stages,
40
- stepGroups,
41
- website,
42
- websiteEvents,
43
- websiteSteps,
44
- websiteValues,
45
- } from "./demo-data.js";
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import { DotsThree, NotePencil } from "phosphor-svelte";
6
+ import { SegmentedFilter } from "../components/segmented/index.js";
7
+ import { Button } from "../shadcn/button/index.js";
8
+ import { Input } from "../shadcn/input/index.js";
9
+ import * as Tabs from "../shadcn/tabs/index.js";
10
+ import RecordShell from "./record-shell.svelte";
11
+ import RecordHeader from "./record-header.svelte";
12
+ import WhereWeAre from "./where-we-are.svelte";
13
+ import NextUp from "./next-up.svelte";
14
+ import RecordStats from "./record-stats.svelte";
15
+ import StepsRail from "./steps-rail.svelte";
16
+ import RecordTimeline from "./record-timeline.svelte";
17
+ import ProjectList from "./project-list.svelte";
18
+ import FieldSection from "./field-section.svelte";
19
+ import InfoList from "./info-list.svelte";
20
+ import { formatAge, formatMoney, formatRange } from "./format.js";
21
+ import {
22
+ latestWhereWeAre,
23
+ mergeClientEvents,
24
+ nextAcrossProjects,
25
+ rollupProjects,
26
+ stepProgress,
27
+ } from "./logic.js";
28
+ import type { FieldValue, RecordEvent, StepDef } from "./types.js";
29
+ import {
30
+ DEMO_NOW,
31
+ DEMO_TODAY,
32
+ clientFields,
33
+ clientOnlyEvents,
34
+ clientProjects,
35
+ clientSections,
36
+ clientValues,
37
+ projectFields,
38
+ projectSections,
39
+ stages,
40
+ stepGroups,
41
+ website,
42
+ websiteEvents,
43
+ websiteSteps,
44
+ websiteValues,
45
+ } from "./demo-data.js";
46
46
 
47
- // =========================
48
- // STATE
49
- // =========================
50
- type Fixture = "project" | "client";
51
- let fixture = $state<Fixture>("project");
52
- let narrow = $state(false);
53
- let tab = $state<"activity" | "notes">("activity");
54
- let filter = $state("all");
55
- let steps = $state<StepDef[]>(structuredClone(websiteSteps));
56
- let activeStep = $state<string | null>("s2");
57
- let projectValues = $state<Record<string, FieldValue | undefined>>({ ...websiteValues });
58
- let personValues = $state<Record<string, FieldValue | undefined>>({ ...clientValues });
59
- let extra = $state<RecordEvent[]>([]);
60
- let draftNote = $state("");
61
- let railOpen = $state(false);
47
+ // =========================
48
+ // STATE
49
+ // =========================
50
+ type Fixture = "project" | "client";
51
+ let fixture = $state<Fixture>("project");
52
+ let narrow = $state(false);
53
+ let tab = $state<"activity" | "notes">("activity");
54
+ let filter = $state("all");
55
+ let steps = $state<StepDef[]>(structuredClone(websiteSteps));
56
+ let activeStep = $state<string | null>("s2");
57
+ let projectValues = $state<Record<string, FieldValue | undefined>>({ ...websiteValues });
58
+ let personValues = $state<Record<string, FieldValue | undefined>>({ ...clientValues });
59
+ let extra = $state<RecordEvent[]>([]);
60
+ let draftNote = $state("");
61
+ let railOpen = $state(false);
62
62
 
63
- // =========================
64
- // DERIVED
65
- // =========================
66
- const locale = "en-GB";
67
- let projectEvents = $derived([...extra, ...websiteEvents]);
68
- let clientEvents = $derived(
69
- mergeClientEvents(
70
- clientOnlyEvents,
71
- clientProjects.map((p) => ({
72
- id: p.summary.id,
73
- name: p.summary.name,
74
- href: p.summary.href,
75
- events: p.events,
76
- })),
77
- ),
78
- );
79
- let summaries = $derived(clientProjects.map((p) => p.summary));
80
- let rollup = $derived(rollupProjects(summaries, stages));
81
- let latest = $derived(latestWhereWeAre(summaries));
82
- let next = $derived(nextAcrossProjects(summaries, stages));
83
- let progress = $derived(stepProgress(steps));
84
- let notes = $derived(projectEvents.filter((e) => e.kind === "note"));
85
- let stage = $derived(stages.find((s) => s.key === website.stageKey));
63
+ // =========================
64
+ // DERIVED
65
+ // =========================
66
+ const locale = "en-GB";
67
+ let projectEvents = $derived([...extra, ...websiteEvents]);
68
+ let clientEvents = $derived(
69
+ mergeClientEvents(
70
+ clientOnlyEvents,
71
+ clientProjects.map((p) => ({
72
+ id: p.summary.id,
73
+ name: p.summary.name,
74
+ href: p.summary.href,
75
+ events: p.events,
76
+ })),
77
+ ),
78
+ );
79
+ let summaries = $derived(clientProjects.map((p) => p.summary));
80
+ let rollup = $derived(rollupProjects(summaries, stages));
81
+ let latest = $derived(latestWhereWeAre(summaries));
82
+ let next = $derived(nextAcrossProjects(summaries, stages));
83
+ let progress = $derived(stepProgress(steps));
84
+ let notes = $derived(projectEvents.filter((e) => e.kind === "note"));
85
+ let stage = $derived(stages.find((s) => s.key === website.stageKey));
86
86
 
87
- let clientStats = $derived.by(() => {
88
- const eur = rollup.totals.EUR;
89
- return [
90
- { label: "Projects", value: String(rollup.count), sub: `${rollup.activeCount} active` },
91
- { label: "Pipeline", value: formatMoney(eur?.pipeline ?? 0, "EUR", locale, true) },
92
- { label: "Won", value: formatMoney(eur?.won ?? 0, "EUR", locale, true) },
93
- { label: "Paid", value: formatMoney(eur?.paid ?? 0, "EUR", locale, true), tone: "good" as const },
94
- { label: "Last call", value: rollup.lastCallAt ? formatAge(rollup.lastCallAt, DEMO_NOW, locale) : "None yet" },
95
- ];
96
- });
87
+ let clientStats = $derived.by(() => {
88
+ const eur = rollup.totals.EUR;
89
+ return [
90
+ { label: "Projects", value: String(rollup.count), sub: `${rollup.activeCount} active` },
91
+ { label: "Pipeline", value: formatMoney(eur?.pipeline ?? 0, "EUR", locale, true) },
92
+ { label: "Won", value: formatMoney(eur?.won ?? 0, "EUR", locale, true) },
93
+ {
94
+ label: "Paid",
95
+ value: formatMoney(eur?.paid ?? 0, "EUR", locale, true),
96
+ tone: "good" as const,
97
+ },
98
+ {
99
+ label: "Last call",
100
+ value: rollup.lastCallAt ? formatAge(rollup.lastCallAt, DEMO_NOW, locale) : "None yet",
101
+ },
102
+ ];
103
+ });
97
104
 
98
- // =========================
99
- // FUNCTIONS
100
- // =========================
101
- function addNote() {
102
- const title = draftNote.trim();
103
- if (!title) return;
104
- extra = [
105
- { id: `n${extra.length}`, kind: "note", occurredAt: DEMO_NOW.toISOString(), title, actor: "Ramzi" },
106
- ...extra,
107
- ];
108
- draftNote = "";
109
- }
105
+ // =========================
106
+ // FUNCTIONS
107
+ // =========================
108
+ function addNote() {
109
+ const title = draftNote.trim();
110
+ if (!title) return;
111
+ extra = [
112
+ {
113
+ id: `n${extra.length}`,
114
+ kind: "note",
115
+ occurredAt: DEMO_NOW.toISOString(),
116
+ title,
117
+ actor: "Ramzi",
118
+ },
119
+ ...extra,
120
+ ];
121
+ draftNote = "";
122
+ }
110
123
 
111
- // A real host would round-trip here. The pause lets the rail show its optimistic order.
112
- async function pause() {
113
- await new Promise((resolve) => setTimeout(resolve, 250));
114
- }
124
+ // A real host would round-trip here. The pause lets the rail show its optimistic order.
125
+ async function pause() {
126
+ await new Promise((resolve) => setTimeout(resolve, 250));
127
+ }
115
128
  </script>
116
129
 
117
130
  <!-- =========================== -->
@@ -125,7 +138,12 @@ async function pause() {
125
138
  addNote();
126
139
  }}
127
140
  >
128
- <Input bind:value={draftNote} placeholder="Write a note" aria-label="Write a note" class="flex-1" />
141
+ <Input
142
+ bind:value={draftNote}
143
+ placeholder="Write a note"
144
+ aria-label="Write a note"
145
+ class="flex-1"
146
+ />
129
147
  <Button type="submit" variant="outline" disabled={!draftNote.trim()}>
130
148
  <NotePencil data-icon="inline-start" />
131
149
  Add
@@ -188,7 +206,9 @@ async function pause() {
188
206
  ]}
189
207
  >
190
208
  {#snippet actions()}
191
- <Button variant="ghost" size="sm" icon aria-label="More actions"><DotsThree weight="bold" /></Button>
209
+ <Button variant="ghost" size="sm" icon aria-label="More actions"
210
+ ><DotsThree weight="bold" /></Button
211
+ >
192
212
  {/snippet}
193
213
  </RecordHeader>
194
214
  {/snippet}
@@ -1,33 +1,42 @@
1
1
  <script lang="ts">
2
- // =========================
3
- // IMPORTS
4
- // =========================
5
- import type { Snippet } from "svelte";
6
- import { CaretLeft } from "phosphor-svelte";
7
- import { cn } from "../../lib/utils.js";
8
- import type { Tone } from "../../lib/tone.js";
9
- import StatusBadge from "../status-badge.svelte";
10
- import { gutterClass } from "./gutter.js";
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import type { Snippet } from "svelte";
6
+ import { CaretLeft } from "phosphor-svelte";
7
+ import { cn } from "../lib/utils.js";
8
+ import type { Tone } from "../lib/tone.js";
9
+ import StatusBadge from "../status/status-badge.svelte";
10
+ import { gutterClass } from "./gutter.js";
11
11
 
12
- // =========================
13
- // PROPS
14
- // =========================
15
- interface Props {
16
- title: string;
17
- /** A mark drawn before the title: a logo, an avatar. */
18
- logo?: Snippet;
19
- /** The stage, in the agency's own word and the tone of its category. */
20
- stage?: { label: string; tone: Tone; detail?: string | null } | null;
21
- /** What this record sits under, such as the client of a project. */
22
- parent?: { label: string; href: string } | null;
23
- /** Quiet facts after the stage: a value, dates. */
24
- facts?: string[];
25
- actions?: Snippet;
26
- /** Under the title row, for a stat strip. */
27
- children?: Snippet;
28
- class?: string;
29
- }
30
- let { title, logo, stage, parent, facts = [], actions, children, class: className }: Props = $props();
12
+ // =========================
13
+ // PROPS
14
+ // =========================
15
+ interface Props {
16
+ title: string;
17
+ /** A mark drawn before the title: a logo, an avatar. */
18
+ logo?: Snippet;
19
+ /** The stage, in the agency's own word and the tone of its category. */
20
+ stage?: { label: string; tone: Tone; detail?: string | null } | null;
21
+ /** What this record sits under, such as the client of a project. */
22
+ parent?: { label: string; href: string } | null;
23
+ /** Quiet facts after the stage: a value, dates. */
24
+ facts?: string[];
25
+ actions?: Snippet;
26
+ /** Under the title row, for a stat strip. */
27
+ children?: Snippet;
28
+ class?: string;
29
+ }
30
+ let {
31
+ title,
32
+ logo,
33
+ stage,
34
+ parent,
35
+ facts = [],
36
+ actions,
37
+ children,
38
+ class: className,
39
+ }: Props = $props();
31
40
  </script>
32
41
 
33
42
  <!-- =========================== -->
@@ -1,60 +1,60 @@
1
1
  <script lang="ts" generics="T extends string = string">
2
- // =========================
3
- // IMPORTS
4
- // =========================
5
- import type { Snippet } from "svelte";
6
- import { CaretRight } from "phosphor-svelte";
7
- import { cn } from "../../lib/utils.js";
8
- import { AnimatedTabs, type TabDef } from "../../components/segmented/index.js";
9
- import * as Sheet from "../../shadcn/sheet/index.js";
10
- import { Progress } from "../../shadcn/progress/index.js";
11
- import { gutterClass } from "./gutter.js";
12
- import { resolveLabels, type RecordLabels } from "./types.js";
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import type { Snippet } from "svelte";
6
+ import { CaretRight } from "phosphor-svelte";
7
+ import { cn } from "../lib/utils.js";
8
+ import { AnimatedTabs, type TabDef } from "../components/segmented/index.js";
9
+ import * as Sheet from "../shadcn/sheet/index.js";
10
+ import { Progress } from "../shadcn/progress/index.js";
11
+ import { gutterClass } from "./gutter.js";
12
+ import { resolveLabels, type RecordLabels } from "./types.js";
13
13
 
14
- // =========================
15
- // PROPS
16
- // =========================
17
- interface Props {
18
- header: Snippet;
19
- /** Where we are, next up, stats: whatever sits between the header and the body. */
20
- banner?: Snippet;
21
- /** The tab row. Put each panel in a `Tabs.Content` from `@heyramzi/ui/shadcn/tabs`. */
22
- tabs?: readonly TabDef<T>[];
23
- tab?: T;
24
- tabsLabel?: string;
25
- /** The side rail. Docked at 48rem and wider, a sheet behind one row under that. */
26
- rail?: Snippet;
27
- /** The sheet's title, read out by screen readers. Defaults to the steps label. */
28
- railTitle?: string;
29
- /** Fills the narrow row's bar. Leave it out for a row with no progress. */
30
- railProgress?: { done: number; total: number } | null;
31
- railOpen?: boolean;
32
- children: Snippet;
33
- labels?: Partial<RecordLabels>;
34
- class?: string;
35
- }
36
- let {
37
- header,
38
- banner,
39
- tabs,
40
- tab = $bindable(),
41
- tabsLabel,
42
- rail,
43
- railTitle,
44
- railProgress = null,
45
- railOpen = $bindable(false),
46
- children,
47
- labels,
48
- class: className,
49
- }: Props = $props();
14
+ // =========================
15
+ // PROPS
16
+ // =========================
17
+ interface Props {
18
+ header: Snippet;
19
+ /** Where we are, next up, stats: whatever sits between the header and the body. */
20
+ banner?: Snippet;
21
+ /** The tab row. Put each panel in a `Tabs.Content` from `@heyramzi/ui/shadcn/tabs`. */
22
+ tabs?: readonly TabDef<T>[];
23
+ tab?: T;
24
+ tabsLabel?: string;
25
+ /** The side rail. Docked at 48rem and wider, a sheet behind one row under that. */
26
+ rail?: Snippet;
27
+ /** The sheet's title, read out by screen readers. Defaults to the steps label. */
28
+ railTitle?: string;
29
+ /** Fills the narrow row's bar. Leave it out for a row with no progress. */
30
+ railProgress?: { done: number; total: number } | null;
31
+ railOpen?: boolean;
32
+ children: Snippet;
33
+ labels?: Partial<RecordLabels>;
34
+ class?: string;
35
+ }
36
+ let {
37
+ header,
38
+ banner,
39
+ tabs,
40
+ tab = $bindable(),
41
+ tabsLabel,
42
+ rail,
43
+ railTitle,
44
+ railProgress = null,
45
+ railOpen = $bindable(false),
46
+ children,
47
+ labels,
48
+ class: className,
49
+ }: Props = $props();
50
50
 
51
- // =========================
52
- // DERIVED
53
- // =========================
54
- let t = $derived(resolveLabels(labels));
55
- let percent = $derived(
56
- railProgress && railProgress.total > 0 ? (railProgress.done / railProgress.total) * 100 : 0,
57
- );
51
+ // =========================
52
+ // DERIVED
53
+ // =========================
54
+ let t = $derived(resolveLabels(labels));
55
+ let percent = $derived(
56
+ railProgress && railProgress.total > 0 ? (railProgress.done / railProgress.total) * 100 : 0,
57
+ );
58
58
  </script>
59
59
 
60
60
  <!-- =========================== -->
@@ -0,0 +1,48 @@
1
+ <script lang="ts">
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import { cn } from "../lib/utils.js";
6
+ import type { PanelStat } from "../panel/side-panel-types.js";
7
+ import { gutterClass } from "./gutter.js";
8
+
9
+ // =========================
10
+ // PROPS
11
+ // =========================
12
+ interface Props {
13
+ stats: PanelStat[];
14
+ /** Sits flush with the record's gutter. Off inside a card. */
15
+ gutter?: boolean;
16
+ class?: string;
17
+ }
18
+ let { stats, gutter = true, class: className }: Props = $props();
19
+
20
+ // =========================
21
+ // DERIVED
22
+ // =========================
23
+ const TONE = {
24
+ default: "",
25
+ muted: "text-muted-foreground",
26
+ good: "text-success",
27
+ bad: "text-destructive",
28
+ } as const;
29
+ </script>
30
+
31
+ <!-- =========================== -->
32
+ <!-- MARKUP -->
33
+ <!-- =========================== -->
34
+ {#if stats.length > 0}
35
+ <dl class={cn("flex flex-wrap gap-x-6 gap-y-2", gutter && gutterClass, className)}>
36
+ {#each stats as stat (stat.label)}
37
+ <div class="min-w-0">
38
+ <dt class="text-xs text-muted-foreground">{stat.label}</dt>
39
+ <dd class={cn("text-sm font-medium tabular-nums", TONE[stat.tone ?? "default"])}>
40
+ {stat.value}
41
+ {#if stat.sub}
42
+ <span class="text-xs font-normal text-muted-foreground">{stat.sub}</span>
43
+ {/if}
44
+ </dd>
45
+ </div>
46
+ {/each}
47
+ </dl>
48
+ {/if}