@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.
- package/COMPONENTS.md +3 -6
- package/dist/ai/confirmation/index.js +3 -6
- package/dist/ai/index.js +1 -5
- package/dist/charts/dashboard/index.js +1 -3
- package/dist/charts/primitives/chart-utils.js +14 -0
- package/dist/components/chip/index.js +1 -0
- package/dist/components/language-flag/flags.js +5 -0
- package/dist/components/language-flag/index.js +1 -0
- package/dist/components/list-page/index.js +1 -3
- package/dist/components/work-parts/index.js +1 -1
- package/dist/editor/doc-blocks.js +2 -1
- package/dist/effects/animated-beam/path-calculator.svelte.js +13 -6
- package/dist/lib/dates.js +41 -0
- package/dist/lib/panel.js +2 -2
- package/dist/lib/tone.js +13 -0
- package/dist/record/format.js +2 -18
- package/dist/record/logic.js +3 -6
- package/dist/status/index.js +1 -1
- package/dist/work/dates.js +2 -3
- package/dist/work/detail/detail-types.js +0 -8
- package/dist/work/docs/edited.js +8 -7
- package/dist/work/inbox/inbox-logic.js +5 -20
- package/dist/work/index.js +0 -2
- package/dist/work/time/duration.js +2 -3
- package/package.json +1 -21
- package/src/ai/confirmation/Confirmation.svelte +2 -2
- package/src/ai/confirmation/{ConfirmationRequest.svelte → ConfirmationState.svelte} +6 -3
- package/src/ai/confirmation/confirmation-context.svelte.ts +2 -2
- package/src/ai/confirmation/confirmation-parts.test.svelte +17 -0
- package/src/ai/confirmation/confirmation-parts.test.ts +23 -0
- package/src/ai/confirmation/index.ts +6 -21
- package/src/ai/index.ts +3 -13
- package/src/ai/typing-dots/TypingDots.svelte +32 -12
- package/src/ai/typing-dots/typing-dots.test.ts +36 -0
- package/src/canvas/ui/canvas-ui.css +12 -0
- package/src/charts/README.md +2 -2
- package/src/charts/area-chart.svelte +3 -10
- package/src/charts/bar-chart.svelte +4 -12
- package/src/charts/dashboard/data-table.svelte +21 -21
- package/src/charts/dashboard/index.ts +1 -3
- package/src/charts/dashboard/rating-chip.svelte +9 -11
- package/src/charts/dashboard/stat-tile.svelte +3 -4
- package/src/charts/line-chart.svelte +3 -10
- package/src/charts/primitives/chart-utils.test.ts +17 -0
- package/src/charts/primitives/chart-utils.ts +16 -0
- package/src/charts/time-series-chart.svelte +8 -4
- package/src/components/chip/count-chip.svelte +35 -0
- package/src/components/chip/index.ts +1 -0
- package/src/components/data-table/data-table.ts +1 -1
- package/src/components/data-table/row-context-menu.svelte +3 -4
- package/src/components/data-table/sortable-head.svelte +45 -10
- package/src/components/language-flag/flags.ts +5 -0
- package/src/components/language-flag/index.ts +1 -0
- package/src/components/language-flag/language-flag.svelte +3 -11
- package/src/components/list-page/empty-state.svelte +90 -12
- package/src/components/list-page/filter-popover.svelte +2 -5
- package/src/components/list-page/grouped-list.svelte +2 -4
- package/src/components/list-page/index.ts +1 -3
- package/src/components/section-header/section-header.svelte +2 -6
- package/src/components/segmented/segment.svelte +13 -19
- package/src/components/segmented/segmented-filter.svelte +1 -2
- package/src/components/table-view/table-view.svelte +31 -45
- package/src/components/table-view/table-view.test.ts +6 -3
- package/src/components/work-parts/group-head.svelte +1 -1
- package/src/components/work-parts/index.ts +1 -1
- package/src/editor/doc-blocks.ts +2 -1
- package/src/effects/animated-beam/path-calculator.svelte.ts +19 -5
- package/src/effects/marquee/Marquee.css +6 -3
- package/src/effects/marquee/Marquee.svelte +6 -2
- package/src/inbox/thread-inbox.svelte +6 -4
- package/src/lib/dates.test.ts +63 -0
- package/src/lib/dates.ts +63 -0
- package/src/lib/panel.svelte +116 -0
- package/src/lib/panel.ts +2 -2
- package/src/lib/tone.ts +15 -0
- package/src/panel/side-panel.svelte +4 -4
- package/src/record/format.ts +3 -15
- package/src/record/logic.ts +2 -6
- package/src/record/record-stats.svelte +4 -3
- package/src/record/steps-rail.svelte +7 -4
- package/src/status/index.ts +1 -1
- package/src/status/status-pill.svelte +2 -8
- package/src/thread/thread.svelte +3 -6
- package/src/work/README.md +0 -1
- package/src/work/dates.ts +3 -3
- package/src/work/demo.svelte +9 -1
- package/src/work/detail/detail-demo.svelte +30 -27
- package/src/work/detail/detail-types.ts +1 -29
- package/src/work/detail/task-detail.svelte +18 -17
- package/src/work/docs/doc-menu.svelte +2 -1
- package/src/work/docs/edited.ts +4 -7
- package/src/work/inbox/inbox-card.svelte +4 -9
- package/src/work/inbox/inbox-logic.ts +4 -16
- package/src/work/index.ts +1 -3
- package/src/work/time/duration.ts +2 -3
- package/dist/ai/thinking-dots/index.js +0 -3
- package/dist/components/icon/index.js +0 -1
- package/dist/components/locale-switch/index.js +0 -1
- package/dist/icons/trades.js +0 -49
- package/dist/status/pill-tint.js +0 -13
- package/dist/work/presets/sales.js +0 -39
- package/src/ai/confirmation/ConfirmationAccepted.svelte +0 -23
- package/src/ai/confirmation/ConfirmationFailed.svelte +0 -23
- package/src/ai/confirmation/ConfirmationRejected.svelte +0 -23
- package/src/ai/thinking-dots/ThinkingDots.svelte +0 -42
- package/src/ai/thinking-dots/index.ts +0 -5
- package/src/charts/dashboard/dashboard-empty.svelte +0 -55
- package/src/charts/dashboard/data-panel.svelte +0 -81
- package/src/charts/dashboard/data-sort-head.svelte +0 -102
- package/src/components/icon/icon.svelte +0 -23
- package/src/components/icon/index.ts +0 -1
- package/src/components/list-page/detail-empty.svelte +0 -45
- package/src/components/list-page/detail-panel.svelte +0 -82
- package/src/components/list-page/rail-empty.svelte +0 -44
- package/src/components/locale-switch/index.ts +0 -1
- package/src/components/locale-switch/locale-switch.svelte +0 -59
- package/src/components/work-parts/count-chip.svelte +0 -20
- package/src/icons/TradeIcon.svelte +0 -16
- package/src/icons/trades.ts +0 -89
- package/src/status/pill-tint.ts +0 -16
- package/src/work/detail/task-property.svelte +0 -17
- package/src/work/detail/task-thread.svelte +0 -221
- 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];
|