@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,197 +1,193 @@
1
1
  <script lang="ts">
2
- import AgentAvatar from './agent-avatar.svelte';
3
- import type { Agent, AgentState } from './types.js';
2
+ import AgentAvatar from "./agent-avatar.svelte";
3
+ import type { Agent, AgentState } from "./types.js";
4
4
 
5
- interface Props {
6
- /** The cast to lay out. */
7
- agents: Agent[];
8
- /** Selected agent id, when the cast is a picker. */
9
- selectedId?: string | null;
10
- /** Called with the agent that was picked. */
11
- onSelect?: (agent: Agent) => void;
12
- /** Hide the role line under each name. */
13
- showRole?: boolean;
14
- /** Extra props forwarded to every `<AgentAvatar>`. */
15
- avatarProps?: Record<string, unknown>;
16
- /** Minimum card width, any CSS length. Controls the column count. */
17
- minColumn?: string;
18
- class?: string;
19
- style?: string;
20
- };
5
+ interface Props {
6
+ /** The cast to lay out. */
7
+ agents: Agent[];
8
+ /** Selected agent id, when the cast is a picker. */
9
+ selectedId?: string | null;
10
+ /** Called with the agent that was picked. */
11
+ onSelect?: (agent: Agent) => void;
12
+ /** Hide the role line under each name. */
13
+ showRole?: boolean;
14
+ /** Extra props forwarded to every `<AgentAvatar>`. */
15
+ avatarProps?: Record<string, unknown>;
16
+ /** Minimum card width, any CSS length. Controls the column count. */
17
+ minColumn?: string;
18
+ class?: string;
19
+ style?: string;
20
+ }
21
21
 
22
- let {
23
- agents,
24
- selectedId = null,
25
- onSelect,
26
- showRole = true,
27
- avatarProps = {},
28
- minColumn = '8.5rem',
29
- class: className,
30
- style,
31
- }: Props = $props();
22
+ let {
23
+ agents,
24
+ selectedId = null,
25
+ onSelect,
26
+ showRole = true,
27
+ avatarProps = {},
28
+ minColumn = "8.5rem",
29
+ class: className,
30
+ style,
31
+ }: Props = $props();
32
32
 
33
- const keyOf = (agent: Agent) => agent.id ?? agent.name;
33
+ const keyOf = (agent: Agent) => agent.id ?? agent.name;
34
34
 
35
- /* The card under the pointer or focus wakes up and works; the rest idle.
35
+ /* The card under the pointer or focus wakes up and works; the rest idle.
36
36
  A `state` in avatarProps wins. */
37
- let awake = $state<string | null>(null);
38
- const stateFor = (id: string) =>
39
- (avatarProps.state as AgentState | undefined) ?? (awake === id ? 'working' : 'default');
37
+ let awake = $state<string | null>(null);
38
+ const stateFor = (id: string) =>
39
+ (avatarProps.state as AgentState | undefined) ?? (awake === id ? "working" : "default");
40
40
 
41
- /* Group when any agent asks for one, otherwise a single flat grid. */
42
- const sections = $derived.by(() => {
43
- const anyGroup = agents.some((agent) => agent.group);
44
- if (!anyGroup) return [{ label: '', items: agents }];
45
- const order: string[] = [];
46
- const byGroup = new Map<string, Agent[]>();
47
- for (const agent of agents) {
48
- const label = agent.group ?? '';
49
- let list = byGroup.get(label);
50
- if (!list) {
51
- list = [];
52
- byGroup.set(label, list);
53
- order.push(label);
54
- }
55
- list.push(agent);
56
- }
57
- return order.map((label) => ({ label, items: byGroup.get(label) ?? [] }));
58
- });
41
+ /* Group when any agent asks for one, otherwise a single flat grid. */
42
+ const sections = $derived.by(() => {
43
+ const anyGroup = agents.some((agent) => agent.group);
44
+ if (!anyGroup) return [{ label: "", items: agents }];
45
+ const order: string[] = [];
46
+ const byGroup = new Map<string, Agent[]>();
47
+ for (const agent of agents) {
48
+ const label = agent.group ?? "";
49
+ let list = byGroup.get(label);
50
+ if (!list) {
51
+ list = [];
52
+ byGroup.set(label, list);
53
+ order.push(label);
54
+ }
55
+ list.push(agent);
56
+ }
57
+ return order.map((label) => ({ label, items: byGroup.get(label) ?? [] }));
58
+ });
59
59
 
