@heyramzi/ui 2.1.0 → 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 (312) hide show
  1. package/package.json +7 -8
  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/card/card-frame.svelte +43 -39
  31. package/src/canvas/card/resize-handles.svelte +89 -80
  32. package/src/canvas/chrome/chrome-zoom.svelte +101 -100
  33. package/src/canvas/chrome/lock-badge.svelte +8 -8
  34. package/src/canvas/chrome/side-handles.svelte +24 -19
  35. package/src/canvas/chrome/size-chip.svelte +30 -30
  36. package/src/canvas/chrome/snap-guides.svelte +20 -20
  37. package/src/canvas/components/icons/ToolIcon.svelte +8 -8
  38. package/src/canvas/components/shared/svg/PreviewSvg.svelte +19 -19
  39. package/src/canvas/components/shared/svg/ShapeOutline.svelte +71 -48
  40. package/src/canvas/components/shared/svg/StrokeNode.svelte +21 -27
  41. package/src/canvas/components/shared/svg/TextRule.svelte +25 -17
  42. package/src/canvas/edges/bend-handle.svelte +46 -46
  43. package/src/canvas/edges/edge-gradient.svelte +10 -10
  44. package/src/canvas/edges/gradient-edge.svelte +45 -29
  45. package/src/canvas/editor/lock.test.ts +6 -1
  46. package/src/canvas/editor/style.ts +7 -1
  47. package/src/canvas/headless/svg-figure.test.ts +5 -1
  48. package/src/canvas/lod/lod-switch.svelte +111 -106
  49. package/src/canvas/pen/PenField.svelte +87 -81
  50. package/src/canvas/pen/PenOverlay.svelte +127 -127
  51. package/src/canvas/pen/ShapeNode.svelte +31 -32
  52. package/src/canvas/pen/TextNode.svelte +54 -53
  53. package/src/canvas/pen/host-field.test.svelte +7 -7
  54. package/src/canvas/pen/shapes.ts +7 -1
  55. package/src/canvas/screen/GlyphIcon.svelte +22 -17
  56. package/src/canvas/screen/PartView.svelte +138 -72
  57. package/src/canvas/screen/ScreenBody.svelte +81 -60
  58. package/src/canvas/screen/ScreenCard.svelte +20 -20
  59. package/src/canvas/ui/CanvasToolbar.svelte +173 -85
  60. package/src/canvas/ui/FrameLayer.svelte +59 -59
  61. package/src/canvas/ui/PenLayer.svelte +39 -30
  62. package/src/canvas/ui/StylePanel.svelte +119 -102
  63. package/src/canvas/ui/canvas-grid.svelte +137 -129
  64. package/src/charts/animated-value.svelte +1 -1
  65. package/src/charts/area-chart.css +2 -5
  66. package/src/charts/area-chart.svelte +1 -1
  67. package/src/charts/bar-chart.css +2 -3
  68. package/src/charts/bar-chart.svelte +1 -1
  69. package/src/charts/charts.css +5 -17
  70. package/src/charts/crosshair.svelte +1 -1
  71. package/src/charts/dashboard/dashboard-empty.svelte +25 -25
  72. package/src/charts/dashboard/dashboard-section.svelte +24 -24
  73. package/src/charts/dashboard/data-panel.svelte +50 -50
  74. package/src/charts/dashboard/data-sort-head.svelte +56 -56
  75. package/src/charts/dashboard/data-table.svelte +138 -138
  76. package/src/charts/dashboard/panel-grid.svelte +30 -30
  77. package/src/charts/dashboard/period-filter.svelte +25 -25
  78. package/src/charts/dashboard/rating-chip.svelte +19 -19
  79. package/src/charts/dashboard/stat-band.svelte +32 -32
  80. package/src/charts/dashboard/stat-tile.svelte +106 -99
  81. package/src/charts/donut-chart.svelte +1 -1
  82. package/src/charts/edge-fade.svelte +1 -1
  83. package/src/charts/figure.svelte +1 -1
  84. package/src/charts/gauge-chart.css +4 -7
  85. package/src/charts/gauge-chart.svelte +1 -1
  86. package/src/charts/hover-focus.svelte +1 -1
  87. package/src/charts/legend.css +1 -3
  88. package/src/charts/legend.svelte +1 -1
  89. package/src/charts/line-chart.svelte +1 -1
  90. package/src/charts/number-chart.css +6 -9
  91. package/src/charts/number-chart.svelte +1 -1
  92. package/src/charts/reference-line.svelte +19 -19
  93. package/src/charts/reveal.svelte +1 -1
  94. package/src/charts/ring-chart.css +2 -4
  95. package/src/charts/ring-chart.svelte +1 -1
  96. package/src/charts/sparkline.svelte +5 -2
  97. package/src/charts/stat-card.svelte +1 -1
  98. package/src/charts/time-series-chart.css +2 -5
  99. package/src/charts/trend-pill.css +2 -4
  100. package/src/charts/trend-pill.svelte +1 -1
  101. package/src/components/copy/copy-button.svelte +93 -98
  102. package/src/components/copy/copy-button.test.ts +10 -2
  103. package/src/components/data-table/infinite-scroll.svelte +42 -42
  104. package/src/components/data-table/pagination.svelte +34 -22
  105. package/src/components/data-table/row-arrow.svelte +19 -16
  106. package/src/components/data-table/row-context-menu.svelte +52 -52
  107. package/src/components/data-table/sortable-head.svelte +25 -25
  108. package/src/components/data-table/table-skeleton.svelte +41 -36
  109. package/src/components/docs/doc-page.svelte +18 -9
  110. package/src/components/docs/on-this-page.svelte +16 -3
  111. package/src/components/docs/scroll-spy.svelte.ts +2 -3
  112. package/src/components/field-row/field-row.svelte +10 -8
  113. package/src/components/hold-to-confirm/hold-to-confirm.svelte +5 -1
  114. package/src/components/icon/icon.svelte +14 -14
  115. package/src/components/language-flag/language-flag.svelte +3 -1
  116. package/src/components/list-page/detail-empty.svelte +34 -34
  117. package/src/components/list-page/detail-header.svelte +55 -47
  118. package/src/components/list-page/detail-panel.svelte +51 -59
  119. package/src/components/list-page/detail-row.svelte +19 -19
  120. package/src/components/list-page/detail-stack.svelte +21 -21
  121. package/src/components/list-page/empty-state.svelte +30 -30
  122. package/src/components/list-page/filter-item.svelte +20 -20
  123. package/src/components/list-page/filter-popover.svelte +60 -55
  124. package/src/components/list-page/grouped-list.svelte +4 -2
  125. package/src/components/list-page/index.ts +5 -1
  126. package/src/components/list-page/list-page-shell.svelte +2 -5
  127. package/src/components/list-page/master-detail.svelte +87 -88
  128. package/src/components/list-page/notice-bar.svelte +38 -38
  129. package/src/components/list-page/prev-next.svelte +63 -63
  130. package/src/components/list-page/rail-body.svelte +18 -18
  131. package/src/components/list-page/rail-empty.svelte +23 -30
  132. package/src/components/list-page/rail-head.svelte +24 -24
  133. package/src/components/list-page/rail-row.svelte +77 -73
  134. package/src/components/list-page/section-host.ts +2 -3
  135. package/src/components/locale-switch/locale-switch.svelte +41 -41
  136. package/src/components/mark/mark.svelte +34 -38
  137. package/src/components/open-in/index.ts +1 -5
  138. package/src/components/open-in/open-in.svelte +40 -40
  139. package/src/components/picker/mark-picker.svelte +49 -49
  140. package/src/components/picker/picker.svelte +5 -3
  141. package/src/components/section-header/section-header.test.ts +7 -1
  142. package/src/components/section-header/section-label.svelte +20 -20
  143. package/src/components/segmented/animated-tabs.svelte +31 -2
  144. package/src/components/segmented/collapse.test.ts +2 -1
  145. package/src/components/segmented/index.ts +2 -0
  146. package/src/components/segmented/segment.svelte +52 -49
  147. package/src/components/segmented/segmented-filter.svelte +79 -80
  148. package/src/components/segmented/segmented-nav.svelte +34 -40
  149. package/src/components/segmented/segmented-overflow.svelte +53 -50
  150. package/src/components/segmented/segmented-track.svelte +62 -46
  151. package/src/components/segmented/segmented.ts +2 -3
  152. package/src/components/star-rating-input/star-rating-input.svelte +103 -103
  153. package/src/components/svg/svg.svelte +4 -4
  154. package/src/components/table-view/table-view.svelte +17 -2
  155. package/src/components/table-view/table-view.test.ts +7 -1
  156. package/src/components/table-view/types.ts +11 -11
  157. package/src/components/tags-input/index.ts +13 -0
  158. package/src/components/tags-input/tags-input.svelte +305 -0
  159. package/src/components/tags-input/tags.test.ts +64 -0
  160. package/src/components/tags-input/tags.ts +142 -0
  161. package/src/components/theme/index.ts +2 -4
  162. package/src/components/theme/theme-provider.svelte +1 -3
  163. package/src/components/toolbar/toolbar-search.svelte +25 -25
  164. package/src/components/toolbar/toolbar.svelte +11 -7
  165. package/src/components/toolbar/toolbar.test.ts +10 -1
  166. package/src/design/index.css +21 -78
  167. package/src/design/polish.css +26 -35
  168. package/src/editor/editor-toolbar.svelte +104 -99
  169. package/src/editor/editor.svelte +296 -266
  170. package/src/editor/image-toolbar.svelte +20 -22
  171. package/src/editor/index.ts +1 -4
  172. package/src/editor/inline-editor.svelte +280 -238
  173. package/src/editor/markdown.ts +15 -15
  174. package/src/editor/renderer.svelte +71 -71
  175. package/src/editor/slash-menu.svelte +24 -27
  176. package/src/effects/animated-beam/diagrams/BeamSvg.svelte +1 -1
  177. package/src/effects/image-comparison/ImageComparison.svelte +11 -1
  178. package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +59 -46
  179. package/src/effects/magic-card/MagicCard.css +14 -7
  180. package/src/effects/marquee/Marquee.svelte +3 -5
  181. package/src/effects/reveal/observe.ts +0 -3
  182. package/src/effects/spotlight/Spotlight.svelte +1 -1
  183. package/src/effects/theme-toggle/ThemeToggle.css +25 -22
  184. package/src/effects/theme-toggle/ThemeToggle.svelte +6 -7
  185. package/src/gallery.test.ts +14 -4
  186. package/src/inbox/README.md +1 -3
  187. package/src/inbox/inbox.test.ts +181 -138
  188. package/src/inbox/index.ts +20 -20
  189. package/src/inbox/logic.ts +114 -111
  190. package/src/inbox/thread-inbox.svelte +227 -151
  191. package/src/inbox/types.ts +130 -108
  192. package/src/lib/theme-transition.ts +2 -4
  193. package/src/lib/tone.ts +2 -4
  194. package/src/lib/utils.ts +2 -2
  195. package/src/modules.test.ts +79 -69
  196. package/src/onboarding/define-tours.test.ts +55 -40
  197. package/src/onboarding/define-tours.ts +23 -23
  198. package/src/onboarding/demo.svelte +24 -5
  199. package/src/onboarding/index.ts +1 -8
  200. package/src/onboarding/onboarding-provider.svelte +19 -7
  201. package/src/onboarding/onboarding.svelte.ts +16 -16
  202. package/src/onboarding/pick.test.ts +61 -52
  203. package/src/onboarding/pick.ts +16 -13
  204. package/src/onboarding/stores.test.ts +80 -80
  205. package/src/onboarding/stores.ts +41 -39
  206. package/src/onboarding/tour-card.svelte +30 -5
  207. package/src/onboarding/tour-runner.svelte +12 -3
  208. package/src/onboarding/types.ts +20 -12
  209. package/src/onboarding/wait.ts +22 -22
  210. package/src/panel/side-panel.svelte +94 -93
  211. package/src/record/demo-data.ts +291 -225
  212. package/src/record/field-section.svelte +38 -34
  213. package/src/record/fields.ts +148 -96
  214. package/src/record/format.ts +63 -56
  215. package/src/record/index.ts +49 -35
  216. package/src/record/info-list.svelte +145 -114
  217. package/src/record/kinds.ts +31 -31
  218. package/src/record/logic.ts +216 -214
  219. package/src/record/next-up.svelte +45 -34
  220. package/src/record/project-list.svelte +56 -50
  221. package/src/record/record-demo.svelte +130 -110
  222. package/src/record/record-header.svelte +37 -28
  223. package/src/record/record-shell.svelte +54 -54
  224. package/src/record/record-stats.svelte +25 -25
  225. package/src/record/record-timeline.svelte +134 -114
  226. package/src/record/record.test.ts +430 -309
  227. package/src/record/steps-rail.svelte +225 -216
  228. package/src/record/types.ts +234 -215
  229. package/src/record/where-we-are.svelte +62 -58
  230. package/src/shadcn/button/button.svelte +1 -1
  231. package/src/shadcn/card/card-title.svelte +1 -5
  232. package/src/shadcn/hooks/use-highlighted-code.svelte.ts +2 -13
  233. package/src/shadcn/sheet/sheet-content.svelte +2 -4
  234. package/src/shadcn/table/table-cell.svelte +2 -3
  235. package/src/shadcn/utilities.css +3 -8
  236. package/src/slides/Controls.svelte +150 -124
  237. package/src/slides/Deck.svelte +243 -238
  238. package/src/slides/Fragment.svelte +64 -57
  239. package/src/slides/Overview.svelte +106 -101
  240. package/src/slides/Presenter.svelte +300 -266
  241. package/src/slides/Slide.svelte +185 -170
  242. package/src/slides/SlideList.svelte +16 -12
  243. package/src/slides/ambient.d.ts +1 -1
  244. package/src/slides/bridges.ts +42 -23
  245. package/src/slides/deck-controller.svelte.ts +47 -35
  246. package/src/slides/demo-slides.svelte +330 -306
  247. package/src/slides/demo.svelte +164 -160
  248. package/src/slides/export/capture.ts +20 -16
  249. package/src/slides/export/ffmpeg.ts +43 -38
  250. package/src/slides/export/index.ts +5 -5
  251. package/src/slides/export/launch.ts +3 -1
  252. package/src/slides/export/pdf.ts +30 -27
  253. package/src/slides/export/types.ts +10 -8
  254. package/src/slides/index.ts +11 -11
  255. package/src/slides/labels.ts +22 -19
  256. package/src/slides/layout.ts +9 -2
  257. package/src/slides/model.ts +4 -4
  258. package/src/slides/navigation.ts +43 -31
  259. package/src/slides/theme.css +5 -7
  260. package/src/slides/types.ts +9 -10
  261. package/src/status/define-statuses.ts +17 -24
  262. package/src/status/index.ts +5 -5
  263. package/src/status/status-badge.svelte +3 -1
  264. package/src/status/status-dot.svelte +1 -3
  265. package/src/status/status-icon.svelte +1 -1
  266. package/src/status/status-types.ts +21 -21
  267. package/src/tasks/board-order.ts +2 -4
  268. package/src/tasks/demo.svelte +189 -31
  269. package/src/tasks/detail/detail-demo.svelte +73 -13
  270. package/src/tasks/detail/detail-types.ts +45 -45
  271. package/src/tasks/detail/task-detail.svelte +40 -10
  272. package/src/tasks/detail/task-property.svelte +8 -2
  273. package/src/tasks/detail/task-thread.svelte +53 -12
  274. package/src/tasks/gantt/gantt-bar.svelte +17 -6
  275. package/src/tasks/gantt/gantt-grid.svelte +40 -9
  276. package/src/tasks/gantt/gantt-group-row.svelte +8 -2
  277. package/src/tasks/gantt/gantt-header.svelte +9 -3
  278. package/src/tasks/gantt/gantt-task-row.svelte +26 -6
  279. package/src/tasks/gantt/gantt.css +2 -1
  280. package/src/tasks/gantt/gantt.test.ts +3 -1
  281. package/src/tasks/gantt/logic.test.ts +110 -20
  282. package/src/tasks/gantt/logic.ts +42 -6
  283. package/src/tasks/inbox/inbox-card.svelte +13 -5
  284. package/src/tasks/inbox/inbox-draft.svelte +1 -1
  285. package/src/tasks/inbox/inbox-logic.ts +6 -40
  286. package/src/tasks/inbox/inbox-statuses.ts +23 -23
  287. package/src/tasks/inbox/inbox-trace.svelte +9 -3
  288. package/src/tasks/inbox/inbox-types.ts +54 -58
  289. package/src/tasks/inbox/index.ts +22 -21
  290. package/src/tasks/index.ts +49 -52
  291. package/src/tasks/kanban-board.svelte +16 -12
  292. package/src/tasks/kanban-types.ts +2 -3
  293. package/src/tasks/presets/sales.ts +6 -6
  294. package/src/tasks/task-gantt.svelte +28 -8
  295. package/src/tasks/task-list.svelte +41 -17
  296. package/src/tasks/time/duration.ts +40 -40
  297. package/src/tasks/time/time-chip.svelte +9 -2
  298. package/src/tasks/time/time-dot.svelte +1 -1
  299. package/src/tasks/time/time-ring.svelte +11 -3
  300. package/src/tasks/time/time-tracker.svelte +57 -15
  301. package/src/tasks/time/time-types.ts +57 -57
  302. package/src/tasks/use-kanban-dnd.svelte.ts +2 -3
  303. package/src/thread/index.ts +7 -7
  304. package/src/thread/logic.ts +36 -33
  305. package/src/thread/thread.svelte +82 -16
  306. package/src/thread/thread.test.ts +58 -47
  307. package/src/thread/types.ts +68 -68
  308. package/src/tokens/craft.css +17 -53
  309. package/src/tokens/index.css +3 -13
  310. package/src/tokens/palette.css +13 -11
  311. package/src/tokens/primitives.css +10 -23
  312. 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
  ];