@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,43 +1,46 @@
1
1
  <script lang="ts">
2
- // =========================
3
- // IMPORTS
4
- // =========================
5
- import type { Snippet } from "svelte";
6
- import { cn } from "../../lib/utils.js";
7
- import { segmentedTrackClass, type SegmentedVariant } from "./segmented.js";
8
- import { slidingPill } from "../../lib/sliding-pill.js";
9
-
10
- // =========================
11
- // TYPES
12
- // =========================
13
- interface Props {
14
- /** Fill the row rather than sit at its natural width. */
15
- fill?: boolean;
16
- /** `pill`, a bordered well with a travelling highlight, or `underline`, a travelling rule. */
17
- variant?: SegmentedVariant;
18
- class?: string;
19
- children: Snippet;
20
- /**
21
- * A last segment that isn't an item: today the overflow trigger. It's inside
22
- * the track but outside the ARIA container, so a `tablist` owns only tabs.
23
- */
24
- after?: Snippet;
25
- // What the ARIA shapes differ by: `role`/`aria-label` for the filter, nothing
26
- // for the nav (its <nav> has it), bits-ui's wiring for tabs.
27
- [key: string]: unknown;
28
- };
29
-
30
- // =========================
31
- // PROPS
32
- // =========================
33
- let {
34
- fill = false,
35
- variant = "pill",
36
- class: className,
37
- children,
38
- after,
39
- ...rest
40
- }: Props = $props();
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import type { Snippet } from "svelte";
6
+ import { cn } from "../../lib/utils.js";
7
+ import {
8
+ segmentedTrackClass,
9
+ type SegmentedVariant,
10
+ } from "./segmented.js";
11
+ import { slidingPill } from "../../lib/sliding-pill.js";
12
+
13
+ // =========================
14
+ // TYPES
15
+ // =========================
16
+ interface Props {
17
+ /** Fill the row rather than sit at its natural width. */
18
+ fill?: boolean;
19
+ /** `pill`, a bordered well with a travelling highlight, or `underline`, a travelling rule. */
20
+ variant?: SegmentedVariant;
21
+ class?: string;
22
+ children: Snippet;
23
+ /**
24
+ * A last segment that isn't an item: today the overflow trigger. It's inside
25
+ * the track but outside the ARIA container, so a `tablist` owns only tabs.
26
+ */
27
+ after?: Snippet;
28
+ // What the ARIA shapes differ by: `role`/`aria-label` for the filter, nothing
29
+ // for the nav (its <nav> has it), bits-ui's wiring for tabs.
30
+ [key: string]: unknown;
31
+ }
32
+
33
+ // =========================
34
+ // PROPS
35
+ // =========================
36
+ let {
37
+ fill = false,
38
+ variant = "pill",
39
+ class: className,
40
+ children,
41
+ after,
42
+ ...rest
43
+ }: Props = $props();
41
44
  </script>
42
45
 
43
46
  <!-- =========================== -->
