@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.
- package/package.json +7 -8
- package/scripts/sync-shadcn.mjs +3 -4
- package/src/agents/agent-avatar.svelte +604 -575
- package/src/agents/agent-cast.svelte +179 -183
- package/src/agents/demo.svelte +125 -113
- package/src/agents/helpers.ts +23 -17
- package/src/agents/index.ts +4 -4
- package/src/agents/page-state.ts +6 -6
- package/src/agents/types.ts +6 -6
- package/src/ai/ai-button/AiButton.svelte +4 -12
- package/src/ai/generation-progress/GenerationProgress.svelte +10 -3
- package/src/ai/prompt-input/PromptInputTextarea.svelte +1 -2
- package/src/ai/response/Response.css +2 -3
- package/src/animations/avatar-group-hover.css +2 -16
- package/src/animations/card-tilt.css +3 -6
- package/src/animations/digit-pop-in.css +2 -15
- package/src/animations/dropdown.css +4 -17
- package/src/animations/input-clear-dissolve.css +5 -18
- package/src/animations/input-shake.css +9 -41
- package/src/animations/learn-more-hover.css +17 -9
- package/src/animations/like-button.css +2 -4
- package/src/animations/page-side-by-side.css +2 -10
- package/src/animations/plus-menu-morph.css +2 -5
- package/src/animations/shimmer-text.css +5 -18
- package/src/animations/spinning-counter.css +2 -6
- package/src/animations/success-check.css +2 -15
- package/src/animations/thinking-states.css +2 -7
- package/src/brand/brand.test.ts +21 -5
- package/src/brand/index.ts +4 -10
- package/src/canvas/card/card-frame.svelte +43 -39
- package/src/canvas/card/resize-handles.svelte +89 -80
- package/src/canvas/chrome/chrome-zoom.svelte +101 -100
- package/src/canvas/chrome/lock-badge.svelte +8 -8
- package/src/canvas/chrome/side-handles.svelte +24 -19
- package/src/canvas/chrome/size-chip.svelte +30 -30
- package/src/canvas/chrome/snap-guides.svelte +20 -20
- package/src/canvas/components/icons/ToolIcon.svelte +8 -8
- package/src/canvas/components/shared/svg/PreviewSvg.svelte +19 -19
- package/src/canvas/components/shared/svg/ShapeOutline.svelte +71 -48
- package/src/canvas/components/shared/svg/StrokeNode.svelte +21 -27
- package/src/canvas/components/shared/svg/TextRule.svelte +25 -17
- package/src/canvas/edges/bend-handle.svelte +46 -46
- package/src/canvas/edges/edge-gradient.svelte +10 -10
- package/src/canvas/edges/gradient-edge.svelte +45 -29
- package/src/canvas/editor/lock.test.ts +6 -1
- package/src/canvas/editor/style.ts +7 -1
- package/src/canvas/headless/svg-figure.test.ts +5 -1
- package/src/canvas/lod/lod-switch.svelte +111 -106
- package/src/canvas/pen/PenField.svelte +87 -81
- package/src/canvas/pen/PenOverlay.svelte +127 -127
- package/src/canvas/pen/ShapeNode.svelte +31 -32
- package/src/canvas/pen/TextNode.svelte +54 -53
- package/src/canvas/pen/host-field.test.svelte +7 -7
- package/src/canvas/pen/shapes.ts +7 -1
- package/src/canvas/screen/GlyphIcon.svelte +22 -17
- package/src/canvas/screen/PartView.svelte +138 -72
- package/src/canvas/screen/ScreenBody.svelte +81 -60
- package/src/canvas/screen/ScreenCard.svelte +20 -20
- package/src/canvas/ui/CanvasToolbar.svelte +173 -85
- package/src/canvas/ui/FrameLayer.svelte +59 -59
- package/src/canvas/ui/PenLayer.svelte +39 -30
- package/src/canvas/ui/StylePanel.svelte +119 -102
- package/src/canvas/ui/canvas-grid.svelte +137 -129
- package/src/charts/animated-value.svelte +1 -1
- package/src/charts/area-chart.css +2 -5
- package/src/charts/area-chart.svelte +1 -1
- package/src/charts/bar-chart.css +2 -3
- package/src/charts/bar-chart.svelte +1 -1
- package/src/charts/charts.css +5 -17
- package/src/charts/crosshair.svelte +1 -1
- package/src/charts/dashboard/dashboard-empty.svelte +25 -25
- package/src/charts/dashboard/dashboard-section.svelte +24 -24
- package/src/charts/dashboard/data-panel.svelte +50 -50
- package/src/charts/dashboard/data-sort-head.svelte +56 -56
- package/src/charts/dashboard/data-table.svelte +138 -138
- package/src/charts/dashboard/panel-grid.svelte +30 -30
- package/src/charts/dashboard/period-filter.svelte +25 -25
- package/src/charts/dashboard/rating-chip.svelte +19 -19
- package/src/charts/dashboard/stat-band.svelte +32 -32
- package/src/charts/dashboard/stat-tile.svelte +106 -99
- package/src/charts/donut-chart.svelte +1 -1
- package/src/charts/edge-fade.svelte +1 -1
- package/src/charts/figure.svelte +1 -1
- package/src/charts/gauge-chart.css +4 -7
- package/src/charts/gauge-chart.svelte +1 -1
- package/src/charts/hover-focus.svelte +1 -1
- package/src/charts/legend.css +1 -3
- package/src/charts/legend.svelte +1 -1
- package/src/charts/line-chart.svelte +1 -1
- package/src/charts/number-chart.css +6 -9
- package/src/charts/number-chart.svelte +1 -1
- package/src/charts/reference-line.svelte +19 -19
- package/src/charts/reveal.svelte +1 -1
- package/src/charts/ring-chart.css +2 -4
- package/src/charts/ring-chart.svelte +1 -1
- package/src/charts/sparkline.svelte +5 -2
- package/src/charts/stat-card.svelte +1 -1
- package/src/charts/time-series-chart.css +2 -5
- package/src/charts/trend-pill.css +2 -4
- package/src/charts/trend-pill.svelte +1 -1
- package/src/components/copy/copy-button.svelte +93 -98
- package/src/components/copy/copy-button.test.ts +10 -2
- package/src/components/data-table/infinite-scroll.svelte +42 -42
- package/src/components/data-table/pagination.svelte +34 -22
- package/src/components/data-table/row-arrow.svelte +19 -16
- package/src/components/data-table/row-context-menu.svelte +52 -52
- package/src/components/data-table/sortable-head.svelte +25 -25
- package/src/components/data-table/table-skeleton.svelte +41 -36
- package/src/components/docs/doc-page.svelte +18 -9
- package/src/components/docs/on-this-page.svelte +16 -3
- package/src/components/docs/scroll-spy.svelte.ts +2 -3
- package/src/components/field-row/field-row.svelte +10 -8
- package/src/components/hold-to-confirm/hold-to-confirm.svelte +5 -1
- package/src/components/icon/icon.svelte +14 -14
- package/src/components/language-flag/language-flag.svelte +3 -1
- package/src/components/list-page/detail-empty.svelte +34 -34
- package/src/components/list-page/detail-header.svelte +55 -47
- package/src/components/list-page/detail-panel.svelte +51 -59
- package/src/components/list-page/detail-row.svelte +19 -19
- package/src/components/list-page/detail-stack.svelte +21 -21
- package/src/components/list-page/empty-state.svelte +30 -30
- package/src/components/list-page/filter-item.svelte +20 -20
- package/src/components/list-page/filter-popover.svelte +60 -55
- package/src/components/list-page/grouped-list.svelte +4 -2
- package/src/components/list-page/index.ts +5 -1
- package/src/components/list-page/list-page-shell.svelte +2 -5
- package/src/components/list-page/master-detail.svelte +87 -88
- package/src/components/list-page/notice-bar.svelte +38 -38
- package/src/components/list-page/prev-next.svelte +63 -63
- package/src/components/list-page/rail-body.svelte +18 -18
- package/src/components/list-page/rail-empty.svelte +23 -30
- package/src/components/list-page/rail-head.svelte +24 -24
- package/src/components/list-page/rail-row.svelte +77 -73
- package/src/components/list-page/section-host.ts +2 -3
- package/src/components/locale-switch/locale-switch.svelte +41 -41
- package/src/components/mark/mark.svelte +34 -38
- package/src/components/open-in/index.ts +1 -5
- package/src/components/open-in/open-in.svelte +40 -40
- package/src/components/picker/mark-picker.svelte +49 -49
- package/src/components/picker/picker.svelte +5 -3
- package/src/components/section-header/section-header.test.ts +7 -1
- package/src/components/section-header/section-label.svelte +20 -20
- package/src/components/segmented/animated-tabs.svelte +31 -2
- package/src/components/segmented/collapse.test.ts +2 -1
- package/src/components/segmented/index.ts +2 -0
- package/src/components/segmented/segment.svelte +52 -49
- package/src/components/segmented/segmented-filter.svelte +79 -80
- package/src/components/segmented/segmented-nav.svelte +34 -40
- package/src/components/segmented/segmented-overflow.svelte +53 -50
- package/src/components/segmented/segmented-track.svelte +62 -46
- package/src/components/segmented/segmented.ts +2 -3
- package/src/components/star-rating-input/star-rating-input.svelte +103 -103
- package/src/components/svg/svg.svelte +4 -4
- package/src/components/table-view/table-view.svelte +17 -2
- package/src/components/table-view/table-view.test.ts +7 -1
- package/src/components/table-view/types.ts +11 -11
- package/src/components/tags-input/index.ts +13 -0
- package/src/components/tags-input/tags-input.svelte +305 -0
- package/src/components/tags-input/tags.test.ts +64 -0
- package/src/components/tags-input/tags.ts +142 -0
- package/src/components/theme/index.ts +2 -4
- package/src/components/theme/theme-provider.svelte +1 -3
- package/src/components/toolbar/toolbar-search.svelte +25 -25
- package/src/components/toolbar/toolbar.svelte +11 -7
- package/src/components/toolbar/toolbar.test.ts +10 -1
- package/src/design/index.css +21 -78
- package/src/design/polish.css +26 -35
- package/src/editor/editor-toolbar.svelte +104 -99
- package/src/editor/editor.svelte +296 -266
- package/src/editor/image-toolbar.svelte +20 -22
- package/src/editor/index.ts +1 -4
- package/src/editor/inline-editor.svelte +280 -238
- package/src/editor/markdown.ts +15 -15
- package/src/editor/renderer.svelte +71 -71
- package/src/editor/slash-menu.svelte +24 -27
- package/src/effects/animated-beam/diagrams/BeamSvg.svelte +1 -1
- package/src/effects/image-comparison/ImageComparison.svelte +11 -1
- package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +59 -46
- package/src/effects/magic-card/MagicCard.css +14 -7
- package/src/effects/marquee/Marquee.svelte +3 -5
- package/src/effects/reveal/observe.ts +0 -3
- package/src/effects/spotlight/Spotlight.svelte +1 -1
- package/src/effects/theme-toggle/ThemeToggle.css +25 -22
- package/src/effects/theme-toggle/ThemeToggle.svelte +6 -7
- package/src/gallery.test.ts +14 -4
- package/src/inbox/README.md +1 -3
- package/src/inbox/inbox.test.ts +181 -138
- package/src/inbox/index.ts +20 -20
- package/src/inbox/logic.ts +114 -111
- package/src/inbox/thread-inbox.svelte +227 -151
- package/src/inbox/types.ts +130 -108
- package/src/lib/theme-transition.ts +2 -4
- package/src/lib/tone.ts +2 -4
- package/src/lib/utils.ts +2 -2
- package/src/modules.test.ts +79 -69
- package/src/onboarding/define-tours.test.ts +55 -40
- package/src/onboarding/define-tours.ts +23 -23
- package/src/onboarding/demo.svelte +24 -5
- package/src/onboarding/index.ts +1 -8
- package/src/onboarding/onboarding-provider.svelte +19 -7
- package/src/onboarding/onboarding.svelte.ts +16 -16
- package/src/onboarding/pick.test.ts +61 -52
- package/src/onboarding/pick.ts +16 -13
- package/src/onboarding/stores.test.ts +80 -80
- package/src/onboarding/stores.ts +41 -39
- package/src/onboarding/tour-card.svelte +30 -5
- package/src/onboarding/tour-runner.svelte +12 -3
- package/src/onboarding/types.ts +20 -12
- package/src/onboarding/wait.ts +22 -22
- package/src/panel/side-panel.svelte +94 -93
- package/src/record/demo-data.ts +291 -225
- package/src/record/field-section.svelte +38 -34
- package/src/record/fields.ts +148 -96
- package/src/record/format.ts +63 -56
- package/src/record/index.ts +49 -35
- package/src/record/info-list.svelte +145 -114
- package/src/record/kinds.ts +31 -31
- package/src/record/logic.ts +216 -214
- package/src/record/next-up.svelte +45 -34
- package/src/record/project-list.svelte +56 -50
- package/src/record/record-demo.svelte +130 -110
- package/src/record/record-header.svelte +37 -28
- package/src/record/record-shell.svelte +54 -54
- package/src/record/record-stats.svelte +25 -25
- package/src/record/record-timeline.svelte +134 -114
- package/src/record/record.test.ts +430 -309
- package/src/record/steps-rail.svelte +225 -216
- package/src/record/types.ts +234 -215
- package/src/record/where-we-are.svelte +62 -58
- package/src/shadcn/button/button.svelte +1 -1
- package/src/shadcn/card/card-title.svelte +1 -5
- package/src/shadcn/hooks/use-highlighted-code.svelte.ts +2 -13
- package/src/shadcn/sheet/sheet-content.svelte +2 -4
- package/src/shadcn/table/table-cell.svelte +2 -3
- package/src/shadcn/utilities.css +3 -8
- package/src/slides/Controls.svelte +150 -124
- package/src/slides/Deck.svelte +243 -238
- package/src/slides/Fragment.svelte +64 -57
- package/src/slides/Overview.svelte +106 -101
- package/src/slides/Presenter.svelte +300 -266
- package/src/slides/Slide.svelte +185 -170
- package/src/slides/SlideList.svelte +16 -12
- package/src/slides/ambient.d.ts +1 -1
- package/src/slides/bridges.ts +42 -23
- package/src/slides/deck-controller.svelte.ts +47 -35
- package/src/slides/demo-slides.svelte +330 -306
- package/src/slides/demo.svelte +164 -160
- package/src/slides/export/capture.ts +20 -16
- package/src/slides/export/ffmpeg.ts +43 -38
- package/src/slides/export/index.ts +5 -5
- package/src/slides/export/launch.ts +3 -1
- package/src/slides/export/pdf.ts +30 -27
- package/src/slides/export/types.ts +10 -8
- package/src/slides/index.ts +11 -11
- package/src/slides/labels.ts +22 -19
- package/src/slides/layout.ts +9 -2
- package/src/slides/model.ts +4 -4
- package/src/slides/navigation.ts +43 -31
- package/src/slides/theme.css +5 -7
- package/src/slides/types.ts +9 -10
- package/src/status/define-statuses.ts +17 -24
- package/src/status/index.ts +5 -5
- package/src/status/status-badge.svelte +3 -1
- package/src/status/status-dot.svelte +1 -3
- package/src/status/status-icon.svelte +1 -1
- package/src/status/status-types.ts +21 -21
- package/src/tasks/board-order.ts +2 -4
- package/src/tasks/demo.svelte +189 -31
- package/src/tasks/detail/detail-demo.svelte +73 -13
- package/src/tasks/detail/detail-types.ts +45 -45
- package/src/tasks/detail/task-detail.svelte +40 -10
- package/src/tasks/detail/task-property.svelte +8 -2
- package/src/tasks/detail/task-thread.svelte +53 -12
- package/src/tasks/gantt/gantt-bar.svelte +17 -6
- package/src/tasks/gantt/gantt-grid.svelte +40 -9
- package/src/tasks/gantt/gantt-group-row.svelte +8 -2
- package/src/tasks/gantt/gantt-header.svelte +9 -3
- package/src/tasks/gantt/gantt-task-row.svelte +26 -6
- package/src/tasks/gantt/gantt.css +2 -1
- package/src/tasks/gantt/gantt.test.ts +3 -1
- package/src/tasks/gantt/logic.test.ts +110 -20
- package/src/tasks/gantt/logic.ts +42 -6
- package/src/tasks/inbox/inbox-card.svelte +13 -5
- package/src/tasks/inbox/inbox-draft.svelte +1 -1
- package/src/tasks/inbox/inbox-logic.ts +6 -40
- package/src/tasks/inbox/inbox-statuses.ts +23 -23
- package/src/tasks/inbox/inbox-trace.svelte +9 -3
- package/src/tasks/inbox/inbox-types.ts +54 -58
- package/src/tasks/inbox/index.ts +22 -21
- package/src/tasks/index.ts +49 -52
- package/src/tasks/kanban-board.svelte +16 -12
- package/src/tasks/kanban-types.ts +2 -3
- package/src/tasks/presets/sales.ts +6 -6
- package/src/tasks/task-gantt.svelte +28 -8
- package/src/tasks/task-list.svelte +41 -17
- package/src/tasks/time/duration.ts +40 -40
- package/src/tasks/time/time-chip.svelte +9 -2
- package/src/tasks/time/time-dot.svelte +1 -1
- package/src/tasks/time/time-ring.svelte +11 -3
- package/src/tasks/time/time-tracker.svelte +57 -15
- package/src/tasks/time/time-types.ts +57 -57
- package/src/tasks/use-kanban-dnd.svelte.ts +2 -3
- package/src/thread/index.ts +7 -7
- package/src/thread/logic.ts +36 -33
- package/src/thread/thread.svelte +82 -16
- package/src/thread/thread.test.ts +58 -47
- package/src/thread/types.ts +68 -68
- package/src/tokens/craft.css +17 -53
- package/src/tokens/index.css +3 -13
- package/src/tokens/palette.css +13 -11
- package/src/tokens/primitives.css +10 -23
- package/src/tasks/inbox/inbox.svelte +0 -203
|
@@ -1,61 +1,61 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
// =========================
|
|
3
|
-
// IMPORTS
|
|
4
|
-
// =========================
|
|
5
|
-
import * as ContextMenu from "../../shadcn/context-menu/index.js";
|
|
6
|
-
import { HoldToConfirm } from "../hold-to-confirm/index.js";
|
|
7
|
-
import { ArrowUpRight, Copy, LinkSimple, Trash } from "phosphor-svelte";
|
|
8
|
-
import type { Snippet } from "svelte";
|
|
2
|
+
// =========================
|
|
3
|
+
// IMPORTS
|
|
4
|
+
// =========================
|
|
5
|
+
import * as ContextMenu from "../../shadcn/context-menu/index.js";
|
|
6
|
+
import { HoldToConfirm } from "../hold-to-confirm/index.js";
|
|
7
|
+
import { ArrowUpRight, Copy, LinkSimple, Trash } from "phosphor-svelte";
|
|
8
|
+
import type { Snippet } from "svelte";
|
|
9
9
|
|
|
10
|
-
// =========================
|
|
11
|
-
// TYPES
|
|
12
|
-
// =========================
|
|
13
|
-
interface Props {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
10
|
+
// =========================
|
|
11
|
+
// TYPES
|
|
12
|
+
// =========================
|
|
13
|
+
interface Props {
|
|
14
|
+
onDelete: () => void;
|
|
15
|
+
href?: string;
|
|
16
|
+
id?: string;
|
|
17
|
+
deleteLabel?: string;
|
|
18
|
+
copyLinkLabel?: string;
|
|
19
|
+
copyIdLabel?: string;
|
|
20
|
+
/** Called after a successful clipboard copy so consumers can show their own toast */
|
|
21
|
+
onCopied?: () => void;
|
|
22
|
+
children: Snippet<[Record<string, unknown>]>;
|
|
23
|
+
}
|
|
24
24
|
|
|
25
|
-
// =========================
|
|
26
|
-
// PROPS
|
|
27
|
-
// =========================
|
|
28
|
-
let {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}: Props = $props();
|
|
25
|
+
// =========================
|
|
26
|
+
// PROPS
|
|
27
|
+
// =========================
|
|
28
|
+
let {
|
|
29
|
+
onDelete,
|
|
30
|
+
href,
|
|
31
|
+
id,
|
|
32
|
+
deleteLabel = "Delete",
|
|
33
|
+
copyLinkLabel = "Copy link",
|
|
34
|
+
copyIdLabel = "Copy ID",
|
|
35
|
+
onCopied,
|
|
36
|
+
children,
|
|
37
|
+
}: Props = $props();
|
|
38
38
|
|
|
39
|
-
// =========================
|
|
40
|
-
// FUNCTIONS
|
|
41
|
-
// =========================
|
|
42
|
-
function handleOpen() {
|
|
43
|
-
|
|
44
|
-
}
|
|
39
|
+
// =========================
|
|
40
|
+
// FUNCTIONS
|
|
41
|
+
// =========================
|
|
42
|
+
function handleOpen() {
|
|
43
|
+
if (href) window.location.href = href;
|
|
44
|
+
}
|
|
45
45
|
|
|
46
|
-
// WHY the whole URL and not the path: what leaves this menu is pasted into a
|
|
47
|
-
// message, a doc or an agent prompt, none of which can resolve "/clients/42".
|
|
48
|
-
async function handleCopyLink() {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
46
|
+
// WHY the whole URL and not the path: what leaves this menu is pasted into a
|
|
47
|
+
// message, a doc or an agent prompt, none of which can resolve "/clients/42".
|
|
48
|
+
async function handleCopyLink() {
|
|
49
|
+
if (!href) return;
|
|
50
|
+
await navigator.clipboard.writeText(new URL(href, window.location.origin).href);
|
|
51
|
+
onCopied?.();
|
|
52
|
+
}
|
|
53
53
|
|
|
54
|
-
async function handleCopyId() {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
54
|
+
async function handleCopyId() {
|
|
55
|
+
if (!id) return;
|
|
56
|
+
await navigator.clipboard.writeText(id);
|
|
57
|
+
onCopied?.();
|
|
58
|
+
}
|
|
59
59
|
</script>
|
|
60
60
|
|
|
61
61
|
<!-- =========================== -->
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
<script lang="ts" generics="T">
|
|
2
|
-
import type { Snippet } from "svelte";
|
|
3
|
-
import { CaretDown, CaretUp, CaretUpDown } from "phosphor-svelte";
|
|
4
|
-
import { cn } from "../../lib/utils.js";
|
|
5
|
-
import type { SortDirection, SortState } from "./data-table.js";
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import { CaretDown, CaretUp, CaretUpDown } from "phosphor-svelte";
|
|
4
|
+
import { cn } from "../../lib/utils.js";
|
|
5
|
+
import type { SortDirection, SortState } from "./data-table.js";
|
|
6
6
|
|
|
7
|
-
// ========================= TYPES
|
|
8
|
-
interface Props {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
7
|
+
// ========================= TYPES
|
|
8
|
+
interface Props {
|
|
9
|
+
key: keyof T & string;
|
|
10
|
+
sort: SortState<T>;
|
|
11
|
+
onSort: (key: keyof T & string) => void;
|
|
12
|
+
class?: string;
|
|
13
|
+
children: Snippet;
|
|
14
|
+
}
|
|
15
15
|
|
|
16
|
-
// ========================= PROPS
|
|
17
|
-
let { key, sort, onSort, class: className, children }: Props = $props();
|
|
16
|
+
// ========================= PROPS
|
|
17
|
+
let { key, sort, onSort, class: className, children }: Props = $props();
|
|
18
18
|
|
|
19
|
-
// ========================= DERIVED
|
|
20
|
-
let active = $derived(sort?.key === key);
|
|
21
|
-
let direction = $derived<SortDirection | null>(sort && active ? sort.direction : null);
|
|
22
|
-
let ariaSort = $derived<"ascending" | "descending" | "none">(
|
|
23
|
-
|
|
24
|
-
);
|
|
19
|
+
// ========================= DERIVED
|
|
20
|
+
let active = $derived(sort?.key === key);
|
|
21
|
+
let direction = $derived<SortDirection | null>(sort && active ? sort.direction : null);
|
|
22
|
+
let ariaSort = $derived<"ascending" | "descending" | "none">(
|
|
23
|
+
direction === "asc" ? "ascending" : direction === "desc" ? "descending" : "none",
|
|
24
|
+
);
|
|
25
25
|
|
|
26
|
-
function handleKeydown(e: KeyboardEvent) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
function handleKeydown(e: KeyboardEvent) {
|
|
27
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
28
|
+
e.preventDefault();
|
|
29
|
+
onSort(key);
|
|
30
|
+
}
|
|
30
31
|
}
|
|
31
|
-
}
|
|
32
32
|
</script>
|
|
33
33
|
|
|
34
34
|
<th
|
|
@@ -1,43 +1,38 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
// ========================= IMPORTS
|
|
3
|
-
import { Skeleton } from "../../shadcn/skeleton/index.js";
|
|
2
|
+
// ========================= IMPORTS
|
|
3
|
+
import { Skeleton } from "../../shadcn/skeleton/index.js";
|
|
4
4
|
|
|
5
|
-
// ========================= TYPES
|
|
6
|
-
type ColumnDef = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
};
|
|
5
|
+
// ========================= TYPES
|
|
6
|
+
type ColumnDef = {
|
|
7
|
+
width?: string;
|
|
8
|
+
align?: "left" | "center" | "right";
|
|
9
|
+
/** Show a small circle before the skeleton bar (e.g. logo/avatar column) */
|
|
10
|
+
circle?: boolean;
|
|
11
|
+
};
|
|
12
12
|
|
|
13
|
-
interface Props {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
13
|
+
interface Props {
|
|
14
|
+
/** Number of skeleton rows to render */
|
|
15
|
+
rows?: number;
|
|
16
|
+
/** Column definitions control skeleton widths and alignment */
|
|
17
|
+
columns?: ColumnDef[];
|
|
18
|
+
/** Simple mode: just specify column count */
|
|
19
|
+
columnCount?: number;
|
|
20
|
+
class?: string;
|
|
21
|
+
}
|
|
22
22
|
|
|
23
|
-
// ========================= PROPS
|
|
24
|
-
let {
|
|
25
|
-
rows = 5,
|
|
26
|
-
columns,
|
|
27
|
-
columnCount = 6,
|
|
28
|
-
class: className,
|
|
29
|
-
}: Props = $props();
|
|
23
|
+
// ========================= PROPS
|
|
24
|
+
let { rows = 5, columns, columnCount = 6, class: className }: Props = $props();
|
|
30
25
|
|
|
31
|
-
// ========================= DERIVED
|
|
32
|
-
let cols = $derived(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
);
|
|
26
|
+
// ========================= DERIVED
|
|
27
|
+
let cols = $derived(
|
|
28
|
+
columns ??
|
|
29
|
+
Array.from<unknown, ColumnDef>({ length: columnCount }, () => ({
|
|
30
|
+
width: undefined,
|
|
31
|
+
align: "left" as const,
|
|
32
|
+
})),
|
|
33
|
+
);
|
|
39
34
|
|
|
40
|
-
const WIDTHS = ["w-24", "w-20", "w-28", "w-16", "w-32", "w-20"];
|
|
35
|
+
const WIDTHS = ["w-24", "w-20", "w-28", "w-16", "w-32", "w-20"];
|
|
41
36
|
</script>
|
|
42
37
|
|
|
43
38
|
<!-- =========================== -->
|
|
@@ -53,9 +48,19 @@ const WIDTHS = ["w-24", "w-20", "w-28", "w-16", "w-32", "w-20"];
|
|
|
53
48
|
{#each cols as col, colIdx (colIdx)}
|
|
54
49
|
<td
|
|
55
50
|
data-slot="table-cell"
|
|
56
|
-
class="h-11 px-2 {col.align === 'center'
|
|
51
|
+
class="h-11 px-2 {col.align === 'center'
|
|
52
|
+
? 'text-center'
|
|
53
|
+
: col.align === 'right'
|
|
54
|
+
? 'text-right'
|
|
55
|
+
: ''}"
|
|
57
56
|
>
|
|
58
|
-
<div
|
|
57
|
+
<div
|
|
58
|
+
class="flex items-center gap-2 {col.align === 'center'
|
|
59
|
+
? 'justify-center'
|
|
60
|
+
: col.align === 'right'
|
|
61
|
+
? 'justify-end'
|
|
62
|
+
: ''}"
|
|
63
|
+
>
|
|
59
64
|
{#if col.circle}
|
|
60
65
|
<Skeleton class="size-6 shrink-0 rounded-md" />
|
|
61
66
|
{/if}
|
|
@@ -81,17 +81,17 @@
|
|
|
81
81
|
<!-- =========================== -->
|
|
82
82
|
<!-- MARKUP -->
|
|
83
83
|
<!-- =========================== -->
|
|
84
|
-
<!-- The anatomy
|
|
85
|
-
|
|
86
|
-
arrive with different layouts. The pane is its own container, since the
|
|
87
|
-
room left after the map is what decides the rail, not the window. -->
|
|
84
|
+
<!-- The one anatomy every doc page shares; the pane is its own container, since
|
|
85
|
+
the room left after the map, not the window, decides the rail. -->
|
|
88
86
|
<div
|
|
89
87
|
bind:this={scroller}
|
|
90
88
|
class="doc-page @container/page thin-scrollbar relative min-h-0 flex-1 overflow-y-auto"
|
|
91
89
|
>
|
|
92
90
|
{#if hasRail}
|
|
93
91
|
<!-- Below the rail's width the contents sit on a strip that stays put. -->
|
|
94
|
-
<div
|
|
92
|
+
<div
|
|
93
|
+
class="sticky top-0 z-20 border-b border-border bg-background/95 backdrop-blur @3xl/page:hidden"
|
|
94
|
+
>
|
|
95
95
|
<OnThisPage
|
|
96
96
|
variant="bar"
|
|
97
97
|
items={headings}
|
|
@@ -124,14 +124,21 @@
|
|
|
124
124
|
{title}
|
|
125
125
|
</h1>
|
|
126
126
|
{#if summary}
|
|
127
|
-
<p
|
|
127
|
+
<p
|
|
128
|
+
class="mt-1.5 max-w-[60ch] text-[15px] leading-relaxed text-muted-foreground text-pretty"
|
|
129
|
+
>
|
|
128
130
|
{summary}
|
|
129
131
|
</p>
|
|
130
132
|
{/if}
|
|
131
133
|
{#if meta.length > 0}
|
|
132
|
-
<p
|
|
134
|
+
<p
|
|
135
|
+
class="mt-3 flex flex-wrap items-center gap-x-2 text-xs tabular-nums text-muted-foreground"
|
|
136
|
+
>
|
|
133
137
|
{#each meta as item, i (item)}
|
|
134
|
-
{#if i > 0}<span
|
|
138
|
+
{#if i > 0}<span
|
|
139
|
+
aria-hidden="true"
|
|
140
|
+
class="size-0.5 rounded-full bg-current opacity-50"
|
|
141
|
+
></span>{/if}
|
|
135
142
|
<span>{item}</span>
|
|
136
143
|
{/each}
|
|
137
144
|
</p>
|
|
@@ -148,7 +155,9 @@
|
|
|
148
155
|
|
|
149
156
|
{#if hasRail}
|
|
150
157
|
<!-- `self-start`, since a sticky child only travels inside its own box. -->
|
|
151
|
-
<aside
|
|
158
|
+
<aside
|
|
159
|
+
class="hidden w-48 shrink-0 self-start pt-10 @3xl/page:sticky @3xl/page:top-0 @3xl/page:block"
|
|
160
|
+
>
|
|
152
161
|
<OnThisPage
|
|
153
162
|
items={headings}
|
|
154
163
|
active={spy.active}
|
|
@@ -42,8 +42,15 @@
|
|
|
42
42
|
// =========================
|
|
43
43
|
// DERIVED
|
|
44
44
|
// =========================
|
|
45
|
-
let activeIndex = $derived(
|
|
46
|
-
|
|
45
|
+
let activeIndex = $derived(
|
|
46
|
+
Math.max(
|
|
47
|
+
0,
|
|
48
|
+
items.findIndex((item) => item.id === active),
|
|
49
|
+
),
|
|
50
|
+
);
|
|
51
|
+
let activeLabel = $derived(
|
|
52
|
+
items.find((item) => item.id === active)?.label ?? items[0]?.label ?? "",
|
|
53
|
+
);
|
|
47
54
|
// How far through the document: the bar's hairline, and the number a reader
|
|
48
55
|
// reads at a glance.
|
|
49
56
|
let progress = $derived(items.length > 1 ? activeIndex / (items.length - 1) : 0);
|
|
@@ -205,7 +212,13 @@
|
|
|
205
212
|
|
|
206
213
|
/* A long list fades into its edges instead of ending on a hard cut. */
|
|
207
214
|
.otp-fade {
|
|
208
|
-
mask-image: linear-gradient(
|
|
215
|
+
mask-image: linear-gradient(
|
|
216
|
+
to bottom,
|
|
217
|
+
transparent,
|
|
218
|
+
#000 0.5rem,
|
|
219
|
+
#000 calc(100% - 1.5rem),
|
|
220
|
+
transparent
|
|
221
|
+
);
|
|
209
222
|
}
|
|
210
223
|
|
|
211
224
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -6,9 +6,8 @@
|
|
|
6
6
|
export type DocHeading = { id: string; label: string };
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* since its headings live in another document.
|
|
9
|
+
* A heading's offset in scroller coordinates. A framed document must supply its own, since
|
|
10
|
+
* its headings live in another document.
|
|
12
11
|
*/
|
|
13
12
|
export type LocateHeading = (id: string) => number | null;
|
|
14
13
|
|
|
@@ -25,7 +25,15 @@
|
|
|
25
25
|
// =========================
|
|
26
26
|
// PROPS
|
|
27
27
|
// =========================
|
|
28
|
-
let {
|
|
28
|
+
let {
|
|
29
|
+
label,
|
|
30
|
+
for: htmlFor,
|
|
31
|
+
description,
|
|
32
|
+
error,
|
|
33
|
+
class: className,
|
|
34
|
+
children,
|
|
35
|
+
action,
|
|
36
|
+
}: Props = $props();
|
|
29
37
|
</script>
|
|
30
38
|
|
|
31
39
|
<!-- =========================== -->
|
|
@@ -35,13 +43,7 @@
|
|
|
35
43
|
<!-- WHY the coarse-pointer height: Button grows to 44px on touch and Input
|
|
36
44
|
does not, so a row built from the two drew a 12px step. -->
|
|
37
45
|
<!-- =========================== -->
|
|
38
|
-
<Field.Simple
|
|
39
|
-
{label}
|
|
40
|
-
{description}
|
|
41
|
-
{error}
|
|
42
|
-
for={htmlFor}
|
|
43
|
-
class={cn("max-w-xl", className)}
|
|
44
|
-
>
|
|
46
|
+
<Field.Simple {label} {description} {error} for={htmlFor} class={cn("max-w-xl", className)}>
|
|
45
47
|
<div
|
|
46
48
|
class="flex items-start gap-2 any-pointer-coarse:[&_[data-slot=input]]:h-11"
|
|
47
49
|
data-slot="field-row"
|
|
@@ -183,7 +183,11 @@
|
|
|
183
183
|
width: 2px;
|
|
184
184
|
margin-left: -2px;
|
|
185
185
|
opacity: 0;
|
|
186
|
-
background: color-mix(
|
|
186
|
+
background: color-mix(
|
|
187
|
+
in oklch,
|
|
188
|
+
var(--color-destructive-foreground) 65%,
|
|
189
|
+
var(--color-destructive)
|
|
190
|
+
);
|
|
187
191
|
box-shadow: 0 0 4px 0 color-mix(in oklch, var(--color-destructive) 92%, transparent);
|
|
188
192
|
transition:
|
|
189
193
|
left var(--duration-quick) var(--ease-smooth-out),
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { PhosphorIcon, IconWeight } from "../../lib/icon-types.js";
|
|
2
|
+
import type { PhosphorIcon, IconWeight } from "../../lib/icon-types.js";
|
|
3
3
|
|
|
4
|
-
// =========================
|
|
5
|
-
// TYPES
|
|
6
|
-
// =========================
|
|
7
|
-
interface Props {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
4
|
+
// =========================
|
|
5
|
+
// TYPES
|
|
6
|
+
// =========================
|
|
7
|
+
interface Props {
|
|
8
|
+
icon: PhosphorIcon;
|
|
9
|
+
size?: number;
|
|
10
|
+
class?: string;
|
|
11
|
+
weight?: IconWeight;
|
|
12
|
+
}
|
|
13
13
|
|
|
14
|
-
// =========================
|
|
15
|
-
// PROPS
|
|
16
|
-
// =========================
|
|
17
|
-
let { icon: IconComp, size = 24, class: className = "", weight }: Props = $props();
|
|
14
|
+
// =========================
|
|
15
|
+
// PROPS
|
|
16
|
+
// =========================
|
|
17
|
+
let { icon: IconComp, size = 24, class: className = "", weight }: Props = $props();
|
|
18
18
|
</script>
|
|
19
19
|
|
|
20
20
|
<!-- =========================== -->
|
|
@@ -56,5 +56,7 @@
|
|
|
56
56
|
{/if}
|
|
57
57
|
</span>
|
|
58
58
|
{:else if showLabel}
|
|
59
|
-
<span class={cn("text-xs font-medium uppercase text-muted-foreground", className)}
|
|
59
|
+
<span class={cn("text-xs font-medium uppercase text-muted-foreground", className)}
|
|
60
|
+
>{language}</span
|
|
61
|
+
>
|
|
60
62
|
{/if}
|
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
// =========================
|
|
3
|
-
// IMPORTS
|
|
4
|
-
// =========================
|
|
5
|
-
import EmptyState from "./empty-state.svelte";
|
|
6
|
-
import { cn } from "../../lib/utils.js";
|
|
7
|
-
import type { PhosphorIcon, IconWeight } from "../../lib/icon-types.js";
|
|
2
|
+
// =========================
|
|
3
|
+
// IMPORTS
|
|
4
|
+
// =========================
|
|
5
|
+
import EmptyState from "./empty-state.svelte";
|
|
6
|
+
import { cn } from "../../lib/utils.js";
|
|
7
|
+
import type { PhosphorIcon, IconWeight } from "../../lib/icon-types.js";
|
|
8
8
|
|
|
9
|
-
// =========================
|
|
10
|
-
// TYPES
|
|
11
|
-
// =========================
|
|
12
|
-
interface Props {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
9
|
+
// =========================
|
|
10
|
+
// TYPES
|
|
11
|
+
// =========================
|
|
12
|
+
interface Props {
|
|
13
|
+
// Shown when nothing is picked or the board is empty. Both mean "content
|
|
14
|
+
// goes here", so both get a dashed `border-2` edge.
|
|
15
|
+
icon?: PhosphorIcon;
|
|
16
|
+
iconWeight?: IconWeight;
|
|
17
|
+
title: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
actionLabel?: string;
|
|
20
|
+
actionHref?: string;
|
|
21
|
+
onAction?: () => void;
|
|
22
|
+
class?: string;
|
|
23
|
+
}
|
|
24
24
|
|
|
25
|
-
// =========================
|
|
26
|
-
// PROPS
|
|
27
|
-
// =========================
|
|
28
|
-
let {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}: Props = $props();
|
|
25
|
+
// =========================
|
|
26
|
+
// PROPS
|
|
27
|
+
// =========================
|
|
28
|
+
let {
|
|
29
|
+
icon,
|
|
30
|
+
iconWeight,
|
|
31
|
+
title,
|
|
32
|
+
description,
|
|
33
|
+
actionLabel,
|
|
34
|
+
actionHref,
|
|
35
|
+
onAction,
|
|
36
|
+
class: className,
|
|
37
|
+
}: Props = $props();
|
|
38
38
|
</script>
|
|
39
39
|
|
|
40
40
|
<!-- =========================== -->
|
|
@@ -1,52 +1,61 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
// =========================
|
|
3
|
-
// IMPORTS
|
|
4
|
-
// =========================
|
|
5
|
-
import type { Snippet } from "svelte";
|
|
6
|
-
import { cn } from "../../lib/utils.js";
|
|
2
|
+
// =========================
|
|
3
|
+
// IMPORTS
|
|
4
|
+
// =========================
|
|
5
|
+
import type { Snippet } from "svelte";
|
|
6
|
+
import { cn } from "../../lib/utils.js";
|
|
7
7
|
|
|
8
|
-
// =========================
|
|
9
|
-
// TYPES
|
|
10
|
-
// =========================
|
|
11
|
-
interface Props {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
8
|
+
// =========================
|
|
9
|
+
// TYPES
|
|
10
|
+
// =========================
|
|
11
|
+
interface Props {
|
|
12
|
+
// Answers three questions in one order: what is this, what state is it in,
|
|
13
|
+
// what can I do with it. Each queue page used to order them differently.
|
|
14
|
+
title: string;
|
|
15
|
+
// The state chip beside the title.
|
|
16
|
+
badge?: Snippet;
|
|
17
|
+
// A picture ahead of the title, like a video frame or a deck cover. Some
|
|
18
|
+
// records aren't recognisable from their title alone.
|
|
19
|
+
leading?: Snippet;
|
|
20
|
+
// Facts about the record, rendered as one dot-separated line under the
|
|
21
|
+
// title. Falsy entries drop out, so a caller can inline its conditionals.
|
|
22
|
+
meta?: Array<string | null | undefined | false>;
|
|
23
|
+
// A sentence under the meta line, when the record explains itself.
|
|
24
|
+
note?: string | null;
|
|
25
|
+
// What you can do to the record. Pinned right of the identity block, EXCEPT
|
|
26
|
+
// when a picture leads: see the note in the markup.
|
|
27
|
+
actions?: Snippet;
|
|
28
|
+
// The top-right control, a record's way out. Pass `undefined` when empty:
|
|
29
|
+
// an empty snippet is still truthy and reserves the corner.
|
|
30
|
+
corner?: Snippet;
|
|
31
|
+
// Hairline-separated rows below the identity block. Use `DetailRow`.
|
|
32
|
+
children?: Snippet;
|
|
33
|
+
class?: string;
|
|
34
|
+
}
|
|
35
35
|
|
|
36
|
-
// =========================
|
|
37
|
-
// PROPS
|
|
38
|
-
// =========================
|
|
39
|
-
let {
|
|
40
|
-
|
|
36
|
+
// =========================
|
|
37
|
+
// PROPS
|
|
38
|
+
// =========================
|
|
39
|
+
let {
|
|
40
|
+
title,
|
|
41
|
+
badge,
|
|
42
|
+
leading,
|
|
43
|
+
meta,
|
|
44
|
+
note,
|
|
45
|
+
actions,
|
|
46
|
+
corner,
|
|
47
|
+
children,
|
|
48
|
+
class: className,
|
|
49
|
+
}: Props = $props();
|
|
41
50
|
|
|
42
|
-
// =========================
|
|
43
|
-
// DERIVED
|
|
44
|
-
// =========================
|
|
45
|
-
let facts = $derived((meta ?? []).filter((item): item is string => Boolean(item)));
|
|
46
|
-
// Actions stack under the meta when something else claims the right edge:
|
|
47
|
-
// a picture, or the corner. Pinned beside a corner, they left the title
|
|
48
|
-
// a third of the row.
|
|
49
|
-
let stackActions = $derived(Boolean(leading || corner));
|
|
51
|
+
// =========================
|
|
52
|
+
// DERIVED
|
|
53
|
+
// =========================
|
|
54
|
+
let facts = $derived((meta ?? []).filter((item): item is string => Boolean(item)));
|
|
55
|
+
// Actions stack under the meta when something else claims the right edge:
|
|
56
|
+
// a picture, or the corner. Pinned beside a corner, they left the title
|
|
57
|
+
// a third of the row.
|
|
58
|
+
let stackActions = $derived(Boolean(leading || corner));
|
|
50
59
|
</script>
|
|
51
60
|
|
|
52
61
|
<!-- =========================== -->
|
|
@@ -69,8 +78,7 @@ let stackActions = $derived(Boolean(leading || corner));
|
|
|
69
78
|
<!-- No text-balance: it evens the lines out, so a two-line title stopped
|
|
70
79
|
short of the corner instead of running the full width. -->
|
|
71
80
|
<h2 class="min-w-0 font-heading text-lg font-semibold leading-snug tracking-tight">
|
|
72
|
-
{title}{#if badge}<span class="ms-2 inline-flex align-middle">{@render badge()}</span
|
|
73
|
-
>{/if}
|
|
81
|
+
{title}{#if badge}<span class="ms-2 inline-flex align-middle">{@render badge()}</span>{/if}
|
|
74
82
|
</h2>
|
|
75
83
|
{#if facts.length > 0}
|
|
76
84
|
<!-- Each dot hangs off the fact it leads, so a wrapped line's dot stays
|