@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
package/src/inbox/types.ts
CHANGED
|
@@ -3,137 +3,159 @@ import type { InboxItem } from "../tasks/inbox/inbox-types.js";
|
|
|
3
3
|
export type InboxActorKind = "user" | "agent";
|
|
4
4
|
|
|
5
5
|
export type InboxActor = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
kind: InboxActorKind;
|
|
7
|
+
name: string;
|
|
8
|
+
/** Image URL for a person. The host's own portrait goes through the `avatar` snippet. */
|
|
9
|
+
avatar?: string;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
export type InboxEntryKind =
|
|
12
|
+
export type InboxEntryKind =
|
|
13
|
+
| "comment"
|
|
14
|
+
| "status"
|
|
15
|
+
| "assigned"
|
|
16
|
+
| "mention"
|
|
17
|
+
| "agent_response"
|
|
18
|
+
| "proposal";
|
|
13
19
|
|
|
14
20
|
/** What the thread is about: one task, project or doc. Entries with the same type and id share a thread. */
|
|
15
21
|
export type InboxSubject = {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
/** "task", "project", "doc" or whatever the host calls it. */
|
|
23
|
+
type: string;
|
|
24
|
+
id: string;
|
|
25
|
+
/** The short reference, such as "TSK-7". */
|
|
26
|
+
ref?: string;
|
|
27
|
+
title: string;
|
|
28
|
+
/** A status id the host draws itself, for a badge in the thread header. */
|
|
29
|
+
status?: string;
|
|
30
|
+
href?: string;
|
|
25
31
|
};
|
|
26
32
|
|
|
27
33
|
export type InboxEntry = {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
34
|
+
id: string;
|
|
35
|
+
kind: InboxEntryKind;
|
|
36
|
+
/** An entry with no subject id belongs to no thread and is dropped. */
|
|
37
|
+
subject?: InboxSubject;
|
|
38
|
+
actor: InboxActor;
|
|
39
|
+
/** ISO timestamp. A malformed one sorts last. */
|
|
40
|
+
at: string;
|
|
41
|
+
read?: boolean;
|
|
42
|
+
/** Text of a comment, a mention or an agent response. */
|
|
43
|
+
body?: string;
|
|
44
|
+
/** A `status` entry: where the subject moved. */
|
|
45
|
+
status?: { from?: string; to: string };
|
|
46
|
+
/** An `assigned` entry: who got the work. */
|
|
47
|
+
assignee?: string;
|
|
48
|
+
/** A `proposal` entry: the agent's ask, drawn as an InboxCard while it waits. */
|
|
49
|
+
proposal?: InboxItem;
|
|
44
50
|
};
|
|
45
51
|
|
|
46
52
|
export type InboxThread = {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
/** `type:id`, unique across subjects. */
|
|
54
|
+
key: string;
|
|
55
|
+
subject: InboxSubject;
|
|
56
|
+
/** Oldest first. */
|
|
57
|
+
entries: InboxEntry[];
|
|
58
|
+
unread: number;
|
|
59
|
+
/** The newest valid timestamp, as written. The raw first one when none parses. */
|
|
60
|
+
latestAt: string;
|
|
61
|
+
/** Proposals still waiting for a verdict, newest first. */
|
|
62
|
+
pending: InboxEntry[];
|
|
57
63
|
};
|
|
58
64
|
|
|
59
65
|
export type InboxFilter = {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
/** A subject type, or "all". */
|
|
67
|
+
type: string;
|
|
68
|
+
/** An actor name, or "all". */
|
|
69
|
+
who: string;
|
|
70
|
+
/** Only threads holding a pending proposal. */
|
|
71
|
+
needsYou: boolean;
|
|
66
72
|
};
|
|
67
73
|
|
|
68
74
|
export const ALL = "all";
|
|
69
75
|
|
|
70
|
-
export type InboxKey =
|
|
76
|
+
export type InboxKey =
|
|
77
|
+
| "next"
|
|
78
|
+
| "previous"
|
|
79
|
+
| "toggleRead"
|
|
80
|
+
| "snooze"
|
|
81
|
+
| "approve"
|
|
82
|
+
| "decline"
|
|
83
|
+
| "steer"
|
|
84
|
+
| "edit";
|
|
71
85
|
|
|
72
86
|
export type InboxSnooze = { thread: InboxThread; until: Date };
|
|
73
87
|
|
|
74
88
|
export type InboxLabels = {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
89
|
+
title: string;
|
|
90
|
+
all: string;
|
|
91
|
+
anyone: string;
|
|
92
|
+
needsYou: string;
|
|
93
|
+
empty: string;
|
|
94
|
+
emptyNeedsYou: string;
|
|
95
|
+
emptyFiltered: string;
|
|
96
|
+
clearFilters: string;
|
|
97
|
+
unread: string;
|
|
98
|
+
markRead: string;
|
|
99
|
+
markUnread: string;
|
|
100
|
+
snooze: string;
|
|
101
|
+
snoozeLater: string;
|
|
102
|
+
snoozeTomorrow: string;
|
|
103
|
+
snoozeNextWeek: string;
|
|
104
|
+
selectThread: string;
|
|
105
|
+
filterType: string;
|
|
106
|
+
filterWho: string;
|
|
107
|
+
filter: string;
|
|
108
|
+
kind: string;
|
|
109
|
+
from: string;
|
|
110
|
+
open: string;
|
|
111
|
+
agent: string;
|
|
112
|
+
statusMoved: string;
|
|
113
|
+
statusSet: string;
|
|
114
|
+
assigned: string;
|
|
115
|
+
mentioned: string;
|
|
116
|
+
commented: string;
|
|
117
|
+
responded: string;
|
|
118
|
+
proposed: string;
|
|
119
|
+
/** Keyboard hint words. */
|
|
120
|
+
hintMove: string;
|
|
121
|
+
hintRead: string;
|
|
122
|
+
hintSnooze: string;
|
|
123
|
+
hintAct: string;
|
|
106
124
|
};
|
|
107
125
|
|
|
108
126
|
export const DEFAULT_INBOX_LABELS: InboxLabels = {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
127
|
+
title: "Inbox",
|
|
128
|
+
all: "All",
|
|
129
|
+
anyone: "Anyone",
|
|
130
|
+
needsYou: "Needs you",
|
|
131
|
+
empty: "Nothing here",
|
|
132
|
+
emptyNeedsYou: "Nothing is waiting on you",
|
|
133
|
+
emptyFiltered: "No thread matches these filters",
|
|
134
|
+
clearFilters: "Clear filters",
|
|
135
|
+
unread: "unread",
|
|
136
|
+
markRead: "Mark read",
|
|
137
|
+
markUnread: "Mark unread",
|
|
138
|
+
snooze: "Snooze",
|
|
139
|
+
snoozeLater: "Later today",
|
|
140
|
+
snoozeTomorrow: "Tomorrow",
|
|
141
|
+
snoozeNextWeek: "Next week",
|
|
142
|
+
selectThread: "Select a thread",
|
|
143
|
+
filterType: "Filter by type",
|
|
144
|
+
filterWho: "Filter by person or agent",
|
|
145
|
+
filter: "Filter",
|
|
146
|
+
kind: "Type",
|
|
147
|
+
from: "From",
|
|
148
|
+
open: "Open",
|
|
149
|
+
agent: "AI",
|
|
150
|
+
statusMoved: "moved this from {from} to {to}",
|
|
151
|
+
statusSet: "set this to {to}",
|
|
152
|
+
assigned: "assigned this to {assignee}",
|
|
153
|
+
mentioned: "mentioned you",
|
|
154
|
+
commented: "commented",
|
|
155
|
+
responded: "replied",
|
|
156
|
+
proposed: "asks for your call",
|
|
157
|
+
hintMove: "move",
|
|
158
|
+
hintRead: "read",
|
|
159
|
+
hintSnooze: "snooze",
|
|
160
|
+
hintAct: "approve, decline, steer, edit",
|
|
139
161
|
};
|
|
@@ -14,10 +14,8 @@ const DEFAULT_DURATION = 400;
|
|
|
14
14
|
const STYLE_ID = "heyramzi-reveal-theme";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* Run `apply` inside a circular wipe
|
|
18
|
-
*
|
|
19
|
-
* browser has no view transitions, the user prefers reduced motion, or `skip`
|
|
20
|
-
* is set. It adds the `::view-transition-*(root)` reset itself.
|
|
17
|
+
* Run `apply` inside a circular wipe from the clicked element or a point, falling back to
|
|
18
|
+
* plain `apply()` without view transitions, under reduced motion, or with `skip`.
|
|
21
19
|
*/
|
|
22
20
|
export function revealTheme(
|
|
23
21
|
origin: RevealOrigin,
|
package/src/lib/tone.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
export type Tone = "neutral" | "accent" | "info" | "success" | "warning" | "destructive";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* The severity scale
|
|
5
|
-
*
|
|
6
|
-
* accent tone reads `--tone-accent` and falls back to `--color-primary`, for a
|
|
7
|
-
* host whose primary is a neutral and whose accent is a brand color.
|
|
4
|
+
* The severity scale as chip classes and dot colors. Accent reads `--tone-accent` before
|
|
5
|
+
* `--color-primary`, for a host whose primary is a neutral.
|
|
8
6
|
*/
|
|
9
7
|
|
|
10
8
|
export const TONE_CLASS: Record<Tone, string> = {
|
package/src/lib/utils.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// The class merge and prop types every shadcn primitive
|
|
2
|
-
//
|
|
1
|
+
// The class merge and prop types every shadcn primitive uses, kept here, not in a shared utils
|
|
2
|
+
// package, so this public package installs with nothing private behind it.
|
|
3
3
|
import { type ClassValue, clsx } from "clsx";
|
|
4
4
|
import { twMerge } from "tailwind-merge";
|
|
5
5
|
|
package/src/modules.test.ts
CHANGED
|
@@ -5,91 +5,101 @@ import { describe, expect, it, vi } from "vite-plus/test";
|
|
|
5
5
|
import * as status from "./status/index.js";
|
|
6
6
|
import * as panel from "./panel/index.js";
|
|
7
7
|
import * as record from "./record/index.js";
|
|
8
|
-
import * as taskInbox from "./tasks/inbox/index.js";
|
|
9
8
|
import * as inbox from "./inbox/index.js";
|
|
10
9
|
import * as thread from "./thread/index.js";
|
|
11
10
|
import type {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
PanelStat as FromTasksPanelStat,
|
|
12
|
+
SidePanelWidth as FromTasksWidth,
|
|
13
|
+
StatusDef as FromTasksStatusDef,
|
|
14
|
+
StatusDotVariant as FromTasksVariant,
|
|
15
|
+
StatusId as FromTasksId,
|
|
16
|
+
StatusMap as FromTasksMap,
|
|
17
|
+
Statuses as FromTasksStatuses,
|
|
19
18
|
} from "./tasks/index.js";
|
|
20
19
|
import type { PanelStat, SidePanelWidth } from "./panel/index.js";
|
|
21
|
-
import type {
|
|
20
|
+
import type {
|
|
21
|
+
StatusDef,
|
|
22
|
+
StatusDotVariant,
|
|
23
|
+
StatusId,
|
|
24
|
+
StatusMap,
|
|
25
|
+
Statuses,
|
|
26
|
+
} from "./status/index.js";
|
|
22
27
|
|
|
23
28
|
// Both spellings of every moved type have to be the same type.
|
|
24
29
|
type Same<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false;
|
|
25
30
|
const sameTypes: [
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
Same<PanelStat, FromTasksPanelStat>,
|
|
32
|
+
Same<SidePanelWidth, FromTasksWidth>,
|
|
33
|
+
Same<StatusDef, FromTasksStatusDef>,
|
|
34
|
+
Same<StatusDotVariant, FromTasksVariant>,
|
|
35
|
+
Same<StatusId<{ a: StatusDef }>, FromTasksId<{ a: StatusDef }>>,
|
|
36
|
+
Same<StatusMap, FromTasksMap>,
|
|
37
|
+
Same<Statuses, FromTasksStatuses>,
|
|
33
38
|
] = [true, true, true, true, true, true, true];
|
|
34
39
|
|
|
35
|
-
const pkg = JSON.parse(
|
|
36
|
-
|
|
40
|
+
const pkg = JSON.parse(
|
|
41
|
+
readFileSync(join(dirname(fileURLToPath(import.meta.url)), "..", "package.json"), "utf8"),
|
|
42
|
+
) as {
|
|
43
|
+
exports: Record<string, string | Record<string, string>>;
|
|
37
44
|
};
|
|
38
45
|
|
|
39
46
|
describe("module split", () => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
it("keeps every moved name on tasks, the same object as on its new module", async () => {
|
|
48
|
+
// The kanban board reads matchMedia on import, and jsdom has none.
|
|
49
|
+
vi.stubGlobal("matchMedia", () => ({
|
|
50
|
+
matches: false,
|
|
51
|
+
addEventListener() {},
|
|
52
|
+
removeEventListener() {},
|
|
53
|
+
}));
|
|
54
|
+
const tasks = await import("./tasks/index.js");
|
|
55
|
+
expect(sameTypes).toHaveLength(7);
|
|
56
|
+
expect(tasks.StatusBadge).toBe(status.StatusBadge);
|
|
57
|
+
expect(tasks.StatusDot).toBe(status.StatusDot);
|
|
58
|
+
expect(tasks.StatusIcon).toBe(status.StatusIcon);
|
|
59
|
+
expect(tasks.defineStatuses).toBe(status.defineStatuses);
|
|
60
|
+
expect(tasks.StatusBadge).toBeDefined();
|
|
61
|
+
expect(tasks.SidePanel).toBe(panel.SidePanel);
|
|
62
|
+
});
|
|
53
63
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
64
|
+
it("holds the record page's names", () => {
|
|
65
|
+
expect(record.RecordShell).toBeDefined();
|
|
66
|
+
expect(record.DEFAULT_RECORD_LABELS).toBeDefined();
|
|
67
|
+
});
|
|
58
68
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
it("names what the new modules export", () => {
|
|
70
|
+
expect(thread.Thread).toBeDefined();
|
|
71
|
+
expect(inbox.ThreadInbox).toBeDefined();
|
|
72
|
+
expect(inbox.InboxCard).toBeDefined();
|
|
73
|
+
expect(inbox.threadsOf).toBeTypeOf("function");
|
|
74
|
+
});
|
|
65
75
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
it("resolves every export path to a file", () => {
|
|
77
|
+
const root = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
78
|
+
const missing: string[] = [];
|
|
79
|
+
for (const [name, target] of Object.entries(pkg.exports)) {
|
|
80
|
+
const path = typeof target === "string" ? target : (target.default ?? target.svelte);
|
|
81
|
+
if (path.includes("*") || path.endsWith(".css")) continue;
|
|
82
|
+
if (!existsSync(join(root, path))) missing.push(`${name} -> ${path}`);
|
|
83
|
+
}
|
|
84
|
+
expect(missing).toEqual([]);
|
|
85
|
+
});
|
|
76
86
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
87
|
+
it("keeps the old subpaths and adds the new ones", () => {
|
|
88
|
+
for (const name of [
|
|
89
|
+
"./tasks",
|
|
90
|
+
"./tasks/status",
|
|
91
|
+
"./tasks/status-dot",
|
|
92
|
+
"./tasks/statuses",
|
|
93
|
+
"./tasks/side-panel",
|
|
94
|
+
"./tasks/record",
|
|
95
|
+
"./tasks/inbox",
|
|
96
|
+
"./status",
|
|
97
|
+
"./panel",
|
|
98
|
+
"./record",
|
|
99
|
+
"./thread",
|
|
100
|
+
"./inbox",
|
|
101
|
+
]) {
|
|
102
|
+
expect(pkg.exports[name], name).toBeDefined();
|
|
103
|
+
}
|
|
104
|
+
});
|
|
95
105
|
});
|
|
@@ -2,49 +2,64 @@ import { describe, expect, it } from "vite-plus/test";
|
|
|
2
2
|
import { defineTours } from "./define-tours.js";
|
|
3
3
|
import type { Step, Tour } from "./types.js";
|
|
4
4
|
|
|
5
|
-
const step = (n: number): Step => ({
|
|
5
|
+
const step = (n: number): Step => ({
|
|
6
|
+
target: `[data-tour="s${n}"]`,
|
|
7
|
+
title: `Title ${n}`,
|
|
8
|
+
body: `Body ${n}`,
|
|
9
|
+
});
|
|
6
10
|
const steps = (count: number) => Array.from({ length: count }, (_, i) => step(i + 1));
|
|
7
11
|
const board = (over: Partial<Extract<Tour, { kind: "steps" }>> = {}): Tour => ({
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
id: "board",
|
|
13
|
+
route: "/(app)/projects",
|
|
14
|
+
kind: "steps",
|
|
15
|
+
steps: steps(3),
|
|
16
|
+
...over,
|
|
13
17
|
});
|
|
14
18
|
|
|
15
19
|
describe("defineTours", () => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
20
|
+
it("returns the tours it was given", () => {
|
|
21
|
+
const list = [
|
|
22
|
+
board(),
|
|
23
|
+
{ id: "home", route: "/(app)", kind: "intro", title: "Hi", body: "Welcome." } as const,
|
|
24
|
+
];
|
|
25
|
+
expect(defineTours(list)).toBe(list);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("rejects a repeated id", () => {
|
|
29
|
+
expect(() => defineTours([board(), board({ route: "/(app)/other" })])).toThrow(
|
|
30
|
+
/"board".*used twice/,
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("takes 1 to 6 steps", () => {
|
|
35
|
+
expect(() => defineTours([board({ steps: steps(1) })])).not.toThrow();
|
|
36
|
+
expect(() => defineTours([board({ steps: steps(6) })])).not.toThrow();
|
|
37
|
+
expect(() => defineTours([board({ steps: [] })])).toThrow(/0 steps/);
|
|
38
|
+
expect(() => defineTours([board({ steps: steps(7) })])).toThrow(/7 steps/);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("rejects a route that isn't a route id", () => {
|
|
42
|
+
expect(() => defineTours([board({ route: "projects" })])).toThrow(/not a route id/);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("rejects a bad version", () => {
|
|
46
|
+
expect(() => defineTours([board({ version: 0 })])).toThrow(/version/);
|
|
47
|
+
expect(() => defineTours([board({ version: 1.5 })])).toThrow(/version/);
|
|
48
|
+
expect(() => defineTours([board({ version: 2 })])).not.toThrow();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("rejects a step with no target or no words", () => {
|
|
52
|
+
expect(() => defineTours([board({ steps: [{ ...step(1), target: " " }] })])).toThrow(
|
|
53
|
+
/step 1 has no target/,
|
|
54
|
+
);
|
|
55
|
+
expect(() => defineTours([board({ steps: [{ ...step(1), body: "" }] })])).toThrow(
|
|
56
|
+
/title and a body/,
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("rejects an intro with no title", () => {
|
|
61
|
+
expect(() =>
|
|
62
|
+
defineTours([{ id: "home", route: "/(app)", kind: "intro", title: "", body: "x" }]),
|
|
63
|
+
).toThrow(/intro/);
|
|
64
|
+
});
|
|
50
65
|
});
|
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
import { MAX_STEPS, type Tour } from "./types.js";
|
|
2
2
|
|
|
3
3
|
function fail(id: string, problem: string): never {
|
|
4
|
-
|
|
4
|
+
throw new Error(`tour "${id}": ${problem}`);
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
/** Returns the tours as written, after checking what a typo would hide until a user hits it. */
|
|
8
8
|
export function defineTours<const T extends readonly Tour[]>(tours: T): T {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
9
|
+
const ids = new Set<string>();
|
|
10
|
+
for (const tour of tours) {
|
|
11
|
+
const { id } = tour;
|
|
12
|
+
if (!id || !id.trim()) throw new Error("a tour needs an id");
|
|
13
|
+
if (ids.has(id)) fail(id, "its id is used twice");
|
|
14
|
+
ids.add(id);
|
|
15
|
+
if (!tour.route.startsWith("/")) fail(id, `route "${tour.route}" is not a route id`);
|
|
16
|
+
const version = tour.version ?? 1;
|
|
17
|
+
if (!Number.isInteger(version) || version < 1) fail(id, "version is a whole number from 1");
|
|
18
|
+
if (tour.kind === "intro") {
|
|
19
|
+
if (!tour.title || !tour.body) fail(id, "an intro needs a title and a body");
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (tour.steps.length < 1 || tour.steps.length > MAX_STEPS) {
|
|
23
|
+
fail(id, `has ${tour.steps.length} steps, and a tour takes 1 to ${MAX_STEPS}`);
|
|
24
|
+
}
|
|
25
|
+
tour.steps.forEach((step, i) => {
|
|
26
|
+
if (!step.target.trim()) fail(id, `step ${i + 1} has no target`);
|
|
27
|
+
if (!step.title || !step.body) fail(id, `step ${i + 1} needs a title and a body`);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return tours;
|
|
31
31
|
}
|