@heyramzi/ui 2.1.0 → 2.3.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 (317) hide show
  1. package/COMPONENTS.md +1 -1
  2. package/package.json +7 -8
  3. package/scripts/sync-shadcn.mjs +3 -4
  4. package/src/agents/agent-avatar.svelte +604 -575
  5. package/src/agents/agent-cast.svelte +179 -183
  6. package/src/agents/demo.svelte +125 -113
  7. package/src/agents/helpers.ts +23 -17
  8. package/src/agents/index.ts +4 -4
  9. package/src/agents/page-state.ts +6 -6
  10. package/src/agents/types.ts +6 -6
  11. package/src/ai/ai-button/AiButton.svelte +4 -12
  12. package/src/ai/generation-progress/GenerationProgress.svelte +10 -3
  13. package/src/ai/prompt-input/PromptInputTextarea.svelte +1 -2
  14. package/src/ai/response/Response.css +2 -3
  15. package/src/animations/avatar-group-hover.css +2 -16
  16. package/src/animations/card-tilt.css +3 -6
  17. package/src/animations/digit-pop-in.css +2 -15
  18. package/src/animations/dropdown.css +4 -17
  19. package/src/animations/input-clear-dissolve.css +5 -18
  20. package/src/animations/input-shake.css +9 -41
  21. package/src/animations/learn-more-hover.css +17 -9
  22. package/src/animations/like-button.css +2 -4
  23. package/src/animations/page-side-by-side.css +2 -10
  24. package/src/animations/plus-menu-morph.css +2 -5
  25. package/src/animations/shimmer-text.css +5 -18
  26. package/src/animations/spinning-counter.css +2 -6
  27. package/src/animations/success-check.css +2 -15
  28. package/src/animations/thinking-states.css +2 -7
  29. package/src/brand/brand.test.ts +21 -5
  30. package/src/brand/index.ts +4 -10
  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/canvas-cleanup.test.ts +1 -1
  49. package/src/canvas/headless/svg-figure.test.ts +5 -1
  50. package/src/canvas/lod/lod-switch.svelte +111 -106
  51. package/src/canvas/ops/ops.ts +1 -1
  52. package/src/canvas/pen/PenField.svelte +87 -81
  53. package/src/canvas/pen/PenOverlay.svelte +127 -127
  54. package/src/canvas/pen/ShapeNode.svelte +31 -32
  55. package/src/canvas/pen/TextNode.svelte +54 -53
  56. package/src/canvas/pen/host-field.test.svelte +7 -7
  57. package/src/canvas/pen/shapes.ts +7 -1
  58. package/src/canvas/screen/GlyphIcon.svelte +22 -17
  59. package/src/canvas/screen/PartView.svelte +138 -72
  60. package/src/canvas/screen/ScreenBody.svelte +81 -60
  61. package/src/canvas/screen/ScreenCard.svelte +20 -20
  62. package/src/canvas/ui/CanvasToolbar.svelte +173 -85
  63. package/src/canvas/ui/FrameLayer.svelte +59 -59
  64. package/src/canvas/ui/PenLayer.svelte +39 -30
  65. package/src/canvas/ui/StylePanel.svelte +119 -102
  66. package/src/canvas/ui/canvas-grid.svelte +137 -129
  67. package/src/charts/animated-value.svelte +1 -1
  68. package/src/charts/area-chart.css +2 -5
  69. package/src/charts/area-chart.svelte +1 -1
  70. package/src/charts/bar-chart.css +2 -3
  71. package/src/charts/bar-chart.svelte +1 -1
  72. package/src/charts/charts.css +5 -17
  73. package/src/charts/crosshair.svelte +1 -1
  74. package/src/charts/dashboard/dashboard-empty.svelte +25 -25
  75. package/src/charts/dashboard/dashboard-section.svelte +24 -24
  76. package/src/charts/dashboard/data-panel.svelte +50 -50
  77. package/src/charts/dashboard/data-sort-head.svelte +56 -56
  78. package/src/charts/dashboard/data-table.svelte +138 -138
  79. package/src/charts/dashboard/panel-grid.svelte +30 -30
  80. package/src/charts/dashboard/period-filter.svelte +25 -25
  81. package/src/charts/dashboard/rating-chip.svelte +19 -19
  82. package/src/charts/dashboard/stat-band.svelte +32 -32
  83. package/src/charts/dashboard/stat-tile.svelte +106 -99
  84. package/src/charts/donut-chart.svelte +1 -1
  85. package/src/charts/edge-fade.svelte +1 -1
  86. package/src/charts/figure.svelte +1 -1
  87. package/src/charts/gauge-chart.css +4 -7
  88. package/src/charts/gauge-chart.svelte +1 -1
  89. package/src/charts/hover-focus.svelte +1 -1
  90. package/src/charts/legend.css +1 -3
  91. package/src/charts/legend.svelte +1 -1
  92. package/src/charts/line-chart.svelte +1 -1
  93. package/src/charts/number-chart.css +6 -9
  94. package/src/charts/number-chart.svelte +1 -1
  95. package/src/charts/reference-line.svelte +19 -19
  96. package/src/charts/reveal.svelte +1 -1
  97. package/src/charts/ring-chart.css +2 -4
  98. package/src/charts/ring-chart.svelte +1 -1
  99. package/src/charts/sparkline.svelte +5 -2
  100. package/src/charts/stat-card.svelte +1 -1
  101. package/src/charts/time-series-chart.css +2 -5
  102. package/src/charts/trend-pill.css +2 -4
  103. package/src/charts/trend-pill.svelte +1 -1
  104. package/src/components/copy/copy-button.svelte +93 -98
  105. package/src/components/copy/copy-button.test.ts +10 -2
  106. package/src/components/data-table/infinite-scroll.svelte +42 -42
  107. package/src/components/data-table/pagination.svelte +34 -22
  108. package/src/components/data-table/row-arrow.svelte +19 -16
  109. package/src/components/data-table/row-context-menu.svelte +52 -52
  110. package/src/components/data-table/sortable-head.svelte +25 -25
  111. package/src/components/data-table/table-skeleton.svelte +41 -36
  112. package/src/components/docs/doc-page.svelte +18 -9
  113. package/src/components/docs/on-this-page.svelte +16 -3
  114. package/src/components/docs/scroll-spy.svelte.ts +2 -3
  115. package/src/components/field-row/field-row.svelte +10 -8
  116. package/src/components/hold-to-confirm/hold-to-confirm.svelte +5 -1
  117. package/src/components/icon/icon.svelte +14 -14
  118. package/src/components/language-flag/language-flag.svelte +3 -1
  119. package/src/components/list-page/detail-empty.svelte +34 -34
  120. package/src/components/list-page/detail-header.svelte +55 -47
  121. package/src/components/list-page/detail-panel.svelte +51 -59
  122. package/src/components/list-page/detail-row.svelte +19 -19
  123. package/src/components/list-page/detail-stack.svelte +21 -21
  124. package/src/components/list-page/empty-state.svelte +30 -30
  125. package/src/components/list-page/filter-item.svelte +20 -20
  126. package/src/components/list-page/filter-popover.svelte +60 -55
  127. package/src/components/list-page/grouped-list.svelte +4 -2
  128. package/src/components/list-page/index.ts +5 -1
  129. package/src/components/list-page/list-page-shell.svelte +2 -5
  130. package/src/components/list-page/master-detail.svelte +87 -88
  131. package/src/components/list-page/notice-bar.svelte +38 -38
  132. package/src/components/list-page/prev-next.svelte +63 -63
  133. package/src/components/list-page/rail-body.svelte +18 -18
  134. package/src/components/list-page/rail-empty.svelte +23 -30
  135. package/src/components/list-page/rail-head.svelte +24 -24
  136. package/src/components/list-page/rail-row.svelte +77 -73
  137. package/src/components/list-page/section-host.ts +2 -3
  138. package/src/components/locale-switch/locale-switch.svelte +41 -41
  139. package/src/components/mark/mark.svelte +34 -38
  140. package/src/components/open-in/index.ts +1 -5
  141. package/src/components/open-in/open-in.svelte +40 -40
  142. package/src/components/picker/mark-picker.svelte +49 -49
  143. package/src/components/picker/picker.svelte +5 -3
  144. package/src/components/section-header/section-header.test.ts +7 -1
  145. package/src/components/section-header/section-label.svelte +20 -20
  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/index.ts +1 -1
  158. package/src/components/table-view/table-view.svelte +352 -13
  159. package/src/components/table-view/table-view.test.ts +108 -1
  160. package/src/components/table-view/types.ts +22 -11
  161. package/src/components/tags-input/index.ts +13 -0
  162. package/src/components/tags-input/tags-input.svelte +305 -0
  163. package/src/components/tags-input/tags.test.ts +64 -0
  164. package/src/components/tags-input/tags.ts +142 -0
  165. package/src/components/theme/index.ts +2 -4
  166. package/src/components/theme/theme-provider.svelte +1 -3
  167. package/src/components/toolbar/toolbar-search.svelte +25 -25
  168. package/src/components/toolbar/toolbar.svelte +11 -7
  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/icons/trades.ts +1 -1
  191. package/src/inbox/README.md +1 -3
  192. package/src/inbox/inbox.test.ts +181 -138
  193. package/src/inbox/index.ts +20 -20
  194. package/src/inbox/logic.ts +114 -111
  195. package/src/inbox/thread-inbox.svelte +227 -151
  196. package/src/inbox/types.ts +130 -108
  197. package/src/lib/theme-transition.ts +2 -4
  198. package/src/lib/tone.ts +2 -4
  199. package/src/lib/utils.ts +2 -2
  200. package/src/modules.test.ts +79 -69
  201. package/src/onboarding/define-tours.test.ts +55 -40
  202. package/src/onboarding/define-tours.ts +23 -23
  203. package/src/onboarding/demo.svelte +24 -5
  204. package/src/onboarding/index.ts +1 -8
  205. package/src/onboarding/onboarding-provider.svelte +19 -7
  206. package/src/onboarding/onboarding.svelte.ts +16 -16
  207. package/src/onboarding/pick.test.ts +61 -52
  208. package/src/onboarding/pick.ts +16 -13
  209. package/src/onboarding/stores.test.ts +80 -80
  210. package/src/onboarding/stores.ts +41 -39
  211. package/src/onboarding/tour-card.svelte +30 -5
  212. package/src/onboarding/tour-runner.svelte +12 -3
  213. package/src/onboarding/types.ts +20 -12
  214. package/src/onboarding/wait.ts +22 -22
  215. package/src/panel/side-panel.svelte +94 -93
  216. package/src/record/demo-data.ts +291 -225
  217. package/src/record/field-section.svelte +38 -34
  218. package/src/record/fields.ts +148 -96
  219. package/src/record/format.ts +63 -56
  220. package/src/record/index.ts +49 -35
  221. package/src/record/info-list.svelte +145 -114
  222. package/src/record/kinds.ts +31 -31
  223. package/src/record/logic.ts +216 -214
  224. package/src/record/next-up.svelte +45 -34
  225. package/src/record/project-list.svelte +56 -50
  226. package/src/record/record-demo.svelte +130 -110
  227. package/src/record/record-header.svelte +37 -28
  228. package/src/record/record-shell.svelte +54 -54
  229. package/src/record/record-stats.svelte +25 -25
  230. package/src/record/record-timeline.svelte +134 -114
  231. package/src/record/record.test.ts +430 -309
  232. package/src/record/steps-rail.svelte +225 -216
  233. package/src/record/types.ts +234 -215
  234. package/src/record/where-we-are.svelte +62 -58
  235. package/src/shadcn/button/button.svelte +1 -1
  236. package/src/shadcn/card/card-title.svelte +1 -5
  237. package/src/shadcn/hooks/use-highlighted-code.svelte.ts +2 -13
  238. package/src/shadcn/sheet/sheet-content.svelte +2 -4
  239. package/src/shadcn/table/table-cell.svelte +2 -3
  240. package/src/shadcn/utilities.css +3 -8
  241. package/src/slides/Controls.svelte +150 -124
  242. package/src/slides/Deck.svelte +243 -238
  243. package/src/slides/Fragment.svelte +64 -57
  244. package/src/slides/Overview.svelte +106 -101
  245. package/src/slides/Presenter.svelte +300 -266
  246. package/src/slides/Slide.svelte +185 -170
  247. package/src/slides/SlideList.svelte +16 -12
  248. package/src/slides/ambient.d.ts +1 -1
  249. package/src/slides/bridges.ts +42 -23
  250. package/src/slides/deck-controller.svelte.ts +47 -35
  251. package/src/slides/demo-slides.svelte +330 -306
  252. package/src/slides/demo.svelte +164 -160
  253. package/src/slides/export/capture.ts +20 -16
  254. package/src/slides/export/ffmpeg.ts +43 -38
  255. package/src/slides/export/index.ts +5 -5
  256. package/src/slides/export/launch.ts +3 -1
  257. package/src/slides/export/pdf.ts +30 -27
  258. package/src/slides/export/types.ts +10 -8
  259. package/src/slides/index.ts +11 -11
  260. package/src/slides/labels.ts +22 -19
  261. package/src/slides/layout.ts +9 -2
  262. package/src/slides/model.ts +4 -4
  263. package/src/slides/navigation.ts +43 -31
  264. package/src/slides/theme.css +5 -7
  265. package/src/slides/types.ts +9 -10
  266. package/src/status/define-statuses.ts +17 -24
  267. package/src/status/index.ts +5 -5
  268. package/src/status/status-badge.svelte +3 -1
  269. package/src/status/status-dot.svelte +1 -3
  270. package/src/status/status-icon.svelte +1 -1
  271. package/src/status/status-types.ts +21 -21
  272. package/src/tasks/board-order.ts +2 -4
  273. package/src/tasks/demo.svelte +189 -31
  274. package/src/tasks/detail/detail-demo.svelte +73 -13
  275. package/src/tasks/detail/detail-types.ts +45 -45
  276. package/src/tasks/detail/task-detail.svelte +40 -10
  277. package/src/tasks/detail/task-property.svelte +8 -2
  278. package/src/tasks/detail/task-thread.svelte +53 -12
  279. package/src/tasks/gantt/gantt-bar.svelte +17 -6
  280. package/src/tasks/gantt/gantt-grid.svelte +40 -9
  281. package/src/tasks/gantt/gantt-group-row.svelte +8 -2
  282. package/src/tasks/gantt/gantt-header.svelte +9 -3
  283. package/src/tasks/gantt/gantt-task-row.svelte +26 -6
  284. package/src/tasks/gantt/gantt.css +2 -1
  285. package/src/tasks/gantt/gantt.test.ts +3 -1
  286. package/src/tasks/gantt/logic.test.ts +110 -20
  287. package/src/tasks/gantt/logic.ts +42 -6
  288. package/src/tasks/inbox/inbox-card.svelte +13 -5
  289. package/src/tasks/inbox/inbox-draft.svelte +1 -1
  290. package/src/tasks/inbox/inbox-logic.ts +6 -40
  291. package/src/tasks/inbox/inbox-statuses.ts +23 -23
  292. package/src/tasks/inbox/inbox-trace.svelte +9 -3
  293. package/src/tasks/inbox/inbox-types.ts +54 -58
  294. package/src/tasks/inbox/index.ts +22 -21
  295. package/src/tasks/index.ts +49 -52
  296. package/src/tasks/kanban-board.svelte +16 -12
  297. package/src/tasks/kanban-types.ts +2 -3
  298. package/src/tasks/presets/sales.ts +6 -6
  299. package/src/tasks/task-gantt.svelte +28 -8
  300. package/src/tasks/task-list.svelte +41 -17
  301. package/src/tasks/time/duration.ts +40 -40
  302. package/src/tasks/time/time-chip.svelte +9 -2
  303. package/src/tasks/time/time-dot.svelte +1 -1
  304. package/src/tasks/time/time-ring.svelte +11 -3
  305. package/src/tasks/time/time-tracker.svelte +57 -15
  306. package/src/tasks/time/time-types.ts +57 -57
  307. package/src/tasks/use-kanban-dnd.svelte.ts +2 -3
  308. package/src/thread/index.ts +7 -7
  309. package/src/thread/logic.ts +36 -33
  310. package/src/thread/thread.svelte +82 -16
  311. package/src/thread/thread.test.ts +58 -47
  312. package/src/thread/types.ts +68 -68
  313. package/src/tokens/craft.css +17 -53
  314. package/src/tokens/index.css +3 -13
  315. package/src/tokens/palette.css +13 -11
  316. package/src/tokens/primitives.css +10 -23
  317. package/src/tasks/inbox/inbox.svelte +0 -203
