@heyramzi/ui 2.22.1 → 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/canvas/editor/rebase.js +26 -2
- 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/editor/safe-url.js +26 -0
- package/dist/editor/serializer.js +10 -4
- package/dist/editor/slash-query.js +10 -0
- 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/triage/index.js +4 -0
- package/dist/triage/types.js +12 -0
- 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 +7 -21
- package/scripts/sync-shadcn.mjs +4 -6
- 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/animations/modal.css +4 -1
- package/src/canvas/editor/rebase.test.ts +37 -0
- package/src/canvas/editor/rebase.ts +33 -1
- package/src/canvas/ui/canvas-ui.css +44 -1
- package/src/charts/README.md +2 -2
- package/src/charts/area-chart.svelte +5 -12
- package/src/charts/bar-chart.svelte +6 -14
- package/src/charts/chart-tokens.css +19 -0
- 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 +4 -5
- package/src/charts/donut-chart.svelte +1 -1
- package/src/charts/gauge-chart.svelte +1 -1
- package/src/charts/line-chart.svelte +5 -12
- package/src/charts/number-chart.svelte +1 -1
- package/src/charts/primitives/chart-utils.test.ts +17 -0
- package/src/charts/primitives/chart-utils.ts +16 -0
- package/src/charts/ring-chart.svelte +2 -2
- package/src/charts/sparkline.svelte +1 -1
- package/src/charts/stat-card.svelte +1 -1
- package/src/charts/time-series-chart.svelte +9 -5
- 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/editor/editor.svelte +7 -5
- package/src/editor/safe-url.ts +32 -0
- package/src/editor/serializer.test.ts +58 -0
- package/src/editor/serializer.ts +9 -6
- package/src/editor/slash-query.test.ts +19 -0
- package/src/editor/slash-query.ts +11 -0
- 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/modules.test.ts +13 -1
- 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/shadcn/alert-dialog/alert-dialog-overlay.svelte +1 -1
- package/src/shadcn/button/button.svelte +1 -1
- package/src/shadcn/button/button.test.ts +2 -2
- package/src/shadcn/command/command-dialog.svelte +5 -10
- package/src/shadcn/dialog/dialog-overlay.svelte +1 -1
- package/src/shadcn/input/input.svelte +2 -2
- package/src/shadcn/sheet/sheet-overlay.svelte +1 -1
- package/src/status/index.ts +1 -1
- package/src/status/status-pill.svelte +2 -8
- package/src/thread/thread.svelte +3 -6
- package/src/tokens/craft.css +30 -0
- package/src/triage/README.md +28 -0
- package/src/triage/index.ts +10 -0
- package/src/triage/triage-plan.svelte +132 -0
- package/src/triage/triage-queue.svelte +48 -0
- package/src/triage/triage-task.svelte +95 -0
- package/src/triage/types.ts +35 -0
- 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/kanban-column.svelte +5 -3
- package/src/work/time/duration.ts +2 -3
- package/src/work/time/time-chip.svelte +1 -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
package/src/status/pill-tint.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { Tone } from "../lib/tone.js";
|
|
2
|
-
|
|
3
|
-
// A quiet tint and no border: the icon and the text carry the tone, the fill only groups
|
|
4
|
-
// them. Neutral reads off the foreground, not `bg-muted`, because muted sits 0.005 L from
|
|
5
|
-
// the canvas and vanishes there (tokens board, "what fights the new scale").
|
|
6
|
-
// It lives in a .ts module, not status-pill.svelte's module script, so a plain tsc consumer
|
|
7
|
-
// can import it: tsc's `*.svelte` shim only knows a default export.
|
|
8
|
-
export const PILL_TINT: Record<Tone, string> = {
|
|
9
|
-
neutral: "bg-foreground/6 text-muted-foreground",
|
|
10
|
-
accent:
|
|
11
|
-
"bg-[color-mix(in_oklab,var(--tone-accent,var(--color-primary))_12%,transparent)] text-[color:var(--tone-accent,var(--color-primary))]",
|
|
12
|
-
info: "bg-info/12 text-info-800 dark:text-info-400",
|
|
13
|
-
success: "bg-success/12 text-success-800 dark:text-success-400",
|
|
14
|
-
warning: "bg-warning/14 text-warning-800 dark:text-warning-400",
|
|
15
|
-
destructive: "bg-destructive/10 text-destructive-ink",
|
|
16
|
-
};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Component, Snippet } from "svelte";
|
|
3
|
-
import PropertyRow from "../../components/work-parts/property-row.svelte";
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
label: string;
|
|
7
|
-
/** A Phosphor icon before the label, shown when the rail is wide. */
|
|
8
|
-
icon?: Component<{ class?: string; "aria-hidden"?: boolean | "true" | "false" }>;
|
|
9
|
-
children: Snippet;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
let { label, icon, children }: Props = $props();
|
|
13
|
-
</script>
|
|
14
|
-
|
|
15
|
-
<!-- A labelled row in the rail: icon, label, value. In the narrow chip row the label hides and
|
|
16
|
-
names the group for assistive tech. -->
|
|
17
|
-
<PropertyRow {label} {icon} layout="responsive">{@render children()}</PropertyRow>
|
|
@@ -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];
|