@heyramzi/ui 3.1.0 → 3.3.1
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/dist/components/list-page/toolbar-density.js +20 -1
- package/dist/lib/sliding-pill.js +2 -2
- package/dist/record/measure-clamp.js +23 -0
- package/dist/shadcn/button-group/index.js +6 -0
- package/dist/shadcn/checkbox/checkbox-box.js +3 -0
- package/dist/shadcn/drawer/index.js +14 -0
- package/dist/shadcn/input-group/index.js +9 -0
- package/dist/shadcn/item/index.js +13 -0
- package/dist/shadcn/native-select/index.js +6 -0
- package/dist/shadcn/pagination/index.js +12 -0
- package/package.json +7 -2
- package/scripts/sync-shadcn.mjs +0 -6
- package/src/ai/generation-progress/GenerationProgress.svelte +14 -12
- package/src/canvas/pen/PenOverlay.svelte +1 -30
- package/src/canvas/screen/PartView.svelte +13 -8
- package/src/canvas/screen/ScreenBody.svelte +18 -11
- package/src/canvas/ui/BarTooltip.svelte +46 -0
- package/src/canvas/ui/BarTooltip.svelte.d.ts +17 -0
- package/src/canvas/ui/CanvasToolbar.svelte +170 -156
- package/src/canvas/ui/StylePanel.svelte +179 -102
- package/src/canvas/ui/canvas-ui.css +12 -76
- package/src/charts/dashboard/data-table.svelte +80 -80
- package/src/charts/dashboard/hint.svelte +34 -0
- package/src/charts/dashboard/hint.svelte.d.ts +10 -0
- package/src/charts/dashboard/rating-chip.svelte +4 -3
- package/src/charts/legend.css +0 -8
- package/src/charts/legend.svelte +26 -30
- package/src/components/copy/copy-button.svelte +10 -2
- package/src/components/copy/copy-button.test.ts +7 -0
- package/src/components/data-table/table-skeleton.svelte +15 -7
- package/src/components/data-table/table-skeleton.svelte.d.ts +4 -0
- package/src/components/docs/on-this-page.svelte +2 -2
- package/src/components/hold-to-confirm/hold-to-confirm.svelte +2 -1
- package/src/components/list-page/filter-item.svelte +20 -7
- package/src/components/list-page/filter-popover.svelte +57 -17
- package/src/components/list-page/filter-popover.svelte.d.ts +1 -1
- package/src/components/list-page/grouped-list.svelte +41 -23
- package/src/components/list-page/list-page-shell.svelte +155 -69
- package/src/components/list-page/list-page-shell.svelte.d.ts +6 -1
- package/src/components/list-page/toolbar-density.ts +24 -1
- package/src/components/picker/picker.svelte +8 -3
- package/src/components/picker/picker.svelte.d.ts +2 -1
- package/src/components/segmented/segmented-filter.svelte +19 -10
- package/src/components/segmented/segmented-track.svelte +11 -3
- package/src/components/table-view/table-view.svelte +22 -6
- package/src/components/tags-input/tags-input.svelte +94 -77
- package/src/components/toolbar/toolbar.svelte +2 -1
- package/src/components/toolbar/toolbar.test.ts +5 -4
- package/src/components/work-parts/group-head.svelte +28 -9
- package/src/components/work-parts/group-head.svelte.d.ts +5 -2
- package/src/editor/editor-toolbar.svelte +223 -193
- package/src/editor/editor.svelte +56 -38
- package/src/editor/image-toolbar.svelte +99 -37
- package/src/editor/image-toolbar.svelte.d.ts +4 -5
- package/src/editor/url-dialog.svelte +96 -0
- package/src/editor/url-dialog.svelte.d.ts +15 -0
- package/src/effects/theme-toggle/ThemeToggle.css +8 -8
- package/src/effects/theme-toggle/ThemeToggle.svelte +20 -6
- package/src/inbox/thread-inbox.svelte +9 -1
- package/src/lib/live-region.svelte +12 -4
- package/src/lib/live-region.svelte.d.ts +5 -1
- package/src/lib/sliding-pill.ts +3 -2
- package/src/record/info-list.svelte +33 -59
- package/src/record/measure-clamp.ts +31 -0
- package/src/record/record-shell.svelte +38 -39
- package/src/record/record-timeline.svelte +10 -5
- package/src/record/steps-rail.svelte +50 -36
- package/src/record/where-we-are.svelte +5 -19
- package/src/shadcn/button-group/button-group-separator.svelte +23 -0
- package/src/shadcn/button-group/button-group-separator.svelte.d.ts +13 -0
- package/src/shadcn/button-group/button-group-text.svelte +28 -0
- package/src/shadcn/button-group/button-group-text.svelte.d.ts +11 -0
- package/src/shadcn/button-group/button-group.svelte +46 -0
- package/src/shadcn/button-group/button-group.svelte.d.ts +16 -0
- package/src/shadcn/button-group/index.ts +15 -0
- package/src/shadcn/checkbox/checkbox-box.ts +4 -0
- package/src/shadcn/checkbox/checkbox.svelte +2 -4
- package/src/shadcn/drawer/drawer-close.svelte +7 -0
- package/src/shadcn/drawer/drawer-close.svelte.d.ts +4 -0
- package/src/shadcn/drawer/drawer-content.svelte +36 -0
- package/src/shadcn/drawer/drawer-content.svelte.d.ts +10 -0
- package/src/shadcn/drawer/drawer-description.svelte +17 -0
- package/src/shadcn/drawer/drawer-description.svelte.d.ts +4 -0
- package/src/shadcn/drawer/drawer-footer.svelte +20 -0
- package/src/shadcn/drawer/drawer-footer.svelte.d.ts +5 -0
- package/src/shadcn/drawer/drawer-header.svelte +23 -0
- package/src/shadcn/drawer/drawer-header.svelte.d.ts +5 -0
- package/src/shadcn/drawer/drawer-nested.svelte +12 -0
- package/src/shadcn/drawer/drawer-nested.svelte.d.ts +3 -0
- package/src/shadcn/drawer/drawer-overlay.svelte +20 -0
- package/src/shadcn/drawer/drawer-overlay.svelte.d.ts +4 -0
- package/src/shadcn/drawer/drawer-portal.svelte +7 -0
- package/src/shadcn/drawer/drawer-portal.svelte.d.ts +3 -0
- package/src/shadcn/drawer/drawer-title.svelte +17 -0
- package/src/shadcn/drawer/drawer-title.svelte.d.ts +4 -0
- package/src/shadcn/drawer/drawer-trigger.svelte +7 -0
- package/src/shadcn/drawer/drawer-trigger.svelte.d.ts +4 -0
- package/src/shadcn/drawer/drawer.svelte +12 -0
- package/src/shadcn/drawer/drawer.svelte.d.ts +3 -0
- package/src/shadcn/drawer/index.ts +38 -0
- package/src/shadcn/input-group/index.ts +22 -0
- package/src/shadcn/input-group/input-group-addon.svelte +51 -0
- package/src/shadcn/input-group/input-group-addon.svelte.d.ts +18 -0
- package/src/shadcn/input-group/input-group-button.svelte +49 -0
- package/src/shadcn/input-group/input-group-button.svelte.d.ts +18 -0
- package/src/shadcn/input-group/input-group-input.svelte +20 -0
- package/src/shadcn/input-group/input-group-input.svelte.d.ts +11 -0
- package/src/shadcn/input-group/input-group-text.svelte +19 -0
- package/src/shadcn/input-group/input-group-text.svelte.d.ts +5 -0
- package/src/shadcn/input-group/input-group-textarea.svelte +20 -0
- package/src/shadcn/input-group/input-group-textarea.svelte.d.ts +3 -0
- package/src/shadcn/input-group/input-group.svelte +24 -0
- package/src/shadcn/input-group/input-group.svelte.d.ts +5 -0
- package/src/shadcn/item/index.ts +34 -0
- package/src/shadcn/item/item-actions.svelte +20 -0
- package/src/shadcn/item/item-actions.svelte.d.ts +5 -0
- package/src/shadcn/item/item-content.svelte +23 -0
- package/src/shadcn/item/item-content.svelte.d.ts +5 -0
- package/src/shadcn/item/item-description.svelte +23 -0
- package/src/shadcn/item/item-description.svelte.d.ts +5 -0
- package/src/shadcn/item/item-footer.svelte +20 -0
- package/src/shadcn/item/item-footer.svelte.d.ts +5 -0
- package/src/shadcn/item/item-group.svelte +21 -0
- package/src/shadcn/item/item-group.svelte.d.ts +5 -0
- package/src/shadcn/item/item-header.svelte +20 -0
- package/src/shadcn/item/item-header.svelte.d.ts +5 -0
- package/src/shadcn/item/item-media.svelte +42 -0
- package/src/shadcn/item/item-media.svelte.d.ts +17 -0
- package/src/shadcn/item/item-separator.svelte +19 -0
- package/src/shadcn/item/item-separator.svelte.d.ts +13 -0
- package/src/shadcn/item/item-title.svelte +20 -0
- package/src/shadcn/item/item-title.svelte.d.ts +5 -0
- package/src/shadcn/item/item.svelte +61 -0
- package/src/shadcn/item/item.svelte.d.ts +28 -0
- package/src/shadcn/native-select/index.ts +13 -0
- package/src/shadcn/native-select/native-select-opt-group.svelte +20 -0
- package/src/shadcn/native-select/native-select-opt-group.svelte.d.ts +5 -0
- package/src/shadcn/native-select/native-select-option.svelte +20 -0
- package/src/shadcn/native-select/native-select-option.svelte.d.ts +5 -0
- package/src/shadcn/native-select/native-select.svelte +45 -0
- package/src/shadcn/native-select/native-select.svelte.d.ts +8 -0
- package/src/shadcn/pagination/index.ts +31 -0
- package/src/shadcn/pagination/pagination-content.svelte +20 -0
- package/src/shadcn/pagination/pagination-content.svelte.d.ts +5 -0
- package/src/shadcn/pagination/pagination-ellipsis.svelte +22 -0
- package/src/shadcn/pagination/pagination-ellipsis.svelte.d.ts +5 -0
- package/src/shadcn/pagination/pagination-item.svelte +14 -0
- package/src/shadcn/pagination/pagination-item.svelte.d.ts +5 -0
- package/src/shadcn/pagination/pagination-link.svelte +41 -0
- package/src/shadcn/pagination/pagination-link.svelte.d.ts +9 -0
- package/src/shadcn/pagination/pagination-next-button.svelte +34 -0
- package/src/shadcn/pagination/pagination-next-button.svelte.d.ts +4 -0
- package/src/shadcn/pagination/pagination-next.svelte +26 -0
- package/src/shadcn/pagination/pagination-next.svelte.d.ts +4 -0
- package/src/shadcn/pagination/pagination-prev-button.svelte +34 -0
- package/src/shadcn/pagination/pagination-prev-button.svelte.d.ts +4 -0
- package/src/shadcn/pagination/pagination-previous.svelte +30 -0
- package/src/shadcn/pagination/pagination-previous.svelte.d.ts +4 -0
- package/src/shadcn/pagination/pagination.svelte +27 -0
- package/src/shadcn/pagination/pagination.svelte.d.ts +4 -0
- package/src/slides/Controls.svelte +39 -36
- package/src/slides/Deck.svelte +11 -8
- package/src/thread/thread.svelte +15 -8
- package/src/work/detail/task-detail.svelte +1 -1
- package/src/work/gantt/gantt-task-row.svelte +3 -6
- package/src/work/inbox/inbox-card.svelte +7 -5
- package/src/work/inbox/inbox-trace.svelte +14 -10
- package/src/work/kanban-board.svelte +40 -25
- package/src/work/kanban-hidden-rail.svelte +67 -65
- package/src/work/task-list.svelte +145 -124
- package/src/work/task-list.svelte.test.ts +5 -2
- package/src/work/time/time-tracker.svelte +35 -10
|
@@ -66,33 +66,45 @@
|
|
|
66
66
|
{@render header()}
|
|
67
67
|
{@render banner?.()}
|
|
68
68
|
|
|
69
|
+
<!-- The rail is drawn twice, once docked and once in the sheet. Only one is ever on
|
|
70
|
+
screen, and the sheet mounts its copy on open. -->
|
|
69
71
|
{#if rail}
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
72
|
+
<Sheet.Root bind:open={railOpen}>
|
|
73
|
+
<Sheet.Trigger>
|
|
74
|
+
{#snippet child({ props })}
|
|
75
|
+
<button
|
|
76
|
+
type="button"
|
|
77
|
+
{...props}
|
|
78
|
+
class={cn(
|
|
79
|
+
"t-press flex min-h-11 w-full items-center gap-3 border-b border-border py-2 text-left @3xl:hidden",
|
|
80
|
+
gutterClass,
|
|
81
|
+
)}
|
|
82
|
+
>
|
|
83
|
+
<span class="text-sm font-medium">{railTitle ?? t.steps}</span>
|
|
84
|
+
{#if railProgress}
|
|
85
|
+
<span class="text-xs tabular-nums text-muted-foreground">
|
|
86
|
+
{t.stepsCount(railProgress.done, railProgress.total)}
|
|
87
|
+
</span>
|
|
88
|
+
<Progress
|
|
89
|
+
value={percent}
|
|
90
|
+
max={100}
|
|
91
|
+
class="h-1 flex-1"
|
|
92
|
+
aria-label={t.stepsCount(railProgress.done, railProgress.total)}
|
|
93
|
+
/>
|
|
94
|
+
{:else}
|
|
95
|
+
<span class="flex-1"></span>
|
|
96
|
+
{/if}
|
|
97
|
+
<CaretRight class="size-4 shrink-0 text-muted-foreground" aria-hidden="true" />
|
|
98
|
+
</button>
|
|
99
|
+
{/snippet}
|
|
100
|
+
</Sheet.Trigger>
|
|
101
|
+
<Sheet.Content side="bottom" class="gap-0 p-0">
|
|
102
|
+
<Sheet.Header class="sr-only">
|
|
103
|
+
<Sheet.Title>{railTitle ?? t.steps}</Sheet.Title>
|
|
104
|
+
</Sheet.Header>
|
|
105
|
+
<div class="overflow-y-auto p-4 pt-6">{@render rail()}</div>
|
|
106
|
+
</Sheet.Content>
|
|
107
|
+
</Sheet.Root>
|
|
96
108
|
{/if}
|
|
97
109
|
|
|
98
110
|
<div class="flex min-w-0 flex-col @3xl:flex-row">
|
|
@@ -123,16 +135,3 @@
|
|
|
123
135
|
{/if}
|
|
124
136
|
</div>
|
|
125
137
|
</div>
|
|
126
|
-
|
|
127
|
-
<!-- The rail is drawn twice, once docked and once here. Only one is ever on screen,
|
|
128
|
-
and the sheet mounts its copy on open. -->
|
|
129
|
-
{#if rail}
|
|
130
|
-
<Sheet.Root bind:open={railOpen}>
|
|
131
|
-
<Sheet.Content side="bottom" class="gap-0 p-0">
|
|
132
|
-
<Sheet.Header class="sr-only">
|
|
133
|
-
<Sheet.Title>{railTitle ?? t.steps}</Sheet.Title>
|
|
134
|
-
</Sheet.Header>
|
|
135
|
-
<div class="overflow-y-auto p-4 pt-6">{@render rail()}</div>
|
|
136
|
-
</Sheet.Content>
|
|
137
|
-
</Sheet.Root>
|
|
138
|
-
{/if}
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { TONE_ICON } from "../lib/tone.js";
|
|
14
14
|
import { DEFAULT_RECORD_FILTERS, DEFAULT_RECORD_KINDS } from "./kinds.js";
|
|
15
15
|
import { formatDayHeader, formatMoney, formatTime } from "./format.js";
|
|
16
|
+
import { measureClamp } from "./measure-clamp.js";
|
|
16
17
|
import {
|
|
17
18
|
dayRelation,
|
|
18
19
|
eventsForFilter,
|
|
@@ -78,6 +79,8 @@
|
|
|
78
79
|
// =========================
|
|
79
80
|
let showAll = $state(false);
|
|
80
81
|
const expanded = new SvelteSet<string>();
|
|
82
|
+
// Ids whose body is cut by its clamp, as measured.
|
|
83
|
+
const cut = new SvelteSet<string>();
|
|
81
84
|
|
|
82
85
|
// =========================
|
|
83
86
|
// DERIVED
|
|
@@ -110,10 +113,11 @@
|
|
|
110
113
|
return kindByKey.get(event.kind) ?? { key: event.kind, label: event.kind };
|
|
111
114
|
}
|
|
112
115
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
116
|
+
function measureBody(id: string) {
|
|
117
|
+
return measureClamp(
|
|
118
|
+
() => expanded.has(id),
|
|
119
|
+
(isCut) => (isCut ? cut.add(id) : cut.delete(id)),
|
|
120
|
+
);
|
|
117
121
|
}
|
|
118
122
|
</script>
|
|
119
123
|
|
|
@@ -180,6 +184,7 @@
|
|
|
180
184
|
</p>
|
|
181
185
|
{#if event.body}
|
|
182
186
|
<p
|
|
187
|
+
{@attach measureBody(event.id)}
|
|
183
188
|
class={cn(
|
|
184
189
|
"mt-0.5 text-sm leading-snug whitespace-pre-line text-muted-foreground wrap-anywhere",
|
|
185
190
|
!expanded.has(event.id) && "line-clamp-3",
|
|
@@ -187,7 +192,7 @@
|
|
|
187
192
|
>
|
|
188
193
|
{event.body}
|
|
189
194
|
</p>
|
|
190
|
-
{#if
|
|
195
|
+
{#if cut.has(event.id) || expanded.has(event.id)}
|
|
191
196
|
<Button
|
|
192
197
|
variant="ghost"
|
|
193
198
|
size="sm"
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
import CountChip from "../components/chip/count-chip.svelte";
|
|
18
18
|
import { Input } from "../shadcn/input/index.js";
|
|
19
19
|
import { Skeleton } from "../shadcn/skeleton/index.js";
|
|
20
|
-
import
|
|
20
|
+
import { DropdownMenu as MenuPrimitive } from "bits-ui";
|
|
21
|
+
import * as DropdownMenu from "../shadcn/dropdown-menu/index.js";
|
|
21
22
|
import * as ContextMenu from "../shadcn/context-menu/index.js";
|
|
22
23
|
import { todayIso } from "../work/dates.js";
|
|
23
24
|
import { formatRange } from "./format.js";
|
|
@@ -267,8 +268,8 @@
|
|
|
267
268
|
</span>
|
|
268
269
|
{/if}
|
|
269
270
|
{#if onToggle && !loading && ordered.length > 0}
|
|
270
|
-
<
|
|
271
|
-
<
|
|
271
|
+
<DropdownMenu.Root bind:open={menuOpen}>
|
|
272
|
+
<DropdownMenu.Trigger>
|
|
272
273
|
{#snippet child({ props })}
|
|
273
274
|
<Button
|
|
274
275
|
{...props}
|
|
@@ -276,7 +277,7 @@
|
|
|
276
277
|
size="sm"
|
|
277
278
|
icon
|
|
278
279
|
class="relative ml-auto text-muted-foreground"
|
|
279
|
-
aria-label={t.editSteps}
|
|
280
|
+
aria-label={hiddenCount > 0 ? `${t.editSteps}: ${hiddenCount}` : t.editSteps}
|
|
280
281
|
>
|
|
281
282
|
<DotsThreeVertical aria-hidden="true" class="size-4" weight="bold" />
|
|
282
283
|
{#if hiddenCount > 0}
|
|
@@ -289,44 +290,57 @@
|
|
|
289
290
|
{/if}
|
|
290
291
|
</Button>
|
|
291
292
|
{/snippet}
|
|
292
|
-
</
|
|
293
|
-
<
|
|
293
|
+
</DropdownMenu.Trigger>
|
|
294
|
+
<DropdownMenu.Content align="end" class="w-64 rounded-2xl">
|
|
294
295
|
{#each menuBuckets as bucket (bucket.key)}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
{
|
|
309
|
-
|
|
310
|
-
{:else}
|
|
311
|
-
<Eye aria-hidden="true" class="size-3.5" />
|
|
312
|
-
{/if}
|
|
313
|
-
</span>
|
|
314
|
-
<span
|
|
315
|
-
class={cn(
|
|
316
|
-
"min-w-0 flex-1 truncate",
|
|
317
|
-
step.hidden && "text-muted-foreground line-through",
|
|
318
|
-
)}>{step.label}</span
|
|
296
|
+
<DropdownMenu.Group>
|
|
297
|
+
{#if bucket.label}
|
|
298
|
+
<DropdownMenu.GroupHeading
|
|
299
|
+
class="px-2 pt-2 pb-1 text-xs font-medium text-muted-foreground"
|
|
300
|
+
>
|
|
301
|
+
{bucket.label}
|
|
302
|
+
</DropdownMenu.GroupHeading>
|
|
303
|
+
{/if}
|
|
304
|
+
{#each bucket.steps as step (step.id)}
|
|
305
|
+
<!-- Bits' item around the kit's ghost Button, not the shadcn row: the eye is
|
|
306
|
+
the checkmark here, so the row keeps its own look. -->
|
|
307
|
+
<MenuPrimitive.CheckboxItem
|
|
308
|
+
checked={!step.hidden}
|
|
309
|
+
closeOnSelect={false}
|
|
310
|
+
onCheckedChange={(shown) => onToggle(step.id, shown)}
|
|
319
311
|
>
|
|
320
|
-
|
|
321
|
-
|
|
312
|
+
{#snippet child({ props })}
|
|
313
|
+
<Button
|
|
314
|
+
{...props}
|
|
315
|
+
variant="ghost"
|
|
316
|
+
class="w-full justify-start gap-2.5 px-2 text-left"
|
|
317
|
+
>
|
|
318
|
+
<span class="flex size-4 shrink-0 items-center justify-center">
|
|
319
|
+
{#if step.hidden}
|
|
320
|
+
<EyeSlash aria-hidden="true" class="size-3.5 text-muted-foreground" />
|
|
321
|
+
{:else}
|
|
322
|
+
<Eye aria-hidden="true" class="size-3.5" />
|
|
323
|
+
{/if}
|
|
324
|
+
</span>
|
|
325
|
+
<span
|
|
326
|
+
class={cn(
|
|
327
|
+
"min-w-0 flex-1 truncate",
|
|
328
|
+
step.hidden && "text-muted-foreground line-through",
|
|
329
|
+
)}>{step.label}</span
|
|
330
|
+
>
|
|
331
|
+
</Button>
|
|
332
|
+
{/snippet}
|
|
333
|
+
</MenuPrimitive.CheckboxItem>
|
|
334
|
+
{/each}
|
|
335
|
+
</DropdownMenu.Group>
|
|
322
336
|
{/each}
|
|
323
|
-
<
|
|
337
|
+
<div
|
|
324
338
|
class="mt-1 border-t border-border px-2 pt-2 pb-1 text-xs tabular-nums text-muted-foreground"
|
|
325
339
|
>
|
|
326
340
|
{t.shownCount(visible.length, ordered.length)}
|
|
327
|
-
</
|
|
328
|
-
</
|
|
329
|
-
</
|
|
341
|
+
</div>
|
|
342
|
+
</DropdownMenu.Content>
|
|
343
|
+
</DropdownMenu.Root>
|
|
330
344
|
{/if}
|
|
331
345
|
</div>
|
|
332
346
|
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import type { Tone } from "../lib/tone.js";
|
|
10
10
|
import { gutterClass } from "./gutter.js";
|
|
11
11
|
import { formatAge } from "./format.js";
|
|
12
|
+
import { measureClamp } from "./measure-clamp.js";
|
|
12
13
|
import { resolveLabels, type RecordLabels } from "./types.js";
|
|
13
14
|
|
|
14
15
|
// =========================
|
|
@@ -35,7 +36,6 @@
|
|
|
35
36
|
// =========================
|
|
36
37
|
let expanded = $state(false);
|
|
37
38
|
let clamped = $state(false);
|
|
38
|
-
let text = $state<HTMLElement | null>(null);
|
|
39
39
|
|
|
40
40
|
// =========================
|
|
41
41
|
// DERIVED
|
|
@@ -43,23 +43,6 @@
|
|
|
43
43
|
let t = $derived(resolveLabels(labels));
|
|
44
44
|
let age = $derived(at ? formatAge(at, now, locale) : null);
|
|
45
45
|
let hasMeta = $derived(Boolean(health || actor || age));
|
|
46
|
-
|
|
47
|
-
// =========================
|
|
48
|
-
// EFFECTS
|
|
49
|
-
// =========================
|
|
50
|
-
// Measured, not guessed from length: a note that fits two lines at 1280px
|
|
51
|
-
// overflows at 390px, and "More" shows only when text is cut.
|
|
52
|
-
$effect(() => {
|
|
53
|
-
if (!text) return;
|
|
54
|
-
const el = text;
|
|
55
|
-
const measure = () => {
|
|
56
|
-
if (!expanded) clamped = el.scrollHeight > el.clientHeight + 1;
|
|
57
|
-
};
|
|
58
|
-
measure();
|
|
59
|
-
const observer = new ResizeObserver(measure);
|
|
60
|
-
observer.observe(el);
|
|
61
|
-
return () => observer.disconnect();
|
|
62
|
-
});
|
|
63
46
|
</script>
|
|
64
47
|
|
|
65
48
|
<!-- =========================== -->
|
|
@@ -83,7 +66,10 @@
|
|
|
83
66
|
<!-- No `title` attribute: a native tooltip would repeat the whole note
|
|
84
67
|
over the steps list. "More" opens it in place. -->
|
|
85
68
|
<p
|
|
86
|
-
|
|
69
|
+
{@attach measureClamp(
|
|
70
|
+
() => expanded,
|
|
71
|
+
(cut) => (clamped = cut),
|
|
72
|
+
)}
|
|
87
73
|
class={cn("text-sm leading-snug text-muted-foreground", !expanded && "line-clamp-2")}
|
|
88
74
|
>
|
|
89
75
|
<span class="font-medium text-foreground">{t.whereWeAre}</span>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Separator } from "../separator/index.js";
|
|
3
|
+
import { cn } from "../../lib/utils.js";
|
|
4
|
+
import type { ComponentProps } from "svelte";
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
ref = $bindable(null),
|
|
8
|
+
class: className,
|
|
9
|
+
orientation = "vertical",
|
|
10
|
+
...restProps
|
|
11
|
+
}: ComponentProps<typeof Separator> = $props();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<Separator
|
|
15
|
+
bind:ref
|
|
16
|
+
data-slot="button-group-separator"
|
|
17
|
+
{orientation}
|
|
18
|
+
class={cn(
|
|
19
|
+
"bg-input relative self-stretch data-horizontal:mx-px data-horizontal:w-auto data-vertical:my-px data-vertical:h-auto",
|
|
20
|
+
className
|
|
21
|
+
)}
|
|
22
|
+
{...restProps}
|
|
23
|
+
/>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare const $$Component: import("svelte").Component<Omit<{
|
|
2
|
+
orientation?: import("bits-ui").Orientation;
|
|
3
|
+
decorative?: boolean;
|
|
4
|
+
}, "children" | "child"> & {
|
|
5
|
+
child?: import("svelte").Snippet<[{
|
|
6
|
+
props: Record<string, unknown>;
|
|
7
|
+
}]> | undefined;
|
|
8
|
+
children?: import("svelte").Snippet<[]> | undefined;
|
|
9
|
+
style?: import("bits-ui").StyleProperties | string | null | undefined;
|
|
10
|
+
ref?: HTMLElement | null | undefined;
|
|
11
|
+
} & import("bits-ui").Without<import("bits-ui").BitsPrimitiveDivAttributes, import("bits-ui").SeparatorRootPropsWithoutHTML>, {}, "ref">;
|
|
12
|
+
type $$Component = ReturnType<typeof $$Component>;
|
|
13
|
+
export default $$Component;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn, type WithElementRef } from "../../lib/utils.js";
|
|
3
|
+
import type { Snippet } from "svelte";
|
|
4
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
ref = $bindable(null),
|
|
8
|
+
class: className,
|
|
9
|
+
child,
|
|
10
|
+
...restProps
|
|
11
|
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
|
12
|
+
child?: Snippet<[{ props: Record<string, unknown> }]>;
|
|
13
|
+
} = $props();
|
|
14
|
+
|
|
15
|
+
const mergedProps = $derived({
|
|
16
|
+
...restProps,
|
|
17
|
+
class: cn("bg-muted gap-2 rounded-md border px-2.5 text-sm font-medium shadow-xs [&_svg:not([class*='size-'])]:size-4 flex items-center [&_svg]:pointer-events-none", className),
|
|
18
|
+
"data-slot": "button-group-text",
|
|
19
|
+
});
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
{#if child}
|
|
23
|
+
{@render child({ props: mergedProps })}
|
|
24
|
+
{:else}
|
|
25
|
+
<div bind:this={ref} {...mergedProps}>
|
|
26
|
+
{@render mergedProps.children?.()}
|
|
27
|
+
</div>
|
|
28
|
+
{/if}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type WithElementRef } from "../../lib/utils.js";
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
+
type $$ComponentProps = WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
|
5
|
+
child?: Snippet<[{
|
|
6
|
+
props: Record<string, unknown>;
|
|
7
|
+
}]>;
|
|
8
|
+
};
|
|
9
|
+
declare const $$Component: import("svelte").Component<$$ComponentProps, {}, "ref">;
|
|
10
|
+
type $$Component = ReturnType<typeof $$Component>;
|
|
11
|
+
export default $$Component;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import { tv, type VariantProps } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
export const buttonGroupVariants = tv({
|
|
5
|
+
base: "has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md group/button-group flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
|
|
6
|
+
variants: {
|
|
7
|
+
orientation: {
|
|
8
|
+
horizontal:
|
|
9
|
+
"[&>[data-slot]:not(:has(~[data-slot]))]:rounded-r-md! [&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
|
|
10
|
+
vertical:
|
|
11
|
+
"[&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-md! flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
defaultVariants: {
|
|
15
|
+
orientation: "horizontal",
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export type ButtonGroupOrientation = VariantProps<typeof buttonGroupVariants>["orientation"];
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<script lang="ts">
|
|
23
|
+
import { cn, type WithElementRef } from "../../lib/utils.js";
|
|
24
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
25
|
+
|
|
26
|
+
let {
|
|
27
|
+
ref = $bindable(null),
|
|
28
|
+
class: className,
|
|
29
|
+
children,
|
|
30
|
+
orientation = "horizontal",
|
|
31
|
+
...restProps
|
|
32
|
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
|
33
|
+
orientation?: ButtonGroupOrientation;
|
|
34
|
+
} = $props();
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<div
|
|
38
|
+
bind:this={ref}
|
|
39
|
+
role="group"
|
|
40
|
+
data-slot="button-group"
|
|
41
|
+
data-orientation={orientation}
|
|
42
|
+
class={cn(buttonGroupVariants({ orientation }), className)}
|
|
43
|
+
{...restProps}
|
|
44
|
+
>
|
|
45
|
+
{@render children?.()}
|
|
46
|
+
</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type VariantProps } from "tailwind-variants";
|
|
2
|
+
export declare const buttonGroupVariants: import("tailwind-variants").TVReturnType<{
|
|
3
|
+
orientation: {
|
|
4
|
+
horizontal: string;
|
|
5
|
+
vertical: string;
|
|
6
|
+
};
|
|
7
|
+
}, undefined, "has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md group/button-group flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1", undefined, undefined, undefined>;
|
|
8
|
+
export type ButtonGroupOrientation = VariantProps<typeof buttonGroupVariants>["orientation"];
|
|
9
|
+
import { type WithElementRef } from "../../lib/utils.js";
|
|
10
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
11
|
+
type $$ComponentProps = WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
|
12
|
+
orientation?: ButtonGroupOrientation;
|
|
13
|
+
};
|
|
14
|
+
declare const $$Component: import("svelte").Component<$$ComponentProps, {}, "ref">;
|
|
15
|
+
type $$Component = ReturnType<typeof $$Component>;
|
|
16
|
+
export default $$Component;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import Separator from "./button-group-separator.svelte";
|
|
2
|
+
import Text from "./button-group-text.svelte";
|
|
3
|
+
import Root, { buttonGroupVariants, type ButtonGroupOrientation } from "./button-group.svelte";
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
Root,
|
|
7
|
+
Text,
|
|
8
|
+
Separator,
|
|
9
|
+
buttonGroupVariants,
|
|
10
|
+
type ButtonGroupOrientation,
|
|
11
|
+
//
|
|
12
|
+
Root as ButtonGroup,
|
|
13
|
+
Text as ButtonGroupText,
|
|
14
|
+
Separator as ButtonGroupSeparator,
|
|
15
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// The checkbox's square, shared with rows that draw it as a picture inside a menu item,
|
|
2
|
+
// where a real checkbox would put a button inside a button.
|
|
3
|
+
export const checkboxBoxClass =
|
|
4
|
+
"border-input dark:bg-input/30 data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary data-checked:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 not-data-checked:enabled:hover:border-foreground/30 focus-visible:border-ring focus-visible:shadow-(--ring-focus) aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-sm border shadow-btn transition-[background-color,border-color,box-shadow] duration-[var(--duration-quick)] ease-[var(--ease-smooth-out)] group-has-disabled/field:opacity-50 aria-invalid:ring-3 peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 any-pointer-coarse:after:-inset-[15px] disabled:cursor-not-allowed disabled:opacity-50";
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { Checkbox as CheckboxPrimitive } from "bits-ui";
|
|
3
3
|
import { cn, type WithoutChildrenOrChild } from "../../lib/utils.js";
|
|
4
4
|
import { Check, Minus } from "phosphor-svelte";
|
|
5
|
+
import { checkboxBoxClass } from "./checkbox-box.js";
|
|
5
6
|
|
|
6
7
|
let {
|
|
7
8
|
ref = $bindable(null),
|
|
@@ -15,10 +16,7 @@
|
|
|
15
16
|
<CheckboxPrimitive.Root
|
|
16
17
|
bind:ref
|
|
17
18
|
data-slot="checkbox"
|
|
18
|
-
class={cn(
|
|
19
|
-
"border-input dark:bg-input/30 data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary data-checked:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 not-data-checked:enabled:hover:border-foreground/30 focus-visible:border-ring focus-visible:shadow-(--ring-focus) aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-sm border shadow-btn transition-[background-color,border-color,box-shadow] duration-[var(--duration-quick)] ease-[var(--ease-smooth-out)] group-has-disabled/field:opacity-50 aria-invalid:ring-3 peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 any-pointer-coarse:after:-inset-[15px] disabled:cursor-not-allowed disabled:opacity-50",
|
|
20
|
-
className,
|
|
21
|
-
)}
|
|
19
|
+
class={cn(checkboxBoxClass, className)}
|
|
22
20
|
bind:checked
|
|
23
21
|
bind:indeterminate
|
|
24
22
|
{...restProps}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Drawer as DrawerPrimitive } from "vaul-svelte";
|
|
3
|
+
import { cn } from "../../lib/utils.js";
|
|
4
|
+
import type { WithoutChildrenOrChild } from "../../lib/utils.js";
|
|
5
|
+
import DrawerOverlay from "./drawer-overlay.svelte";
|
|
6
|
+
import DrawerPortal from "./drawer-portal.svelte";
|
|
7
|
+
import type { ComponentProps } from "svelte";
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
ref = $bindable(null),
|
|
11
|
+
class: className,
|
|
12
|
+
portalProps,
|
|
13
|
+
children,
|
|
14
|
+
...restProps
|
|
15
|
+
}: DrawerPrimitive.ContentProps & {
|
|
16
|
+
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof DrawerPortal>>;
|
|
17
|
+
} = $props();
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<DrawerPortal {...portalProps}>
|
|
21
|
+
<DrawerOverlay />
|
|
22
|
+
<DrawerPrimitive.Content
|
|
23
|
+
bind:ref
|
|
24
|
+
data-slot="drawer-content"
|
|
25
|
+
class={cn(
|
|
26
|
+
"bg-popover text-popover-foreground flex h-auto flex-col text-sm data-[vaul-drawer-direction=bottom]:rounded-t-xl data-[vaul-drawer-direction=bottom]:border-t data-[vaul-drawer-direction=left]:rounded-r-xl data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=right]:rounded-l-xl data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=top]:rounded-b-xl data-[vaul-drawer-direction=top]:border-b group/drawer-content fixed z-50 data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:start-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:end-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=left]:sm:max-w-sm data-[vaul-drawer-direction=right]:sm:max-w-sm",
|
|
27
|
+
className
|
|
28
|
+
)}
|
|
29
|
+
{...restProps}
|
|
30
|
+
>
|
|
31
|
+
<div
|
|
32
|
+
class="bg-muted mx-auto mt-4 hidden h-1.5 w-[100px] shrink-0 rounded-full mx-auto hidden shrink-0 group-data-[vaul-drawer-direction=bottom]/drawer-content:block"
|
|
33
|
+
></div>
|
|
34
|
+
{@render children?.()}
|
|
35
|
+
</DrawerPrimitive.Content>
|
|
36
|
+
</DrawerPortal>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Drawer as DrawerPrimitive } from "vaul-svelte";
|
|
2
|
+
import type { WithoutChildrenOrChild } from "../../lib/utils.js";
|
|
3
|
+
import DrawerPortal from "./drawer-portal.svelte";
|
|
4
|
+
import type { ComponentProps } from "svelte";
|
|
5
|
+
type $$ComponentProps = DrawerPrimitive.ContentProps & {
|
|
6
|
+
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof DrawerPortal>>;
|
|
7
|
+
};
|
|
8
|
+
declare const $$Component: import("svelte").Component<$$ComponentProps, {}, "ref">;
|
|
9
|
+
type $$Component = ReturnType<typeof $$Component>;
|
|
10
|
+
export default $$Component;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Drawer as DrawerPrimitive } from "vaul-svelte";
|
|
3
|
+
import { cn } from "../../lib/utils.js";
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
...restProps
|
|
9
|
+
}: DrawerPrimitive.DescriptionProps = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<DrawerPrimitive.Description
|
|
13
|
+
bind:ref
|
|
14
|
+
data-slot="drawer-description"
|
|
15
|
+
class={cn("text-muted-foreground text-sm", className)}
|
|
16
|
+
{...restProps}
|
|
17
|
+
/>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn, type WithElementRef } from "../../lib/utils.js";
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
children,
|
|
9
|
+
...restProps
|
|
10
|
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<div
|
|
14
|
+
bind:this={ref}
|
|
15
|
+
data-slot="drawer-footer"
|
|
16
|
+
class={cn("gap-2 p-4 mt-auto flex flex-col", className)}
|
|
17
|
+
{...restProps}
|
|
18
|
+
>
|
|
19
|
+
{@render children?.()}
|
|
20
|
+
</div>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type WithElementRef } from "../../lib/utils.js";
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
declare const $$Component: import("svelte").Component<WithElementRef<HTMLAttributes<HTMLDivElement>>, {}, "ref">;
|
|
4
|
+
type $$Component = ReturnType<typeof $$Component>;
|
|
5
|
+
export default $$Component;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn, type WithElementRef } from "../../lib/utils.js";
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
children,
|
|
9
|
+
...restProps
|
|
10
|
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<div
|
|
14
|
+
bind:this={ref}
|
|
15
|
+
data-slot="drawer-header"
|
|
16
|
+
class={cn(
|
|
17
|
+
"gap-0.5 p-4 md:gap-1.5 md:text-left flex flex-col group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center",
|
|
18
|
+
className
|
|
19
|
+
)}
|
|
20
|
+
{...restProps}
|
|
21
|
+
>
|
|
22
|
+
{@render children?.()}
|
|
23
|
+
</div>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type WithElementRef } from "../../lib/utils.js";
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
declare const $$Component: import("svelte").Component<WithElementRef<HTMLAttributes<HTMLDivElement>>, {}, "ref">;
|
|
4
|
+
type $$Component = ReturnType<typeof $$Component>;
|
|
5
|
+
export default $$Component;
|