@@ -1,127 +1,135 @@
1
1
  <script lang="ts">
2
- // =========================
3
- // IMPORTS
4
- // =========================
5
- import { Check, CaretUpDown } from "phosphor-svelte";
6
- import { cn } from "../lib/utils.js";
7
- import { Button } from "../shadcn/button/index.js";
8
- import { Input } from "../shadcn/input/index.js";
9
- import { Textarea } from "../shadcn/textarea/index.js";
10
- import { Spinner } from "../shadcn/spinner/index.js";
11
- import * as Select from "../shadcn/select/index.js";
12
- import * as Popover from "../shadcn/popover/index.js";
13
- import * as Command from "../shadcn/command/index.js";
14
- import StatusBadge from "../status/status-badge.svelte";
15
- import { resolveLabels, type InfoRow, type RecordLabels } from "./types.js";
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import { Check, CaretUpDown } from "phosphor-svelte";
6
+ import { cn } from "../lib/utils.js";
7
+ import { Button } from "../shadcn/button/index.js";
8
+ import { Input } from "../shadcn/input/index.js";
9
+ import { Textarea } from "../shadcn/textarea/index.js";
10
+ import { Spinner } from "../shadcn/spinner/index.js";
11
+ import * as Select from "../shadcn/select/index.js";
12
+ import * as Popover from "../shadcn/popover/index.js";
13
+ import * as Command from "../shadcn/command/index.js";
14
+ import { TagsInput } from "../components/tags-input/index.js";
15
+ import StatusBadge from "../status/status-badge.svelte";
16
+ import { resolveLabels, type InfoRow, type RecordLabels } from "./types.js";
16
17
 