60
- const rootStyle = $derived(
61
- `--agent-cast-min:${minColumn};${style ?? ''}`,
62
- );
60
+ const rootStyle = $derived(`--agent-cast-min:${minColumn};${style ?? ""}`);
63
61
  </script>
64
62
 
65
- <div
66
- class={className ? `agent-cast ${className}` : 'agent-cast'}
67
- style={rootStyle}
68
- >
69
- {#each sections as section, s (section.label || `flat-${s}`)}
70
- <section class="agent-cast__section">
71
- {#if section.label}
72
- <h3 class="agent-cast__heading">{section.label}</h3>
73
- {/if}
74
- <ul class="agent-cast__grid">
75
- {#each section.items as agent (keyOf(agent))}
76
- {@const id = keyOf(agent)}
77
- <li>
78
- <button
79
- type="button"
80
- class="agent-cast__card"
81
- aria-pressed={onSelect ? id === selectedId : undefined}
82
- onclick={() => onSelect?.(agent)}
83
- onpointerenter={() => (awake = id)}
84
- onpointerleave={() => awake === id && (awake = null)}
85
- onfocus={() => (awake = id)}
86
- onblur={() => awake === id && (awake = null)}
87
- >
88
- <span class="agent-cast__slot">
89
- <AgentAvatar
90
- name={agent.name}
91
- role={agent.role}
92
- shape={agent.shape ?? 'clover'}
93
- color={agent.color}
94
- aria-hidden
95
- {...avatarProps}
96
- state={stateFor(id)}
97
- />
98
- </span>
99
- <span class="agent-cast__meta">
100
- <span class="agent-cast__name">{agent.name}</span>
101
- {#if showRole && agent.role}
102
- <span class="agent-cast__role">{agent.role}</span>
103
- {/if}
104
- </span>
105
- </button>
106
- </li>
107
- {/each}
108
- </ul>
109
- </section>
110
- {/each}
63
+ <div class={className ? `agent-cast ${className}` : "agent-cast"} style={rootStyle}>
64
+ {#each sections as section, s (section.label || `flat-${s}`)}
65
+ <section class="agent-cast__section">
66
+ {#if section.label}
67
+ <h3 class="agent-cast__heading">{section.label}</h3>
68
+ {/if}
69
+ <ul class="agent-cast__grid">
70
+ {#each section.items as agent (keyOf(agent))}
71
+ {@const id = keyOf(agent)}
72
+ <li>
73
+ <button
74
+ type="button"
75
+ class="agent-cast__card"
76
+ aria-pressed={onSelect ? id === selectedId : undefined}
77
+ onclick={() => onSelect?.(agent)}
78
+ onpointerenter={() => (awake = id)}
79
+ onpointerleave={() => awake === id && (awake = null)}
80
+ onfocus={() => (awake = id)}
81
+ onblur={() => awake === id && (awake = null)}
82
+ >
83
+ <span class="agent-cast__slot">
84
+ <AgentAvatar
85
+ name={agent.name}
86
+ role={agent.role}
87
+ shape={agent.shape ?? "clover"}
88
+ color={agent.color}
89
+ aria-hidden
90
+ {...avatarProps}
91
+ state={stateFor(id)}
92
+ />
93
+ </span>
94
+ <span class="agent-cast__meta">
95
+ <span class="agent-cast__name">{agent.name}</span>
96
+ {#if showRole && agent.role}
97
+ <span class="agent-cast__role">{agent.role}</span>
98
+ {/if}
99
+ </span>
100
+ </button>
101
+ </li>
102
+ {/each}
103
+ </ul>
104
+ </section>
105
+ {/each}
111
106
  </div>
112
107
 
113
108
  <style>
114
- .agent-cast {
115
- width: 100%;
116
- color: var(--color-foreground, #18181b);
117
- }
118
- .agent-cast__section + .agent-cast__section {
119
- margin-top: 2rem;
120
- }
121
- .agent-cast__heading {
122
- margin: 0 0 0.75rem;
123
- font-size: 0.9375rem;
124
- font-weight: 600;
125
- letter-spacing: -0.015em;
126
- }
127
- .agent-cast__grid {
128
- display: grid;
129
- gap: 0.75rem;
130
- grid-template-columns: repeat(auto-fill, minmax(var(--agent-cast-min, 8.5rem), 1fr));
131
- margin: 0;
132
- padding: 0;
133
- list-style: none;
134
- }
135
- .agent-cast__card {
136
- display: flex;
137
- flex-direction: column;
138
- width: 100%;
139
- height: 100%;
140
- overflow: hidden;
141
- padding: 0;
142
- text-align: left;
143
- background: var(--color-card, #fff);
144
- border: 1px solid var(--color-border, #e4e4e7);
145
- border-radius: 0.75rem;
146
- cursor: pointer;
147
- transition:
148
- border-color var(--duration-quick, 150ms) var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1)),
149
- transform var(--duration-quick, 150ms) var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1));
150
- }
151
- @media (prefers-reduced-motion: reduce) {
152
- .agent-cast__card {
153
- transition: border-color var(--duration-quick, 150ms) linear;
154
- }
155
- .agent-cast__card:active {
156
- transform: none;
157
- }
158
- }
159
- @media (hover: hover) and (pointer: fine) {
160
- .agent-cast__card:hover {
161
- border-color: color-mix(in oklab, var(--color-foreground, #18181b) 25%, transparent);
162
- }
163
- }
164
- .agent-cast__card:active {
165
- transform: scale(0.985);
166
- }
167
- .agent-cast__card:focus-visible {
168
- outline: 2px solid var(--color-ring, #6366f1);
169
- outline-offset: 2px;
170
- }
171
- .agent-cast__card[aria-pressed='true'] {
172
- border-color: var(--color-accent, #6366f1);
173
- box-shadow: 0 0 0 1px var(--color-accent, #6366f1);
174
- }
175
- /* Room above the head, so a hop or a hat never meets the card's edge. */
176
- .agent-cast__slot {
177
- display: block;
178
- width: 100%;
179
- padding: 0.5rem 0.5rem 0;
180
- }
181
- .agent-cast__meta {
182
- display: flex;
183
- flex-direction: column;
184
- gap: 0.125rem;
185
- padding: 0.625rem;
186
- }
187
- .agent-cast__name {
188
- font-size: 0.8125rem;
189
- font-weight: 500;
190
- line-height: 1.2;
191
- }
192
- .agent-cast__role {
193
- font-size: 0.75rem;
194
- line-height: 1.3;
195
- color: var(--color-muted-foreground, #71717a);
196
- }
109
+ .agent-cast {
110
+ width: 100%;
111
+ color: var(--color-foreground, #18181b);
112
+ }
113
+ .agent-cast__section + .agent-cast__section {
114
+ margin-top: 2rem;
115
+ }
116
+ .agent-cast__heading {
117
+ margin: 0 0 0.75rem;
118
+ font-size: 0.9375rem;
119
+ font-weight: 600;
120
+ letter-spacing: -0.015em;
121
+ }
122
+ .agent-cast__grid {
123
+ display: grid;
124
+ gap: 0.75rem;
125
+ grid-template-columns: repeat(auto-fill, minmax(var(--agent-cast-min, 8.5rem), 1fr));
126
+ margin: 0;
127
+ padding: 0;
128
+ list-style: none;
129
+ }
130
+ .agent-cast__card {
131
+ display: flex;
132
+ flex-direction: column;
133
+ width: 100%;
134
+ height: 100%;
135
+ overflow: hidden;
136
+ padding: 0;
137
+ text-align: left;
138
+ background: var(--color-card, #fff);
139
+ border: 1px solid var(--color-border, #e4e4e7);
140
+ border-radius: 0.75rem;
141
+ cursor: pointer;
142
+ transition:
143
+ border-color var(--duration-quick, 150ms)
144
+ var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1)),
145
+ transform var(--duration-quick, 150ms) var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1));
146
+ }
147
+ @media (prefers-reduced-motion: reduce) {
148
+ .agent-cast__card {
149
+ transition: border-color var(--duration-quick, 150ms) linear;
150
+ }
151
+ .agent-cast__card:active {
152
+ transform: none;
153
+ }
154
+ }
155
+ @media (hover: hover) and (pointer: fine) {
156
+ .agent-cast__card:hover {
157
+ border-color: color-mix(in oklab, var(--color-foreground, #18181b) 25%, transparent);
158
+ }
159
+ }
160
+ .agent-cast__card:active {
161
+ transform: scale(0.985);
162
+ }
163
+ .agent-cast__card:focus-visible {
164
+ outline: 2px solid var(--color-ring, #6366f1);
165
+ outline-offset: 2px;
166
+ }
167
+ .agent-cast__card[aria-pressed="true"] {
168
+ border-color: var(--color-accent, #6366f1);
169
+ box-shadow: 0 0 0 1px var(--color-accent, #6366f1);
170
+ }
171
+ /* Room above the head, so a hop or a hat never meets the card's edge. */
172
+ .agent-cast__slot {
173
+ display: block;
174
+ width: 100%;
175
+ padding: 0.5rem 0.5rem 0;
176
+ }
177
+ .agent-cast__meta {
178
+ display: flex;
179
+ flex-direction: column;
180
+ gap: 0.125rem;
181
+ padding: 0.625rem;
182
+ }
183
+ .agent-cast__name {
184
+ font-size: 0.8125rem;
185
+ font-weight: 500;
186
+ line-height: 1.2;
187
+ }
188
+ .agent-cast__role {
189
+ font-size: 0.75rem;
190
+ line-height: 1.3;
191
+ color: var(--color-muted-foreground, #71717a);
192
+ }
197
193
  </style>
@@ -1,125 +1,137 @@
1
1
  <script lang="ts">
2
- import AgentAvatar from './agent-avatar.svelte';
3
- import AgentCast from './agent-cast.svelte';
4
- import type { Agent, AgentState } from './types.js';
2
+ import AgentAvatar from "./agent-avatar.svelte";
3
+ import AgentCast from "./agent-cast.svelte";
4
+ import type { Agent, AgentState } from "./types.js";
5
5
 
6
- const cast: Agent[] = [
7
- { id: 'ada', name: 'Ada', role: 'Researcher', shape: 'clover', color: '#41C4FF', group: 'Research' },
8
- { id: 'bo', name: 'Bo', role: 'Analyst', shape: 'flower', group: 'Research' },
9
- { id: 'cy', name: 'Cy', role: 'Planner', shape: 'mech', group: 'Planning' },
10
- { id: 'dia', name: 'Dia', role: 'Scheduler', shape: 'droid', group: 'Planning' },
11
- { id: 'eli', name: 'Eli', role: 'Writer', shape: 'cat', group: 'Craft' },
12
- { id: 'fen', name: 'Fen', role: 'Editor', shape: 'pill', group: 'Craft' },
13
- { id: 'gus', name: 'Gus', role: 'Runner', shape: 'ghost', group: 'Craft' },
14
- { id: 'hal', name: 'Hal', role: 'Watcher', shape: 'star', group: 'Craft' },
15
- ];
6
+ const cast: Agent[] = [
7
+ {
8
+ id: "ada",
9
+ name: "Ada",
10
+ role: "Researcher",
11
+ shape: "clover",
12
+ color: "#41C4FF",
13
+ group: "Research",
14
+ },
15
+ { id: "bo", name: "Bo", role: "Analyst", shape: "flower", group: "Research" },
16
+ { id: "cy", name: "Cy", role: "Planner", shape: "mech", group: "Planning" },
17
+ { id: "dia", name: "Dia", role: "Scheduler", shape: "droid", group: "Planning" },
18
+ { id: "eli", name: "Eli", role: "Writer", shape: "cat", group: "Craft" },
19
+ { id: "fen", name: "Fen", role: "Editor", shape: "pill", group: "Craft" },
20
+ { id: "gus", name: "Gus", role: "Runner", shape: "ghost", group: "Craft" },
21
+ { id: "hal", name: "Hal", role: "Watcher", shape: "star", group: "Craft" },
22
+ ];
16
23
 
17
- const states: { value: AgentState; label: string }[] = [
18
- { value: 'default', label: 'Idle' },
19
- { value: 'working', label: 'Working' },
20
- { value: 'sleeping', label: 'Sleeping' },
21
- ];
24
+ const states: { value: AgentState; label: string }[] = [
25
+ { value: "default", label: "Idle" },
26
+ { value: "working", label: "Working" },
27
+ { value: "sleeping", label: "Sleeping" },
28
+ ];
22
29
 
23
- let selected = $state<string | null>('ada');
24
- let leadState = $state<AgentState>('working');
25
- let lead = $derived(cast.find((agent) => agent.id === selected) ?? cast[0]);
30
+ let selected = $state<string | null>("ada");
31
+ let leadState = $state<AgentState>("working");
32
+ let lead = $derived(cast.find((agent) => agent.id === selected) ?? cast[0]);
26
33
  </script>
27
34
 
28
35
  <div class="demo">
29
- <header class="demo__hero">
30
- <div class="demo__portrait">
31
- <AgentAvatar
32
- name={lead.name}
33
- role={lead.role}
34
- shape={lead.shape}
35
- color={lead.color}
36
- state={leadState}
37
- />
38
- </div>
39
- <div class="demo__intro">
40
- <p class="demo__eyebrow">AgentCast</p>
41
- <h1 class="demo__title">{lead.name}</h1>
42
- <p class="demo__role">{lead.role}</p>
43
- <div class="demo__states" role="radiogroup" aria-label="State">
44
- {#each states as s (s.value)}
45
- <button
46
- type="button"
47
- role="radio"
48
- aria-checked={leadState === s.value}
49
- onclick={() => (leadState = s.value)}
50
- >
51
- {s.label}
52
- </button>
53
- {/each}
54
- </div>
55
- </div>
56
- </header>
36
+ <header class="demo__hero">
37
+ <div class="demo__portrait">
38
+ <AgentAvatar
39
+ name={lead.name}
40
+ role={lead.role}
41
+ shape={lead.shape}
42
+ color={lead.color}
43
+ state={leadState}
44
+ />
45
+ </div>
46
+ <div class="demo__intro">
47
+ <p class="demo__eyebrow">AgentCast</p>
48
+ <h1 class="demo__title">{lead.name}</h1>
49
+ <p class="demo__role">{lead.role}</p>
50
+ <div class="demo__states" role="radiogroup" aria-label="State">
51
+ {#each states as s (s.value)}
52
+ <button
53
+ type="button"
54
+ role="radio"
55
+ aria-checked={leadState === s.value}
56
+ onclick={() => (leadState = s.value)}
57
+ >
58
+ {s.label}
59
+ </button>
60
+ {/each}
61
+ </div>
62
+ </div>
63
+ </header>
57
64
 
58
- <AgentCast agents={cast} selectedId={selected} onSelect={(agent) => (selected = agent.id ?? agent.name)} />
65
+ <AgentCast
66
+ agents={cast}
67
+ selectedId={selected}
68
+ onSelect={(agent) => (selected = agent.id ?? agent.name)}
69
+ />
59
70
  </div>
60
71
 
61
72
  <style>
62
- .demo {
63
- max-width: 56rem;
64
- margin: 0 auto;
65
- padding: 2rem 1.5rem 4rem;
66
- color: var(--color-foreground, #18181b);
67
- background: var(--color-background, #fafafa);
68
- }
69
- .demo__hero {
70
- display: flex;
71
- align-items: center;
72
- gap: 1.5rem;
73
- margin-bottom: 2.5rem;
74
- }
75
- .demo__portrait {
76
- flex: none;
77
- width: 9rem;
78
- }
79
- .demo__eyebrow {
80
- margin: 0;
81
- font-size: 0.75rem;
82
- letter-spacing: 0.14em;
83
- text-transform: uppercase;
84
- color: var(--color-muted-foreground, #71717a);
85
- }
86
- .demo__title {
87
- margin: 0.25rem 0 0;
88
- font-size: 2.25rem;
89
- letter-spacing: -0.03em;
90
- }
91
- .demo__role {
92
- margin: 0.25rem 0 0;
93
- color: var(--color-muted-foreground, #52525b);
94
- }
95
- .demo__states {
96
- display: inline-flex;
97
- gap: 0.25rem;
98
- margin-top: 0.875rem;
99
- padding: 0.1875rem;
100
- border-radius: 0.625rem;
101
- background: color-mix(in oklab, var(--color-foreground, #18181b) 6%, transparent);
102
- }
103
- .demo__states button {
104
- padding: 0.3125rem 0.75rem;
105
- font: inherit;
106
- font-size: 0.8125rem;
107
- color: var(--color-muted-foreground, #71717a);
108
- background: transparent;
109
- border: 0;
110
- border-radius: 0.4375rem;
111
- cursor: pointer;
112
- transition:
113
- color var(--duration-quick, 150ms) var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1)),
114
- background-color var(--duration-quick, 150ms) var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1));
115
- }
116
- .demo__states button[aria-checked='true'] {
117
- color: var(--color-foreground, #18181b);
118
- background: var(--color-card, #fff);
119
- box-shadow: var(--elev-hairline, 0 0 0 1px rgb(0 0 0 / 0.06));
120
- }
121
- .demo__states button:focus-visible {
122
- outline: 2px solid var(--color-ring, #6366f1);
123
- outline-offset: 1px;
124
- }
73
+ .demo {
74
+ max-width: 56rem;
75
+ margin: 0 auto;
76
+ padding: 2rem 1.5rem 4rem;
77
+ color: var(--color-foreground, #18181b);
78
+ background: var(--color-background, #fafafa);
79
+ }
80
+ .demo__hero {
81
+ display: flex;
82
+ align-items: center;
83
+ gap: 1.5rem;
84
+ margin-bottom: 2.5rem;
85
+ }
86
+ .demo__portrait {
87
+ flex: none;
88
+ width: 9rem;
89
+ }
90
+ .demo__eyebrow {
91
+ margin: 0;
92
+ font-size: 0.75rem;
93
+ letter-spacing: 0.14em;
94
+ text-transform: uppercase;
95
+ color: var(--color-muted-foreground, #71717a);
96
+ }
97
+ .demo__title {
98
+ margin: 0.25rem 0 0;
99
+ font-size: 2.25rem;
100
+ letter-spacing: -0.03em;
101
+ }
102
+ .demo__role {
103
+ margin: 0.25rem 0 0;
104
+ color: var(--color-muted-foreground, #52525b);
105
+ }
106
+ .demo__states {
107
+ display: inline-flex;
108
+ gap: 0.25rem;
109
+ margin-top: 0.875rem;
110
+ padding: 0.1875rem;
111
+ border-radius: 0.625rem;
112
+ background: color-mix(in oklab, var(--color-foreground, #18181b) 6%, transparent);
113
+ }
114
+ .demo__states button {
115
+ padding: 0.3125rem 0.75rem;
116
+ font: inherit;
117
+ font-size: 0.8125rem;
118
+ color: var(--color-muted-foreground, #71717a);
119
+ background: transparent;
120
+ border: 0;
121
+ border-radius: 0.4375rem;
122
+ cursor: pointer;
123
+ transition:
124
+ color var(--duration-quick, 150ms) var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1)),
125
+ background-color var(--duration-quick, 150ms)
126
+ var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1));
127
+ }
128
+ .demo__states button[aria-checked="true"] {
129
+ color: var(--color-foreground, #18181b);
130
+ background: var(--color-card, #fff);
131
+ box-shadow: var(--elev-hairline, 0 0 0 1px rgb(0 0 0 / 0.06));
132
+ }
133
+ .demo__states button:focus-visible {
134
+ outline: 2px solid var(--color-ring, #6366f1);
135
+ outline-offset: 1px;
136
+ }
125
137
  </style>