@heyramzi/ui 2.23.0 → 2.24.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 (123) hide show
  1. package/COMPONENTS.md +3 -6
  2. package/dist/ai/confirmation/index.js +3 -6
  3. package/dist/ai/index.js +1 -5
  4. package/dist/charts/dashboard/index.js +1 -3
  5. package/dist/charts/primitives/chart-utils.js +14 -0
  6. package/dist/components/chip/index.js +1 -0
  7. package/dist/components/language-flag/flags.js +5 -0
  8. package/dist/components/language-flag/index.js +1 -0
  9. package/dist/components/list-page/index.js +1 -3
  10. package/dist/components/work-parts/index.js +1 -1
  11. package/dist/editor/doc-blocks.js +2 -1
  12. package/dist/effects/animated-beam/path-calculator.svelte.js +13 -6
  13. package/dist/lib/dates.js +41 -0
  14. package/dist/lib/panel.js +2 -2
  15. package/dist/lib/tone.js +13 -0
  16. package/dist/record/format.js +2 -18
  17. package/dist/record/logic.js +3 -6
  18. package/dist/status/index.js +1 -1
  19. package/dist/work/dates.js +2 -3
  20. package/dist/work/detail/detail-types.js +0 -8
  21. package/dist/work/docs/edited.js +8 -7
  22. package/dist/work/inbox/inbox-logic.js +5 -20
  23. package/dist/work/index.js +0 -2
  24. package/dist/work/time/duration.js +2 -3
  25. package/package.json +1 -21
  26. package/src/ai/confirmation/Confirmation.svelte +2 -2
  27. package/src/ai/confirmation/{ConfirmationRequest.svelte → ConfirmationState.svelte} +6 -3
  28. package/src/ai/confirmation/confirmation-context.svelte.ts +2 -2
  29. package/src/ai/confirmation/confirmation-parts.test.svelte +17 -0
  30. package/src/ai/confirmation/confirmation-parts.test.ts +23 -0
  31. package/src/ai/confirmation/index.ts +6 -21
  32. package/src/ai/index.ts +3 -13
  33. package/src/ai/typing-dots/TypingDots.svelte +32 -12
  34. package/src/ai/typing-dots/typing-dots.test.ts +36 -0
  35. package/src/canvas/ui/canvas-ui.css +12 -0
  36. package/src/charts/README.md +2 -2
  37. package/src/charts/area-chart.svelte +3 -10
  38. package/src/charts/bar-chart.svelte +4 -12
  39. package/src/charts/dashboard/data-table.svelte +21 -21
  40. package/src/charts/dashboard/index.ts +1 -3
  41. package/src/charts/dashboard/rating-chip.svelte +9 -11
  42. package/src/charts/dashboard/stat-tile.svelte +3 -4
  43. package/src/charts/line-chart.svelte +3 -10
  44. package/src/charts/primitives/chart-utils.test.ts +17 -0
  45. package/src/charts/primitives/chart-utils.ts +16 -0
  46. package/src/charts/time-series-chart.svelte +8 -4
  47. package/src/components/chip/count-chip.svelte +35 -0
  48. package/src/components/chip/index.ts +1 -0
  49. package/src/components/data-table/data-table.ts +1 -1
  50. package/src/components/data-table/row-context-menu.svelte +3 -4
  51. package/src/components/data-table/sortable-head.svelte +45 -10
  52. package/src/components/language-flag/flags.ts +5 -0
  53. package/src/components/language-flag/index.ts +1 -0
  54. package/src/components/language-flag/language-flag.svelte +3 -11
  55. package/src/components/list-page/empty-state.svelte +90 -12
  56. package/src/components/list-page/filter-popover.svelte +2 -5
  57. package/src/components/list-page/grouped-list.svelte +2 -4
  58. package/src/components/list-page/index.ts +1 -3
  59. package/src/components/section-header/section-header.svelte +2 -6
  60. package/src/components/segmented/segment.svelte +13 -19
  61. package/src/components/segmented/segmented-filter.svelte +1 -2
  62. package/src/components/table-view/table-view.svelte +31 -45
  63. package/src/components/table-view/table-view.test.ts +6 -3
  64. package/src/components/work-parts/group-head.svelte +1 -1
  65. package/src/components/work-parts/index.ts +1 -1
  66. package/src/editor/doc-blocks.ts +2 -1
  67. package/src/effects/animated-beam/path-calculator.svelte.ts +19 -5
  68. package/src/effects/marquee/Marquee.css +6 -3
  69. package/src/effects/marquee/Marquee.svelte +6 -2
  70. package/src/inbox/thread-inbox.svelte +6 -4
  71. package/src/lib/dates.test.ts +63 -0
  72. package/src/lib/dates.ts +63 -0
  73. package/src/lib/panel.svelte +116 -0
  74. package/src/lib/panel.ts +2 -2
  75. package/src/lib/tone.ts +15 -0
  76. package/src/panel/side-panel.svelte +4 -4
  77. package/src/record/format.ts +3 -15
  78. package/src/record/logic.ts +2 -6
  79. package/src/record/record-stats.svelte +4 -3
  80. package/src/record/steps-rail.svelte +7 -4
  81. package/src/status/index.ts +1 -1
  82. package/src/status/status-pill.svelte +2 -8
  83. package/src/thread/thread.svelte +3 -6
  84. package/src/work/README.md +0 -1
  85. package/src/work/dates.ts +3 -3
  86. package/src/work/demo.svelte +9 -1
  87. package/src/work/detail/detail-demo.svelte +30 -27
  88. package/src/work/detail/detail-types.ts +1 -29
  89. package/src/work/detail/task-detail.svelte +18 -17
  90. package/src/work/docs/doc-menu.svelte +2 -1
  91. package/src/work/docs/edited.ts +4 -7
  92. package/src/work/inbox/inbox-card.svelte +4 -9
  93. package/src/work/inbox/inbox-logic.ts +4 -16
  94. package/src/work/index.ts +1 -3
  95. package/src/work/time/duration.ts +2 -3
  96. package/dist/ai/thinking-dots/index.js +0 -3
  97. package/dist/components/icon/index.js +0 -1
  98. package/dist/components/locale-switch/index.js +0 -1
  99. package/dist/icons/trades.js +0 -49
  100. package/dist/status/pill-tint.js +0 -13
  101. package/dist/work/presets/sales.js +0 -39
  102. package/src/ai/confirmation/ConfirmationAccepted.svelte +0 -23
  103. package/src/ai/confirmation/ConfirmationFailed.svelte +0 -23
  104. package/src/ai/confirmation/ConfirmationRejected.svelte +0 -23
  105. package/src/ai/thinking-dots/ThinkingDots.svelte +0 -42
  106. package/src/ai/thinking-dots/index.ts +0 -5
  107. package/src/charts/dashboard/dashboard-empty.svelte +0 -55
  108. package/src/charts/dashboard/data-panel.svelte +0 -81
  109. package/src/charts/dashboard/data-sort-head.svelte +0 -102
  110. package/src/components/icon/icon.svelte +0 -23
  111. package/src/components/icon/index.ts +0 -1
  112. package/src/components/list-page/detail-empty.svelte +0 -45
  113. package/src/components/list-page/detail-panel.svelte +0 -82
  114. package/src/components/list-page/rail-empty.svelte +0 -44
  115. package/src/components/locale-switch/index.ts +0 -1
  116. package/src/components/locale-switch/locale-switch.svelte +0 -59
  117. package/src/components/work-parts/count-chip.svelte +0 -20
  118. package/src/icons/TradeIcon.svelte +0 -16
  119. package/src/icons/trades.ts +0 -89
  120. package/src/status/pill-tint.ts +0 -16
  121. package/src/work/detail/task-property.svelte +0 -17
  122. package/src/work/detail/task-thread.svelte +0 -221
  123. package/src/work/presets/sales.ts +0 -16