17
- // =========================
18
- // PROPS
19
- // =========================
20
- interface Props {
21
- rows: InfoRow[];
22
- /** A heading over the list. Left out, nothing is drawn. */
23
- title?: string | null;
24
- labels?: Partial<RecordLabels>;
25
- class?: string;
26
- }
27
- let { rows, title = null, labels, class: className }: Props = $props();
28
-
29
- // =========================
30
- // STATE
31
- // =========================
32
- let editing = $state<string | null>(null);
33
- let draft = $state("");
34
- let saving = $state<string | null>(null);
35
- let failed = $state<{ key: string; text: string } | null>(null);
36
- let pickerOpen = $state<string | null>(null);
18
+ // =========================
19
+ // PROPS
20
+ // =========================
21
+ interface Props {
22
+ rows: InfoRow[];
23
+ /** A heading over the list. Left out, nothing is drawn. */
24
+ title?: string | null;
25
+ labels?: Partial<RecordLabels>;
26
+ class?: string;
27
+ }
28
+ let { rows, title = null, labels, class: className }: Props = $props();
37
29
 
38
- // =========================
39
- // DERIVED
40
- // =========================
41
- let t = $derived(resolveLabels(labels));
42
- // A read-only row with nothing in it is noise. An editable one stays, as the way to fill it.
43
- let shown = $derived(
44
- rows.filter(
45
- (r) => r.divider || r.onSave || (r.value != null && r.value !== "") || (r.chips?.length ?? 0) > 0,
46
- ),
47
- );
48
- // Past this many options a plain list is slower than typing.
49
- const SEARCH_AT = 7;
30
+ // =========================
31
+ // STATE
32
+ // =========================
33
+ let editing = $state<string | null>(null);
34
+ let draft = $state("");
35
+ let saving = $state<string | null>(null);
36
+ let failed = $state<{ key: string; text: string } | null>(null);
37
+ let pickerOpen = $state<string | null>(null);
50
38
 
