@heyramzi/ui 2.0.1 → 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 +48 -24
- 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/README.md +9 -12
- 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 +8 -4
- 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/index.ts +1 -0
- package/src/components/section-header/section-header.svelte +1 -1
- package/src/components/section-header/section-header.test.ts +7 -1
- package/src/components/section-header/section-label.svelte +39 -0
- 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/index.ts +2 -0
- package/src/components/{list-page → toolbar}/toolbar-search.svelte +25 -25
- package/src/components/toolbar/toolbar.svelte +13 -9
- 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 +27 -0
- package/src/inbox/inbox.test.ts +214 -0
- package/src/inbox/index.ts +31 -0
- package/src/inbox/logic.ts +169 -0
- package/src/inbox/thread-inbox.svelte +439 -0
- package/src/inbox/types.ts +161 -0
- 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 +105 -0
- 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/README.md +5 -0
- package/src/panel/index.ts +2 -0
- package/src/panel/side-panel.svelte +194 -0
- package/src/record/README.md +3 -0
- package/src/record/demo-data.ts +352 -0
- package/src/record/field-section.svelte +57 -0
- package/src/record/fields.ts +194 -0
- package/src/record/format.ts +94 -0
- package/src/{tasks/record → record}/index.ts +49 -35
- package/src/{tasks/record → record}/info-list.svelte +145 -114
- package/src/record/kinds.ts +42 -0
- package/src/record/logic.ts +326 -0
- package/src/record/next-up.svelte +81 -0
- package/src/{tasks/record → record}/project-list.svelte +56 -50
- package/src/{tasks/record → record}/record-demo.svelte +130 -110
- package/src/{tasks/record → record}/record-header.svelte +37 -28
- package/src/{tasks/record → record}/record-shell.svelte +54 -54
- package/src/record/record-stats.svelte +48 -0
- package/src/record/record-timeline.svelte +251 -0
- package/src/record/record.test.ts +471 -0
- package/src/{tasks/record → record}/steps-rail.svelte +225 -216
- package/src/record/types.ts +299 -0
- package/src/record/where-we-are.svelte +125 -0
- 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/README.md +18 -0
- package/src/status/define-statuses.ts +25 -0
- package/src/status/index.ts +11 -0
- package/src/{tasks → status}/status-badge.svelte +3 -1
- package/src/{tasks → status}/status-dot.svelte +1 -3
- package/src/{tasks → status}/status-icon.svelte +1 -1
- package/src/status/status-types.ts +40 -0
- package/src/tasks/README.md +1 -1
- package/src/tasks/board-order.ts +2 -4
- package/src/tasks/demo.svelte +192 -34
- package/src/tasks/detail/detail-demo.svelte +75 -15
- 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 +4 -2
- package/src/tasks/gantt/logic.test.ts +110 -20
- package/src/tasks/gantt/logic.ts +42 -6
- package/src/tasks/inbox/inbox-card.svelte +15 -7
- 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 +24 -24
- 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 +52 -53
- package/src/tasks/kanban-board.svelte +16 -12
- package/src/tasks/kanban-types.ts +2 -3
- package/src/tasks/presets/sales.ts +7 -7
- 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/README.md +31 -0
- package/src/thread/index.ts +12 -0
- package/src/thread/logic.ts +61 -0
- package/src/thread/thread.svelte +432 -0
- package/src/thread/thread.test.ts +73 -0
- package/src/thread/types.ts +93 -0
- 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/components/list-page/section-label.svelte +0 -39
- package/src/tasks/define-statuses.ts +0 -32
- package/src/tasks/inbox/inbox.svelte +0 -203
- package/src/tasks/record/demo-data.ts +0 -286
- package/src/tasks/record/field-section.svelte +0 -53
- package/src/tasks/record/fields.ts +0 -142
- package/src/tasks/record/format.ts +0 -87
- package/src/tasks/record/kinds.ts +0 -42
- package/src/tasks/record/logic.ts +0 -324
- package/src/tasks/record/next-up.svelte +0 -70
- package/src/tasks/record/record-stats.svelte +0 -48
- package/src/tasks/record/record-timeline.svelte +0 -231
- package/src/tasks/record/record.test.ts +0 -350
- package/src/tasks/record/types.ts +0 -280
- package/src/tasks/record/where-we-are.svelte +0 -121
- package/src/tasks/side-panel.svelte +0 -193
- package/src/tasks/status-types.ts +0 -40
- /package/src/components/{list-page → toolbar}/toolbar-trigger.ts +0 -0
- /package/src/{tasks → panel}/side-panel-types.ts +0 -0
- /package/src/{tasks/record → record}/gutter.ts +0 -0
|
@@ -1,37 +1,37 @@
|
|
|
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
|
-
}
|
|
8
|
+
// =========================
|
|
9
|
+
// TYPES
|
|
10
|
+
// =========================
|
|
11
|
+
interface Props {
|
|
12
|
+
/** `<DataPanel>` children, or tiles standing beside one. */
|
|
13
|
+
children: Snippet;
|
|
14
|
+
/**
|
|
15
|
+
* Panels per row: two charts, three breakdowns, or `main`, where the first
|
|
16
|
+
* child takes two thirds and the rates beside it one third.
|
|
17
|
+
*/
|
|
18
|
+
columns?: 2 | 3 | "main";
|
|
19
|
+
class?: string;
|
|
20
|
+
}
|
|
21
21
|
|
|
22
|
-
// =========================
|
|
23
|
-
// PROPS
|
|
24
|
-
// =========================
|
|
25
|
-
let { children, columns = 2, class: className }: Props = $props();
|
|
22
|
+
// =========================
|
|
23
|
+
// PROPS
|
|
24
|
+
// =========================
|
|
25
|
+
let { children, columns = 2, class: className }: Props = $props();
|
|
26
26
|
|
|
27
|
-
// =========================
|
|
28
|
-
// CONSTANTS
|
|
29
|
-
// =========================
|
|
30
|
-
const COLUMNS: Record<2 | 3 | "main", string> = {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
};
|
|
27
|
+
// =========================
|
|
28
|
+
// CONSTANTS
|
|
29
|
+
// =========================
|
|
30
|
+
const COLUMNS: Record<2 | 3 | "main", string> = {
|
|
31
|
+
2: "lg:grid-cols-2",
|
|
32
|
+
3: "lg:grid-cols-2 xl:grid-cols-3",
|
|
33
|
+
main: "lg:grid-cols-3 lg:[&>*:first-child]:col-span-2",
|
|
34
|
+
};
|
|
35
35
|
</script>
|
|
36
36
|
|
|
37
37
|
<!-- =========================== -->
|
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
<script lang="ts" generics="T extends string">
|
|
2
|
-
// =========================
|
|
3
|
-
// IMPORTS
|
|
4
|
-
// =========================
|
|
5
|
-
import { cn } from "../../lib/utils.js";
|
|
6
|
-
import { SegmentedFilter, SegmentedNav, type TabDef } from "../../components/segmented/index.js";
|
|
2
|
+
// =========================
|
|
3
|
+
// IMPORTS
|
|
4
|
+
// =========================
|
|
5
|
+
import { cn } from "../../lib/utils.js";
|
|
6
|
+
import { SegmentedFilter, SegmentedNav, type TabDef } from "../../components/segmented/index.js";
|
|
7
7
|
|
|
8
|
-
// =========================
|
|
9
|
-
// TYPES
|
|
10
|
-
// =========================
|
|
11
|
-
interface Props {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
8
|
+
// =========================
|
|
9
|
+
// TYPES
|
|
10
|
+
// =========================
|
|
11
|
+
interface Props {
|
|
12
|
+
options: readonly TabDef<T>[];
|
|
13
|
+
value: T;
|
|
14
|
+
/**
|
|
15
|
+
* Give this and the strip is links, so the choice survives reload, back and a
|
|
16
|
+
* shared link. Omit it and the strip is a `<SegmentedFilter>` the caller owns.
|
|
17
|
+
*/
|
|
18
|
+
href?: (value: T) => string;
|
|
19
|
+
/** Filter mode only. Ignored when `href` is set. */
|
|
20
|
+
onValueChange?: (value: T) => void;
|
|
21
|
+
ariaLabel: string;
|
|
22
|
+
class?: string;
|
|
23
|
+
}
|
|
24
24
|
|
|
25
|
-
// =========================
|
|
26
|
-
// PROPS
|
|
27
|
-
// =========================
|
|
28
|
-
let { options, value, href, onValueChange, ariaLabel, class: className }: Props = $props();
|
|
25
|
+
// =========================
|
|
26
|
+
// PROPS
|
|
27
|
+
// =========================
|
|
28
|
+
let { options, value, href, onValueChange, ariaLabel, class: className }: Props = $props();
|
|
29
29
|
</script>
|
|
30
30
|
|
|
31
31
|
<!-- =========================== -->
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
/*
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { cn } from "../../lib/utils.js";
|
|
2
|
+
/*
|
|
3
|
+
* One A to E grade on one colour scale, so a C means one thing everywhere.
|
|
4
|
+
* Light mode takes the 800 shades, since amber on cream fails contrast.
|
|
5
|
+
*/
|
|
6
|
+
import { cn } from "../../lib/utils.js";
|
|
7
7
|
|
|
8
|
-
interface Props {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
8
|
+
interface Props {
|
|
9
|
+
grade: string;
|
|
10
|
+
/** What the letter hides: the score and what it was charged for. */
|
|
11
|
+
hint?: string;
|
|
12
|
+
class?: string;
|
|
13
|
+
}
|
|
14
14
|
|
|
15
|
-
let { grade, hint, class: className }: Props = $props();
|
|
15
|
+
let { grade, hint, class: className }: Props = $props();
|
|
16
16
|
|
|
17
|
-
const TONE: Record<string, string> = {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
};
|
|
17
|
+
const TONE: Record<string, string> = {
|
|
18
|
+
A: "bg-success/12 text-success-800 dark:text-success",
|
|
19
|
+
B: "bg-success/12 text-success-800 dark:text-success",
|
|
20
|
+
C: "bg-muted text-foreground",
|
|
21
|
+
D: "bg-warning/18 text-warning-800 dark:text-warning",
|
|
22
|
+
E: "bg-destructive/12 text-destructive",
|
|
23
|
+
};
|
|
24
24
|
</script>
|
|
25
25
|
|
|
26
26
|
<span
|
|
@@ -1,39 +1,39 @@
|
|
|
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
|
-
}
|
|
8
|
+
// =========================
|
|
9
|
+
// TYPES
|
|
10
|
+
// =========================
|
|
11
|
+
interface Props {
|
|
12
|
+
/** `<StatTile>` children. Four to a row on a desk, two on a phone. */
|
|
13
|
+
children: Snippet;
|
|
14
|
+
/**
|
|
15
|
+
* Cards per row at the widest breakpoint, four unless the set is smaller.
|
|
16
|
+
* Five and six are only for a fixed scorecard. The headline stays one row.
|
|
17
|
+
*/
|
|
18
|
+
columns?: 2 | 3 | 4 | 5 | 6;
|
|
19
|
+
class?: string;
|
|
20
|
+
}
|
|
21
21
|
|
|
22
|
-
// =========================
|
|
23
|
-
// PROPS
|
|
24
|
-
// =========================
|
|
25
|
-
let { children, columns = 4, class: className }: Props = $props();
|
|
22
|
+
// =========================
|
|
23
|
+
// PROPS
|
|
24
|
+
// =========================
|
|
25
|
+
let { children, columns = 4, class: className }: Props = $props();
|
|
26
26
|
|
|
27
|
-
// =========================
|
|
28
|
-
// DERIVED
|
|
29
|
-
// =========================
|
|
30
|
-
const COLUMNS: Record<2 | 3 | 4 | 5 | 6, string> = {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
};
|
|
27
|
+
// =========================
|
|
28
|
+
// DERIVED
|
|
29
|
+
// =========================
|
|
30
|
+
const COLUMNS: Record<2 | 3 | 4 | 5 | 6, string> = {
|
|
31
|
+
2: "sm:grid-cols-2",
|
|
32
|
+
3: "sm:grid-cols-2 lg:grid-cols-3",
|
|
33
|
+
4: "sm:grid-cols-2 lg:grid-cols-4",
|
|
34
|
+
5: "sm:grid-cols-3 lg:grid-cols-5",
|
|
35
|
+
6: "sm:grid-cols-3 xl:grid-cols-6",
|
|
36
|
+
};
|
|
37
37
|
</script>
|
|
38
38
|
|
|
39
39
|
<!-- =========================== -->
|
|
@@ -1,108 +1,108 @@
|
|
|
1
1
|
<script lang="ts" module>
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export type StatDirection = "up-good" | "down-good" | "neutral";
|
|
2
|
+
/**
|
|
3
|
+
* Which way a metric has to move to be good news. `neutral` fits a figure like
|
|
4
|
+
* spend, which isn't a win or a loss until the return sits beside it.
|
|
5
|
+
*/
|
|
6
|
+
export type StatDirection = "up-good" | "down-good" | "neutral";
|
|
7
7
|
</script>
|
|
8
8
|
|
|
9
9
|
<script lang="ts">
|
|
10
|
-
// =========================
|
|
11
|
-
// IMPORTS
|
|
12
|
-
// =========================
|
|
13
|
-
import NumberChart from "../number-chart.svelte";
|
|
14
|
-
import Sparkline from "../sparkline.svelte";
|
|
15
|
-
import type { Snippet } from "svelte";
|
|
16
|
-
import { cn } from "../../lib/utils.js";
|
|
17
|
-
import { Icon } from "../../components/icon/index.js";
|
|
18
|
-
import type { PhosphorIcon } from "../../lib/icon-types.js";
|
|
10
|
+
// =========================
|
|
11
|
+
// IMPORTS
|
|
12
|
+
// =========================
|
|
13
|
+
import NumberChart from "../number-chart.svelte";
|
|
14
|
+
import Sparkline from "../sparkline.svelte";
|
|
15
|
+
import type { Snippet } from "svelte";
|
|
16
|
+
import { cn } from "../../lib/utils.js";
|
|
17
|
+
import { Icon } from "../../components/icon/index.js";
|
|
18
|
+
import type { PhosphorIcon } from "../../lib/icon-types.js";
|
|
19
19
|
|
|
20
|
-
// =========================
|
|
21
|
-
// TYPES
|
|
22
|
-
// =========================
|
|
23
|
-
interface Props {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
20
|
+
// =========================
|
|
21
|
+
// TYPES
|
|
22
|
+
// =========================
|
|
23
|
+
interface Props {
|
|
24
|
+
label: string;
|
|
25
|
+
/** Already formatted. The tile never guesses a currency or a locale. */
|
|
26
|
+
value: string;
|
|
27
|
+
/**
|
|
28
|
+
* Percent change against the previous period. `null` means nothing to
|
|
29
|
+
* compare yet and draws a dash. Omit it when the figure has no period at all.
|
|
30
|
+
*/
|
|
31
|
+
deltaPct?: number | null;
|
|
32
|
+
direction?: StatDirection;
|
|
33
|
+
/** The one figure the screen was opened to read. Set it on exactly one tile. */
|
|
34
|
+
lead?: boolean;
|
|
35
|
+
/** A quiet line under the value: what it was measured over, or why it is a dash. */
|
|
36
|
+
hint?: string;
|
|
37
|
+
/**
|
|
38
|
+
* 0 to 1, drawn as a track under the value: share of a total or progress to
|
|
39
|
+
* a target. Omit it for a cash balance.
|
|
40
|
+
*/
|
|
41
|
+
share?: number;
|
|
42
|
+
/** What `share` is measured against, e.g. "of revenue". Only with `share`. */
|
|
43
|
+
shareLabel?: string;
|
|
44
|
+
/** Track colour. The first series token unless a tile means something else. */
|
|
45
|
+
color?: string;
|
|
46
|
+
/**
|
|
47
|
+
* A shape behind the figure, oldest first, bled along the card's bottom.
|
|
48
|
+
* The treatment every tile gives a number with a history. Omit when there
|
|
49
|
+
* is none.
|
|
50
|
+
*/
|
|
51
|
+
series?: number[];
|
|
52
|
+
/** Leading mark before the label. */
|
|
53
|
+
icon?: PhosphorIcon;
|
|
54
|
+
/**
|
|
55
|
+
* Makes the tile a link, like a balance that opens the bank. It lives here so
|
|
56
|
+
* a linked figure isn't drawn as a second, different card style.
|
|
57
|
+
*/
|
|
58
|
+
href?: string;
|
|
59
|
+
/** What the link opens, shown on hover. Only with `href`. */
|
|
60
|
+
hrefLabel?: string;
|
|
61
|
+
/**
|
|
62
|
+
* `_blank` for a figure that leaves the app (a bank, a provider console),
|
|
63
|
+
* `_self` for one that is another page of this app. Only with `href`.
|
|
64
|
+
*/
|
|
65
|
+
target?: "_self" | "_blank";
|
|
66
|
+
/**
|
|
67
|
+
* A chip at the end of the label row: the limit the figure is judged against,
|
|
68
|
+
* the state it is in. Wins over `hrefLabel`, which is only a hover hint.
|
|
69
|
+
*/
|
|
70
|
+
badge?: Snippet;
|
|
71
|
+
/** A loss or an overrun: the figure turns the destructive colour. */
|
|
72
|
+
negative?: boolean;
|
|
73
|
+
class?: string;
|
|
74
|
+
}
|
|
75
75
|
|
|
76
|
-
// =========================
|
|
77
|
-
// PROPS
|
|
78
|
-
// =========================
|
|
79
|
-
let {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}: Props = $props();
|
|
76
|
+
// =========================
|
|
77
|
+
// PROPS
|
|
78
|
+
// =========================
|
|
79
|
+
let {
|
|
80
|
+
label,
|
|
81
|
+
value,
|
|
82
|
+
deltaPct,
|
|
83
|
+
direction = "neutral",
|
|
84
|
+
lead = false,
|
|
85
|
+
hint,
|
|
86
|
+
share,
|
|
87
|
+
shareLabel,
|
|
88
|
+
color,
|
|
89
|
+
series,
|
|
90
|
+
icon,
|
|
91
|
+
href,
|
|
92
|
+
hrefLabel,
|
|
93
|
+
target = "_blank",
|
|
94
|
+
badge,
|
|
95
|
+
negative = false,
|
|
96
|
+
class: className,
|
|
97
|
+
}: Props = $props();
|
|
98
98
|
|
|
99
|
-
// =========================
|
|
100
|
-
// DERIVED
|
|
101
|
-
// =========================
|
|
102
|
-
// `Sparkline` plots rows, and a card carries a bare series. Two points is a
|
|
103
|
-
// line, not a shape, so it is not drawn.
|
|
104
|
-
let points = $derived(series?.map((value, index) => ({ i: index, v: value })) ?? []);
|
|
105
|
-
let hasSeries = $derived(points.length > 2);
|
|
99
|
+
// =========================
|
|
100
|
+
// DERIVED
|
|
101
|
+
// =========================
|
|
102
|
+
// `Sparkline` plots rows, and a card carries a bare series. Two points is a
|
|
103
|
+
// line, not a shape, so it is not drawn.
|
|
104
|
+
let points = $derived(series?.map((value, index) => ({ i: index, v: value })) ?? []);
|
|
105
|
+
let hasSeries = $derived(points.length > 2);
|
|
106
106
|
</script>
|
|
107
107
|
|
|
108
108
|
<!-- =========================== -->
|
|
@@ -155,7 +155,14 @@ let hasSeries = $derived(points.length > 2);
|
|
|
155
155
|
class="pointer-events-none absolute inset-x-px bottom-px h-12 overflow-hidden rounded-b-[calc(var(--radius-xl)-1px)]"
|
|
156
156
|
aria-hidden="true"
|
|
157
157
|
>
|
|
158
|
-
<Sparkline
|
|
158
|
+
<Sparkline
|
|
159
|
+
data={points}
|
|
160
|
+
xKey="i"
|
|
161
|
+
yKey="v"
|
|
162
|
+
color={color ?? "var(--chart-1)"}
|
|
163
|
+
height={48}
|
|
164
|
+
bare
|
|
165
|
+
/>
|
|
159
166
|
</div>
|
|
160
167
|
{/if}
|
|
161
168
|
</svelte:element>
|
package/src/charts/figure.svelte
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
otherwise collide with RingChart's identical `.value`/`.label`/`.center`/
|
|
4
|
-
`.fill`/`svg` names once they are no longer Svelte-scoped). */
|
|
1
|
+
/* A plain stylesheet (see area-chart.css), namespaced under `.hr-gauge` because RingChart's
|
|
2
|
+
unscoped `.value`, `.label` and `.center` would otherwise collide. */
|
|
5
3
|
|
|
6
4
|
.hr-gauge {
|
|
7
5
|
position: relative;
|
|
@@ -51,9 +49,8 @@
|
|
|
51
49
|
/* WHY: active paint comes from the fill attribute (flat or gradient url), so
|
|
52
50
|
no CSS fill here, which would override it. */
|
|
53
51
|
.hr-gauge .fill {
|
|
54
|
-
/* WHY:
|
|
55
|
-
|
|
56
|
-
of every notch popping in from the centre at once. */
|
|
52
|
+
/* WHY: active notches fade up in arc order, so the gauge reads as filling
|
|
53
|
+
instead of every notch popping in at once. */
|
|
57
54
|
animation: hr-gauge-notch-in 0.3s var(--chart-ease-out, cubic-bezier(0.22, 1, 0.36, 1)) both;
|
|
58
55
|
}
|
|
59
56
|
|
package/src/charts/legend.css
CHANGED
|
@@ -111,9 +111,7 @@
|
|
|
111
111
|
height: 100%;
|
|
112
112
|
border-radius: 999px;
|
|
113
113
|
/* WHY: scaleX from the left avoids the layout thrash of animating width;
|
|
114
|
-
the bar's fill fraction is set inline as --hr-bar-scale.
|
|
115
|
-
sweeps from 0 once (delays match the ring sweep); the transition takes
|
|
116
|
-
over for later data changes. */
|
|
114
|
+
the bar's fill fraction is set inline as --hr-bar-scale. */
|
|
117
115
|
transform-origin: left center;
|
|
118
116
|
transform: scaleX(var(--hr-bar-scale, 0));
|
|
119
117
|
animation: hr-legend-fill var(--chart-motion-reveal, 1100ms)
|
package/src/charts/legend.svelte
CHANGED
|
@@ -18,9 +18,8 @@
|
|
|
18
18
|
border-color: color-mix(in srgb, var(--ring, var(--chart-1)) 28%, var(--border, transparent));
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
/*
|
|
22
|
-
|
|
23
|
-
Same object, one less border. */
|
|
21
|
+
/* A band is one panel with hairlines through it, so a figure inside it must bring no
|
|
22
|
+
edge of its own. */
|
|
24
23
|
.hr-number-chart[data-bare] {
|
|
25
24
|
padding: 1rem;
|
|
26
25
|
border: 0;
|
|
@@ -60,9 +59,8 @@
|
|
|
60
59
|
font-size: 0.625rem;
|
|
61
60
|
}
|
|
62
61
|
|
|
63
|
-
/*
|
|
64
|
-
carry a caption
|
|
65
|
-
sit on one line. The slack falls to the bottom, where nothing reads it. */
|
|
62
|
+
/* Baseline-aligned and top-anchored, so values sit on one line even when only some
|
|
63
|
+
figures carry a caption. */
|
|
66
64
|
.hr-number-row {
|
|
67
65
|
display: flex;
|
|
68
66
|
align-items: baseline;
|
|
@@ -108,9 +106,8 @@
|
|
|
108
106
|
.hr-number-delta-text {
|
|
109
107
|
font-variant-numeric: tabular-nums;
|
|
110
108
|
}
|
|
111
|
-
/*
|
|
112
|
-
|
|
113
|
-
serves both themes and the package needs to know nothing about which is on. */
|
|
109
|
+
/* A trend hue measures about 3.5:1 as 12px text, so it's mixed toward the foreground,
|
|
110
|
+
which works in both themes. */
|
|
114
111
|
.hr-number-delta[data-tone="up"] {
|
|
115
112
|
color: color-mix(
|
|
116
113
|
in oklab,
|