@@ -1,221 +0,0 @@
1
- <script lang="ts">
2
- import type { Snippet } from "svelte";
3
- import { PencilSimple, Trash } from "phosphor-svelte";
4
- import { initial } from "../../lib/initials.js";
5
- import { AgentAvatar } from "../../agents/index.js";
6
- import { Skeleton } from "../../shadcn/skeleton/index.js";
7
- import { Button } from "../../shadcn/button/index.js";
8
- import { Textarea } from "../../shadcn/textarea/index.js";
9
- import * as Avatar from "../../shadcn/avatar/index.js";
10
- import {
11
- DEFAULT_TASK_DETAIL_LABELS,
12
- type TaskComment,
13
- type TaskDetailLabels,
14
- } from "./detail-types.js";
15
-
16
- interface Props {
17
- comments: TaskComment[];
18
- /** Rows still on their way. Draws skeleton rows in place of the thread. */
19
- loading?: boolean;
20
- labels?: Partial<TaskDetailLabels>;
21
- /** Replaces the default agent avatar, drawn in a 24px slot. */
22
- agentAvatar?: Snippet<[TaskComment]>;
23
- /** Replaces the default initial for a person, drawn in a 24px slot. */
24
- avatar?: Snippet<[TaskComment]>;
25
- /** How a timestamp reads. Defaults to a short date. */
26
- when?: (comment: TaskComment) => string;
27
- /** The locale the default times read in. */
28
- locale?: string;
29
- /** Returns false to keep the draft. Without it the composer is hidden. */
30
- onSend?: (body: string) => void | boolean | Promise<void | boolean>;
31
- onEdit?: (comment: TaskComment, body: string) => void | Promise<void>;
32
- onDelete?: (comment: TaskComment) => void | Promise<void>;
33
- canEdit?: (comment: TaskComment) => boolean;
34
- }
35
-
36
- let {
37
- comments,
38
- loading = false,
39
- labels: labelOverrides,
40
- agentAvatar,
41
- avatar,
42
- locale = "en-GB",
43
- when = (comment) =>
44
- new Intl.DateTimeFormat(locale, { month: "short", day: "numeric" }).format(
45
- new Date(comment.createdAt),
46
- ),
47
- onSend,
48
- onEdit,
49
- onDelete,
50
- canEdit = () => false,
51
- }: Props = $props();
52
-
53
- let labels = $derived({ ...DEFAULT_TASK_DETAIL_LABELS, ...labelOverrides });
54
- let draft = $state("");
55
- let sending = $state(false);
56
- let editingId = $state<string | null>(null);
57
- let editDraft = $state("");
58
- let canSend = $derived(draft.trim().length > 0 && !sending);
59
-
60
- async function send(): Promise<void> {
61
- if (!canSend || !onSend) return;
62
- sending = true;
63
- try {
64
- const result = await onSend(draft.trim());
65
- if (result !== false) draft = "";
66
- } finally {
67
- sending = false;
68
- }
69
- }
70
-
71
- function onComposerKeydown(event: KeyboardEvent): void {
72
- if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
73
- event.preventDefault();
74
- void send();
75
- }
76
- }
77
-
78
- function startEdit(comment: TaskComment): void {
79
- editingId = comment.id;
80
- editDraft = comment.body;
81
- }
82
-
83
- async function saveEdit(comment: TaskComment): Promise<void> {
84
- const body = editDraft.trim();
85
- editingId = null;
86
- if (!body || body === comment.body) return;
87
- await onEdit?.(comment, body);
88
- }
89
- </script>
90
-
91
- <section aria-label={labels.comments} class="flex flex-col gap-3">
92
- <h2 class="flex h-7 items-center text-xs font-medium text-muted-foreground">{labels.comments}</h2>
93
-
94
- {#if loading}
95
- <ol class="flex flex-col gap-4" aria-busy="true">
96
- {#each [0, 1] as row (row)}
97
- <li class="flex gap-3">
98
- <Skeleton class="size-6 shrink-0 rounded-full" />
99
- <div class="flex flex-1 flex-col gap-2">
100
- <Skeleton class="h-3.5 w-28" />
101
- <Skeleton class="h-3.5 w-full" />
102
- </div>
103
- </li>
104
- {/each}
105
- </ol>
106
- {:else if comments.length > 0}
107
- <ol class="flex flex-col gap-4">
108
- {#each comments as comment (comment.id)}
109
- <li class="group hover-row relative flex gap-3">
110
- <!-- The rail that ties one avatar to the next, as in an activity feed. -->
111
- <span
112
- class="absolute start-[11.5px] top-8 -bottom-3 w-px bg-border group-last:hidden"
113
- aria-hidden="true"
114
- ></span>
115
- <span class="relative size-6 shrink-0">
116
- {#if comment.agent}
117
- {#if agentAvatar}
118
- {@render agentAvatar(comment)}
119
- {:else}
120
- <AgentAvatar name={comment.author} size={24} paused interactive={false} />
121
- {/if}
122
- {:else if avatar}
123
- {@render avatar(comment)}
124
- {:else}
125
- <Avatar.Root class="size-6" aria-hidden="true">
126
- <Avatar.Fallback class="text-xs font-medium"
127
- >{initial(comment.author)}</Avatar.Fallback
128
- >
129
- </Avatar.Root>
130
- {/if}
131
- </span>
132
-
133
- <div class="min-w-0 flex-1">
134
- <div class="flex h-6 items-center gap-2">
135
- <span class="truncate text-(length:--text-control) font-medium">{comment.author}</span
136
- >
137
- {#if comment.agent}
138
- <span class="sr-only">{labels.ai}</span>
139
- {/if}
140
- <span class="text-xs text-muted-foreground tabular-nums">{when(comment)}</span>
141
- {#if comment.edited}
142
- <span class="text-xs text-muted-foreground">{labels.commentEdited}</span>
143
- {/if}
144
- {#if canEdit(comment) && editingId !== comment.id}
145
- <span class="row-action ms-auto flex gap-0.5">
146
- {#if onEdit}
147
- <Button
148
- variant="ghost"
149
- size="sm"
150
- icon
151
- class="text-muted-foreground"
152
- aria-label={labels.commentEdit}
153
- onclick={() => startEdit(comment)}
154
- >
155
- <PencilSimple aria-hidden="true" />
156
- </Button>
157
- {/if}
158
- {#if onDelete}
159
- <Button
160
- variant="ghost"
161
- size="sm"
162
- icon
163
- class="text-muted-foreground"
164
- aria-label={labels.commentDelete}
165
- onclick={() => onDelete?.(comment)}
166
- >
167
- <Trash aria-hidden="true" />
168
- </Button>
169
- {/if}
170
- </span>
171
- {/if}
172
- </div>
173
-
174
- {#if editingId === comment.id}
175
- <Textarea
176
- bind:value={editDraft}
177
- rows={3}
178
- aria-label={labels.comments}
179
- class="mt-1 resize-y leading-relaxed"
180
- />
181
- <div class="mt-2 flex justify-end gap-1.5">
182
- <Button variant="ghost" size="sm" onclick={() => (editingId = null)}
183
- >{labels.cancel}</Button
184
- >
185
- <Button size="sm" onclick={() => saveEdit(comment)}>{labels.save}</Button>
186
- </div>
187
- {:else}
188
- <p class="text-sm leading-relaxed whitespace-pre-wrap text-pretty">{comment.body}</p>
189
- {/if}
190
- </div>
191
- </li>
192
- {/each}
193
- </ol>
194
- {:else if !onSend}
195
- <p class="text-(length:--text-control) text-muted-foreground">{labels.commentsEmpty}</p>
196
- {/if}
197
-
198
- {#if onSend}
199
- <!-- The send button sits inside the field's bottom edge, so the composer reads as one box. -->
200
- <div class="relative">
201
- <Textarea
202
- bind:value={draft}
203
- onkeydown={onComposerKeydown}
204
- rows={2}
205
- placeholder={labels.commentPlaceholder}
206
- aria-label={labels.commentPlaceholder}
207
- class="max-h-60 resize-none px-3 pb-11 leading-relaxed"
208
- />
209
- <!-- An empty draft reads as an outlined button, not a faded fill. -->
210
- <Button
211
- size="sm"
212
- variant={canSend ? "default" : "outline"}
213
- class="absolute end-2 bottom-2 disabled:opacity-100"
214
- onclick={send}
215
- disabled={!canSend}
216
- >
217
- {sending ? labels.saving : labels.commentSend}
218
- </Button>
219
- </div>
220
- {/if}
221
- </section>
@@ -1,16 +0,0 @@
1
- import { defineStatuses } from "../../status/define-statuses.js";
2
-
3
- /**
4
- * An example status map for a sales pipeline. Names are neutral on purpose:
5
- * swap the keys and labels for your own domain.
6
- */
7
- export const salesStatuses = defineStatuses({
8
- new: { label: "New", tone: "accent", variant: "open" },
9
- contacted: { label: "Contacted", tone: "info", variant: "open" },
10
- proposal: { label: "Proposal", tone: "accent", variant: "progress", progress: 0.25 },
11
- negotiation: { label: "Negotiation", tone: "warning", variant: "progress", progress: 0.75 },
12
- won: { label: "Won", tone: "success", variant: "completed" },
13
- lost: { label: "Lost", tone: "destructive", variant: "lost" },
14
- });
15
-
16
- export type SalesStatus = (typeof salesStatuses.ids)[number];