51
- // =========================
52
- // FUNCTIONS
53
- // =========================
54
- const keyOf = (row: InfoRow) => row.id ?? row.label;
39
+ // =========================
40
+ // DERIVED
41
+ // =========================
42
+ let t = $derived(resolveLabels(labels));
43
+ // A read-only row with nothing in it is noise. An editable one stays, as the way to fill it.
44
+ let shown = $derived(
45
+ rows.filter(
46
+ (r) =>
47
+ r.divider || r.onSave || (r.value != null && r.value !== "") || (r.chips?.length ?? 0) > 0,
48
+ ),
49
+ );
50
+ // Past this many options a plain list is slower than typing.
51
+ const SEARCH_AT = 7;
55
52
 
56
- function isEmpty(row: InfoRow): boolean {
57
- return (row.value == null || row.value === "") && (row.chips?.length ?? 0) === 0;
58
- }
53
+ // =========================
54
+ // FUNCTIONS
55
+ // =========================
56
+ const keyOf = (row: InfoRow) => row.id ?? row.label;
59
57
 
60
- function inputType(row: InfoRow): string {
61
- return row.input === "date" || row.input === "number" || row.input === "url" || row.input === "email"
62
- ? row.input
63
- : "text";
64
- }
58
+ function isEmpty(row: InfoRow): boolean {
59
+ return (row.value == null || row.value === "") && (row.chips?.length ?? 0) === 0;
60
+ }
65
61
 