@@ -86,7 +89,10 @@ let {
86
89
  .track :global(.ui-segment[data-state="active"] + .ui-segment)::before,
87
90
  .track :global(.ui-segment[aria-current="page"] + .ui-segment)::before,
88
91
  .track :global(.ui-segment[aria-pressed="true"] + .ui-segment)::before,
89
- .track :global([data-slot="tabs-list"]:has(> .ui-segment:last-child[data-state="active"]) + .ui-segment)::before {
92
+ .track
93
+ :global(
94
+ [data-slot="tabs-list"]:has(> .ui-segment:last-child[data-state="active"]) + .ui-segment
95
+ )::before {
90
96
  opacity: 0;
91
97
  }
92
98
 
@@ -109,7 +115,12 @@ let {
109
115
  @media (hover: hover) {
110
116
  .track
111
117
  :global(
112
- .ui-segment:hover:not([data-state="active"], [aria-current="page"], [aria-pressed="true"], [data-state="open"])
118
+ .ui-segment:hover:not(
119
+ [data-state="active"],
120
+ [aria-current="page"],
121
+ [aria-pressed="true"],
122
+ [data-state="open"]
123
+ )
113
124
  ) {
114
125
  background-color: color-mix(in oklch, var(--color-muted) 55%, transparent);
115
126
  }
@@ -139,7 +150,8 @@ let {
139
150
 
140
151
  /* Before the attachment measures, the active segment draws the pill itself,
141
152
  so a server-rendered strip is right before any JS arrives. */
142
- .track:not([data-pill="on"]) :global(:is([data-state="active"], [aria-current="page"], [aria-pressed="true"])) {
153
+ .track:not([data-pill="on"])
154
+ :global(:is([data-state="active"], [aria-current="page"], [aria-pressed="true"])) {
143
155
  background-color: var(--color-muted);
144
156
  box-shadow: inset 0 0 0 1px color-mix(in oklch, var(--color-foreground) 6%, transparent);
145
157
  }
@@ -153,7 +165,12 @@ let {
153
165
  @media (hover: hover) {
154
166
  .track[data-variant="underline"]
155
167
  :global(
156
- .ui-segment:hover:not([data-state="active"], [aria-current="page"], [aria-pressed="true"], [data-state="open"])
168
+ .ui-segment:hover:not(
169
+ [data-state="active"],
170
+ [aria-current="page"],
171
+ [aria-pressed="true"],
172
+ [data-state="open"]
173
+ )
157
174
  ) {
158
175
  background-color: transparent;
159
176
  }
@@ -174,9 +191,8 @@ let {
174
191
  box-shadow: inset 0 -2px 0 var(--segmented-rule, var(--color-foreground));
175
192
  }
176
193
 
177
- /* On a coarse pointer the well is 44px and its segments fill it, so the hit area is the strip.
178
- A clipped well can't hold a hit area that hangs outside it. The border becomes a ring drawn
179
- over the segments, and the pill keeps its 2px gap inside that ring. */
194
+ /* On a coarse pointer the well grows to 44px and its segments are the hit area, since a
195
+ clipped well can't hold one hanging outside it. */
180
196
  @media (any-pointer: coarse) {
181
197
  .track[data-variant="pill"]::after {
182
198
  content: "";
@@ -52,9 +52,8 @@ export const segmentedTriggerClass = tv({
52
52
  "h-full text-xs",
53
53
  ],
54
54
  variants: {
55
- // The pill is concentric with the track's border and its 2px inset. The
56
- // underline has no well to be concentric with, so no padding either: the
57
- // rule under a label is as wide as the label.
55
+ // The pill sits concentric in the track's 2px inset; the underline has no well, so
56
+ // no padding, and its rule is as wide as the label.
58
57
  variant: {
59
58
  pill: "rounded-[calc(var(--radius-lg)-3px)] px-2.5 any-pointer-coarse:px-3.5",
60
59
  underline: "rounded-sm px-0",
@@ -1,109 +1,109 @@
1
1
  <script lang="ts" module>
2
- /**
3
- * Two sizes, picked by the job: `sm` reads a value back in a row or cell,
4
- * `lg` is the ask.
5
- */
6
- // A middle `md` step used to exist. Nobody could place it, so the same question
7
- // ended up asked at three sizes.
8
- export type StarRatingSize = "sm" | "lg";
9
-
10
- const STAR_SIZE: Record<StarRatingSize, string> = {
11
- sm: "size-4",
12
- lg: "size-7",
13
- };
14
-
15
- const HIT_SIZE: Record<StarRatingSize, string> = {
16
- sm: "p-0.5",
17
- lg: "p-1",
18
- };
19
-
20
- /** Pop duration plus the longest stagger, after which the class can come off. */
21
- const POP_WINDOW_MS = 350 + 4 * 40;
2
+ /**
3
+ * Two sizes, picked by the job: `sm` reads a value back in a row or cell,
4
+ * `lg` is the ask.
5
+ */
6
+ // A middle `md` step used to exist. Nobody could place it, so the same question
7
+ // ended up asked at three sizes.
8
+ export type StarRatingSize = "sm" | "lg";
9
+
10
+ const STAR_SIZE: Record<StarRatingSize, string> = {
11
+ sm: "size-4",
12
+ lg: "size-7",
13
+ };
14
+
15
+ const HIT_SIZE: Record<StarRatingSize, string> = {
16
+ sm: "p-0.5",
17
+ lg: "p-1",
18
+ };
19
+
20
+ /** Pop duration plus the longest stagger, after which the class can come off. */
21
+ const POP_WINDOW_MS = 350 + 4 * 40;
22
22
  </script>
23
23
 
24
24
  <script lang="ts">
25
- import { Star } from "phosphor-svelte";
26
- import { cn } from "../../lib/utils.js";
27
-
28
- interface Props {
29
- /** Current rating value (0 = unrated). */
30
- value: number;
31
- /** Maximum rating. Defaults to 5. */
32
- max?: number;
33
- /** Visual size of each star. `sm` reads back, `lg` asks. */
34
- size?: StarRatingSize;
35
- /** Render as static display, no hover or click. */
36
- readonly?: boolean;
37
- /** Disable interaction. */
38
- disabled?: boolean;
39
- /** Form field name for native submission. When set, a hidden input is rendered. */
40
- name?: string;
41
- /** ARIA label for the radiogroup. */
42
- ariaLabel?: string;
43
- /** Per-step descriptive labels (length must equal max). */
44
- labels?: readonly string[];
45
- /** Show the label of the currently hovered/selected step beside the stars. */
46
- showLabel?: boolean;
47
- class?: string;
48
- onchange?: (value: number) => void;
49
- };
50
-
51
- let {
52
- value = $bindable(0),
53
- max = 5,
54
- size = "sm",
55
- readonly = false,
56
- disabled = false,
57
- name,
58
- ariaLabel,
59
- labels,
60
- showLabel = false,
61
- class: className,
62
- onchange,
63
- }: Props = $props();
64
-
65
- let hover = $state(0);
66
- /** Held for the length of the pop, then dropped so the next pick can replay it. */
67
- let popping = $state(false);
68
- let popTimer: ReturnType<typeof setTimeout> | undefined;
69
- let displayed = $derived(hover || value);
70
- let starSize = $derived(STAR_SIZE[size]);
71
- let hitSize = $derived(HIT_SIZE[size]);
72
- let groupAriaLabel = $derived(ariaLabel ?? `Rating, ${max} stars`);
73
- let labelText = $derived(
74
- displayed > 0 && labels && labels.length >= displayed ? labels[displayed - 1] : "",
75
- );
76
-
77
- function buttonAriaLabel(step: number): string {
78
- const stepLabel = labels?.[step - 1];
79
- const base = `${step} of ${max}`;
80
- return stepLabel ? `${base} (${stepLabel})` : base;
81
- }
82
-
83
- function setRating(step: number) {
84
- if (readonly || disabled) return;
85
- value = step;
86
- onchange?.(step);
87
-
88
- // Drop the class before re-adding it, or a second pick inside the animation
89
- // window finds it already set and nothing replays.
90
- popping = false;
91
- clearTimeout(popTimer);
92
- requestAnimationFrame(() => {
93
- popping = true;
94
- popTimer = setTimeout(() => (popping = false), POP_WINDOW_MS);
95
- });
96
- }
97
-
98
- function handleEnter(step: number) {
99
- if (readonly || disabled) return;
100
- hover = step;
101
- }
102
-
103
- function handleLeave() {
104
- if (readonly || disabled) return;
105
- hover = 0;
106
- }
25
+ import { Star } from "phosphor-svelte";
26
+ import { cn } from "../../lib/utils.js";
27
+
28
+ interface Props {
29
+ /** Current rating value (0 = unrated). */
30
+ value: number;
31
+ /** Maximum rating. Defaults to 5. */
32
+ max?: number;
33
+ /** Visual size of each star. `sm` reads back, `lg` asks. */
34
+ size?: StarRatingSize;
35
+ /** Render as static display, no hover or click. */
36
+ readonly?: boolean;
37
+ /** Disable interaction. */
38
+ disabled?: boolean;
39
+ /** Form field name for native submission. When set, a hidden input is rendered. */
40
+ name?: string;
41
+ /** ARIA label for the radiogroup. */
42
+ ariaLabel?: string;
43
+ /** Per-step descriptive labels (length must equal max). */
44
+ labels?: readonly string[];
45
+ /** Show the label of the currently hovered/selected step beside the stars. */
46
+ showLabel?: boolean;
47
+ class?: string;
48
+ onchange?: (value: number) => void;
49
+ }
50
+
51
+ let {
52
+ value = $bindable(0),
53
+ max = 5,
54
+ size = "sm",
55
+ readonly = false,
56
+ disabled = false,
57
+ name,
58
+ ariaLabel,
59
+ labels,
60
+ showLabel = false,
61
+ class: className,
62
+ onchange,
63
+ }: Props = $props();
64
+
65
+ let hover = $state(0);
66
+ /** Held for the length of the pop, then dropped so the next pick can replay it. */
67
+ let popping = $state(false);
68
+ let popTimer: ReturnType<typeof setTimeout> | undefined;
69
+ let displayed = $derived(hover || value);
70
+ let starSize = $derived(STAR_SIZE[size]);
71
+ let hitSize = $derived(HIT_SIZE[size]);
72
+ let groupAriaLabel = $derived(ariaLabel ?? `Rating, ${max} stars`);
73
+ let labelText = $derived(
74
+ displayed > 0 && labels && labels.length >= displayed ? labels[displayed - 1] : "",
75
+ );
76
+
77
+ function buttonAriaLabel(step: number): string {
78
+ const stepLabel = labels?.[step - 1];
79
+ const base = `${step} of ${max}`;
80
+ return stepLabel ? `${base} (${stepLabel})` : base;
81
+ }
82
+
83
+ function setRating(step: number) {
84
+ if (readonly || disabled) return;
85
+ value = step;
86
+ onchange?.(step);
87
+
88
+ // Drop the class before re-adding it, or a second pick inside the animation
89
+ // window finds it already set and nothing replays.
90
+ popping = false;
91
+ clearTimeout(popTimer);
92
+ requestAnimationFrame(() => {
93
+ popping = true;
94
+ popTimer = setTimeout(() => (popping = false), POP_WINDOW_MS);
95
+ });
96
+ }
97
+
98
+ function handleEnter(step: number) {
99
+ if (readonly || disabled) return;
100
+ hover = step;
101
+ }
102
+
103
+ function handleLeave() {
104
+ if (readonly || disabled) return;
105
+ hover = 0;
106
+ }
107
107
  </script>
108
108
 
109
109
  <!-- One star, drawn once. It used to be written twice, once per branch, and the
@@ -152,7 +152,7 @@ function handleLeave() {
152
152
  {/if}
153
153
 
154
154
  {#if name}
155
- <input type="hidden" {name} value={value} />
155
+ <input type="hidden" {name} {value} />
156
156
  {/if}
157
157
  </div>
158
158
 
@@ -1,9 +1,9 @@
1
1
  <script lang="ts">
2
- // Renders a drawing kept in its own .svg file, imported with `?raw`.
3
- // The markup is ours and static, so rendering it as HTML is safe.
4
- let { src, class: className = "" }: { src: string; class?: string } = $props();
2
+ // Renders a drawing kept in its own .svg file, imported with `?raw`.
3
+ // The markup is ours and static, so rendering it as HTML is safe.
4
+ let { src, class: className = "" }: { src: string; class?: string } = $props();
5
5
 
6
- const markup = $derived(className ? src.replace("<svg", `<svg class="${className}"`) : src);
6
+ const markup = $derived(className ? src.replace("<svg", `<svg class="${className}"`) : src);
7
7
  </script>
8
8
 
9
9
  {@html markup}
@@ -36,7 +36,17 @@
36
36
  // =========================
37
37
  // PROPS
38
38
  // =========================
39
- let { columns, rows, rowKey, label, footer, cell, rowClass, minWidth = "0", class: className }: Props = $props();
39
+ let {
40
+ columns,
41
+ rows,
42
+ rowKey,
43
+ label,
44
+ footer,
45
+ cell,
46
+ rowClass,
47
+ minWidth = "0",
48
+ class: className,
49
+ }: Props = $props();
40
50
 
41
51
  // =========================
42
52
  // FUNCTIONS
@@ -63,7 +73,12 @@
63
73
  )}
64
74
  >
65
75
  {#if cell}
66
- {@render cell({ row, column, value: (row as Record<string, unknown>)[column.key], text: textOf(column, row) })}
76
+ {@render cell({
77
+ row,
78
+ column,
79
+ value: (row as Record<string, unknown>)[column.key],
80
+ text: textOf(column, row),
81
+ })}
67
82
  {:else}
68
83
  {textOf(column, row)}
69
84
  {/if}
@@ -25,7 +25,13 @@ function render(extra: Record<string, unknown> = {}) {
25
25
  },
26
26
  });
27
27
  flushSync();
28
- return { target, done: () => { void unmount(app); target.remove(); } };
28
+ return {
29
+ target,
30
+ done: () => {
31
+ void unmount(app);
32
+ target.remove();
33
+ },
34
+ };
29
35
  }
30
36
 
31
37
  describe("TableView", () => {
@@ -1,14 +1,14 @@
1
1
  /** One column of a `TableView`. */
2
2
  export interface TableColumn<Row> {
3
- /** The key of the value in the row. */
4
- key: string;
5
- label: string;
6
- /** A number or an amount: right-aligned, tabular figures, never wraps. */
7
- numeric?: boolean;
8
- /** Turns the raw value into the text shown. A string value that has no `format` prints as it is. A money column passes its own currency formatter. */
9
- format?: (value: unknown, row: Row) => string;
10
- /** A column width such as `"30%"` or `"8rem"`. Leave it out and the table shares the rest. */
11
- width?: string;
12
- /** Draws the column in the muted colour. */
13
- muted?: boolean;
3
+ /** The key of the value in the row. */
4
+ key: string;
5
+ label: string;
6
+ /** A number or an amount: right-aligned, tabular figures, never wraps. */
7
+ numeric?: boolean;
8
+ /** Turns the raw value into the text shown. A string value that has no `format` prints as it is. A money column passes its own currency formatter. */
9
+ format?: (value: unknown, row: Row) => string;
10
+ /** A column width such as `"30%"` or `"8rem"`. Leave it out and the table shares the rest. */
11
+ width?: string;
12
+ /** Draws the column in the muted colour. */
13
+ muted?: boolean;
14
14
  }
@@ -0,0 +1,13 @@
1
+ export { default as TagsInput } from "./tags-input.svelte";
2
+ export {
3
+ addTag,
4
+ canCreate,
5
+ cleanTags,
6
+ collectOptions,
7
+ editDistance,
8
+ findOption,
9
+ fold,
10
+ matchOptions,
11
+ removeTag,
12
+ splitTags,
13
+ } from "./tags.js";