66
- function begin(row: InfoRow) {
67
- editing = keyOf(row);
68
- failed = null;
69
- const from = row.editValue ?? row.value ?? "";
70
- draft = Array.isArray(from) ? from.join(", ") : String(from);
71
- }
62
+ function inputType(row: InfoRow): string {
63
+ return row.input === "date" ||
64
+ row.input === "number" ||
65
+ row.input === "url" ||
66
+ row.input === "email"
67
+ ? row.input
68
+ : "text";
69
+ }
72
70
 
73
- function stop() {
74
- editing = null;
75
- failed = null;
76
- draft = "";
77
- }
71
+ function begin(row: InfoRow) {
72
+ editing = keyOf(row);
73
+ failed = null;
74
+ const from = row.editValue ?? row.value ?? "";
75
+ draft = Array.isArray(from) ? from.join(", ") : String(from);
76
+ }
78
77
 
79
- async function commit(row: InfoRow, value: string | string[], close = true) {
80
- if (!row.onSave) return;
81
- const key = keyOf(row);
82
- const next = Array.isArray(value) ? value : value.trim();
83
- if (row.required && (Array.isArray(next) ? next.length === 0 : next === "")) {
84
- failed = { key, text: t.required };
85
- return;
78
+ function stop() {
79
+ editing = null;
80
+ failed = null;
81
+ draft = "";
86
82
  }
87
- saving = key;
88
- failed = null;
89
- try {
90
- await row.onSave(next);
91
- if (close) stop();
92
- } catch {
93
- failed = { key, text: t.saveFailed };
94
- } finally {
95
- saving = null;
83
+
84
+ async function commit(row: InfoRow, value: string | string[], close = true) {
85
+ if (!row.onSave) return;
86
+ const key = keyOf(row);
87
+ const next = Array.isArray(value) ? value : value.trim();
88
+ if (row.required && (Array.isArray(next) ? next.length === 0 : next === "")) {
89
+ failed = { key, text: t.required };
90
+ return;
91
+ }
92
+ saving = key;
93
+ failed = null;
94
+ try {
95
+ await row.onSave(next);
96
+ if (close) stop();
97
+ } catch {
98
+ failed = { key, text: t.saveFailed };
99
+ } finally {
100
+ saving = null;
101
+ }
96
102
  }
97
- }
98
103
 
99
- function pick(row: InfoRow, value: string) {
100
- pickerOpen = null;
101
- const current = typeof row.editValue === "string" ? row.editValue : null;
102
- if (value !== current) void commit(row, value, false);
103
- }
104
+ function pick(row: InfoRow, value: string) {
105
+ pickerOpen = null;
106
+ const current = typeof row.editValue === "string" ? row.editValue : null;
107
+ if (value !== current) void commit(row, value, false);
108
+ }
104
109
 
105
- function toggle(row: InfoRow, value: string) {
106
- const current = Array.isArray(row.editValue) ? row.editValue : [];
107
- const next = current.includes(value) ? current.filter((v) => v !== value) : [...current, value];
108
- void commit(row, next, false);
109
- }
110
+ function toggle(row: InfoRow, value: string) {
111
+ const current = Array.isArray(row.editValue) ? row.editValue : [];
112
+ const next = current.includes(value) ? current.filter((v) => v !== value) : [...current, value];
113
+ void commit(row, next, false);
114
+ }
110
115
 
111
- // Enter saves a line. A long text keeps Enter for the line break and saves on Cmd or Ctrl.
112
- function onKey(event: KeyboardEvent, row: InfoRow) {
113
- if (event.key === "Escape") {
114
- event.preventDefault();
115
- stop();
116
- } else if (event.key === "Enter" && (row.input !== "longtext" || event.metaKey || event.ctrlKey)) {
117
- event.preventDefault();
118
- void commit(row, draft);
116
+ // Enter saves a line. A long text keeps Enter for the line break and saves on Cmd or Ctrl.
117
+ function onKey(event: KeyboardEvent, row: InfoRow) {
118
+ if (event.key === "Escape") {
119
+ event.preventDefault();
120
+ stop();
121
+ } else if (
122
+ event.key === "Enter" &&
123
+ (row.input !== "longtext" || event.metaKey || event.ctrlKey)
124
+ ) {
125
+ event.preventDefault();
126
+ void commit(row, draft);
127
+ }
119
128
  }
120
- }
121
129
 
122
- // The ghost button that opens an editor reads as text until hovered, so a read
123
- // of the record isn't a page of controls.
124
- const OPENER = "-ml-1.5 max-w-full px-1.5 text-sm font-medium";
130
+ // The ghost button that opens an editor reads as text until hovered, so a read
131
+ // of the record isn't a page of controls.
132
+ const OPENER = "-ml-1.5 max-w-full px-1.5 text-sm font-medium";
125
133
  </script>
126
134
 
127
135
  <!-- =========================== -->
@@ -137,8 +145,9 @@ const OPENER = "-ml-1.5 max-w-full px-1.5 text-sm font-medium";
137
145
  {:else if row.tone && row.value}
138
146
  <StatusBadge tone={row.tone} capitalize={false}>{row.value}</StatusBadge>
139
147
  {:else if row.href && row.value}
140
- <a href={row.href} class="min-w-0 truncate text-sm font-medium underline-offset-2 hover:underline"
141
- >{row.value}</a
148
+ <a
149
+ href={row.href}
150
+ class="min-w-0 truncate text-sm font-medium underline-offset-2 hover:underline">{row.value}</a
142
151
  >
143
152
  {:else if row.value}
144
153
  <span
@@ -191,7 +200,10 @@ const OPENER = "-ml-1.5 max-w-full px-1.5 text-sm font-medium";
191
200
  onSelect={() => (multi ? toggle(row, option.value) : pick(row, option.value))}
192
201
  >
193
202
  <Check
194
- class={cn("size-3.5", current.includes(option.value) ? "opacity-100" : "opacity-0")}
203
+ class={cn(
204
+ "size-3.5",
205
+ current.includes(option.value) ? "opacity-100" : "opacity-0",
206
+ )}
195
207
  />
196
208
  {option.label}
197
209
  </Command.Item>
@@ -208,7 +220,9 @@ const OPENER = "-ml-1.5 max-w-full px-1.5 text-sm font-medium";
208
220
  {#if title}
209
221
  <h2 class="text-xs font-medium tracking-wide text-muted-foreground uppercase">{title}</h2>
210
222
  {/if}
211
- <dl class="grid grid-cols-[minmax(5rem,max-content)_minmax(0,1fr)] items-start gap-x-4 gap-y-2.5">
223
+ <dl
224
+ class="grid grid-cols-[minmax(5rem,max-content)_minmax(0,1fr)] items-start gap-x-4 gap-y-2.5"
225
+ >
212
226
  {#each shown as row, index (row.divider ? `divider-${index}` : keyOf(row))}
213
227
  {#if row.divider}
214
228
  <div class="col-span-2 -my-0.5 border-t border-border/50"></div>
@@ -227,9 +241,24 @@ const OPENER = "-ml-1.5 max-w-full px-1.5 text-sm font-medium";
227
241
  {/if}
228
242
  {row.label}
229
243
  </dt>
230
- <dd class={cn("flex min-h-7 min-w-0 flex-col justify-center gap-1", long && "col-span-2 -mt-1")}>
244
+ <dd
245
+ class={cn(
246
+ "flex min-h-7 min-w-0 flex-col justify-center gap-1",
247
+ long && "col-span-2 -mt-1",
248
+ )}
249
+ >
231
250
  {#if !row.onSave}
232
251
  {@render display(row)}
252
+ {:else if row.input === "tags" && row.tags}
253
+ <TagsInput
254
+ value={Array.isArray(row.editValue) ? row.editValue : []}
255
+ options={row.tags.options}
256
+ allowCreate={row.tags.allowCreate}
257
+ max={row.tags.max}
258
+ label={t.edit(row.label)}
259
+ labels={{ add: t.add(row.label), none: t.noMatch }}
260
+ onchange={(next) => commit(row, next, false)}
261
+ />
233
262
  {:else if row.input === "multi" && row.options}
234
263
  {@render list(row, key, true)}
235
264
  {:else if row.input === "select" && row.options && row.options.length > SEARCH_AT}
@@ -255,7 +284,9 @@ const OPENER = "-ml-1.5 max-w-full px-1.5 text-sm font-medium";
255
284
  </Select.Trigger>
256
285
  <Select.Content>
257
286
  {#each row.options as option (option.value)}
258
- <Select.Item value={option.value} label={option.label}>{option.label}</Select.Item>
287
+ <Select.Item value={option.value} label={option.label}
288
+ >{option.label}</Select.Item
289
+ >
259
290
  {/each}
260
291
  </Select.Content>
261
292
  </Select.Root>
@@ -1,42 +1,42 @@
1
1
  import {
2
- CheckCircle,
3
- ClipboardText,
4
- CurrencyCircleDollar,
5
- EnvelopeSimple,
6
- File,
7
- Flag,
8
- Gavel,
9
- NavigationArrow,
10
- NotePencil,
11
- Phone,
12
- Receipt,
13
- Signpost,
14
- UsersThree,
2
+ CheckCircle,
3
+ ClipboardText,
4
+ CurrencyCircleDollar,
5
+ EnvelopeSimple,
6
+ File,
7
+ Flag,
8
+ Gavel,
9
+ NavigationArrow,
10
+ NotePencil,
11
+ Phone,
12
+ Receipt,
13
+ Signpost,
14
+ UsersThree,
15
15
  } from "phosphor-svelte";
16
16
  import type { RecordFilterDef, RecordKindDef } from "./types.js";
17
17
 
18
18
  /** The kit's event kinds, drawn in plain English. A module adds its own beside them. */
19
19
  export const DEFAULT_RECORD_KINDS: RecordKindDef[] = [
20
- { key: "call", label: "Call", icon: Phone },
21
- { key: "meeting", label: "Meeting", icon: UsersThree },
22
- { key: "email", label: "Email", icon: EnvelopeSimple },
23
- { key: "form", label: "Form", icon: ClipboardText },
24
- { key: "note", label: "Note", icon: NotePencil },
25
- { key: "status", label: "Where we are", icon: NavigationArrow },
26
- { key: "stage", label: "Stage", icon: Signpost },
27
- { key: "task.done", label: "Task done", icon: CheckCircle, tone: "success" },
28
- { key: "milestone.done", label: "Step done", icon: Flag, tone: "success" },
29
- { key: "invoice.sent", label: "Invoice", icon: Receipt },
30
- { key: "payment", label: "Payment", icon: CurrencyCircleDollar, tone: "success" },
31
- { key: "decision", label: "Decision", icon: Gavel },
32
- { key: "file", label: "File", icon: File },
20
+ { key: "call", label: "Call", icon: Phone },
21
+ { key: "meeting", label: "Meeting", icon: UsersThree },
22
+ { key: "email", label: "Email", icon: EnvelopeSimple },
23
+ { key: "form", label: "Form", icon: ClipboardText },
24
+ { key: "note", label: "Note", icon: NotePencil },
25
+ { key: "status", label: "Where we are", icon: NavigationArrow },
26
+ { key: "stage", label: "Stage", icon: Signpost },
27
+ { key: "task.done", label: "Task done", icon: CheckCircle, tone: "success" },
28
+ { key: "milestone.done", label: "Step done", icon: Flag, tone: "success" },
29
+ { key: "invoice.sent", label: "Invoice", icon: Receipt },
30
+ { key: "payment", label: "Payment", icon: CurrencyCircleDollar, tone: "success" },
31
+ { key: "decision", label: "Decision", icon: Gavel },
32
+ { key: "file", label: "File", icon: File },
33
33
  ];
34
34
 
35
35
  /** The chips over the timeline. Kinds a record has none of are not drawn. */
36
36
  export const DEFAULT_RECORD_FILTERS: RecordFilterDef[] = [
37
- { key: "calls", label: "Calls", kinds: ["call", "meeting"] },
38
- { key: "notes", label: "Notes", kinds: ["note"] },
39
- { key: "money", label: "Money", kinds: ["invoice.sent", "payment"] },
40
- { key: "stage", label: "Stage", kinds: ["stage"] },
41
- { key: "status", label: "Status", kinds: ["status"] },
37
+ { key: "calls", label: "Calls", kinds: ["call", "meeting"] },
38
+ { key: "notes", label: "Notes", kinds: ["note"] },
39
+ { key: "money", label: "Money", kinds: ["invoice.sent", "payment"] },
40
+ { key: "stage", label: "Stage", kinds: ["stage"] },
41
+ { key: "status", label: "Status", kinds: ["status"] },
42
42
  ];