@tulipfarm/sprout 0.3.0 → 0.4.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/README.md +45 -40
- package/dist/components/accordion.d.ts +2 -2
- package/dist/components/accordion.js +9 -9
- package/dist/components/agent-fanout.d.ts +2 -2
- package/dist/components/agent-fanout.js +65 -87
- package/dist/components/alert-dialog.d.ts +6 -6
- package/dist/components/alert-dialog.js +20 -20
- package/dist/components/alert.d.ts +6 -6
- package/dist/components/alert.js +13 -13
- package/dist/components/aspect-ratio.d.ts +2 -2
- package/dist/components/aspect-ratio.js +2 -2
- package/dist/components/attachment.d.ts +17 -17
- package/dist/components/attachment.js +82 -115
- package/dist/components/avatar.d.ts +10 -10
- package/dist/components/avatar.js +14 -14
- package/dist/components/badge.d.ts +4 -4
- package/dist/components/badge.js +18 -18
- package/dist/components/board.d.ts +107 -0
- package/dist/components/board.js +640 -0
- package/dist/components/brand-icon.d.ts +6 -6
- package/dist/components/brand-icon.js +55 -63
- package/dist/components/breadcrumb.d.ts +11 -11
- package/dist/components/breadcrumb.js +16 -18
- package/dist/components/button-group.d.ts +6 -6
- package/dist/components/button-group.js +14 -14
- package/dist/components/button.d.ts +11 -11
- package/dist/components/button.js +46 -56
- package/dist/components/calendar.d.ts +5 -5
- package/dist/components/calendar.js +44 -53
- package/dist/components/canvas.d.ts +4 -4
- package/dist/components/canvas.js +39 -46
- package/dist/components/card.d.ts +6 -6
- package/dist/components/card.js +17 -17
- package/dist/components/carousel.d.ts +7 -7
- package/dist/components/carousel.js +57 -75
- package/dist/components/chart.d.ts +5 -112
- package/dist/components/chart.js +5 -172
- package/dist/components/chat-confirmation.d.ts +13 -11
- package/dist/components/chat-confirmation.js +32 -38
- package/dist/components/chat-input.d.ts +4 -4
- package/dist/components/chat-input.js +74 -81
- package/dist/components/chat-plan.d.ts +2 -2
- package/dist/components/chat-plan.js +15 -20
- package/dist/components/chat-sources.d.ts +8 -8
- package/dist/components/chat-sources.js +18 -27
- package/dist/components/checkbox.d.ts +1 -1
- package/dist/components/checkbox.js +9 -9
- package/dist/components/choice-list.d.ts +2 -2
- package/dist/components/choice-list.js +16 -18
- package/dist/components/code-block.d.ts +5 -5
- package/dist/components/code-block.js +26 -26
- package/dist/components/collapsible.d.ts +1 -1
- package/dist/components/collapsible.js +7 -11
- package/dist/components/combobox.d.ts +3 -3
- package/dist/components/combobox.js +24 -24
- package/dist/components/command.d.ts +13 -13
- package/dist/components/command.js +61 -73
- package/dist/components/context-menu.d.ts +5 -5
- package/dist/components/context-menu.js +22 -22
- package/dist/components/dialog.d.ts +6 -6
- package/dist/components/dialog.js +23 -28
- package/dist/components/direction.d.ts +1 -1
- package/dist/components/direction.js +1 -1
- package/dist/components/dropdown-menu.d.ts +5 -5
- package/dist/components/dropdown-menu.js +20 -20
- package/dist/components/field.d.ts +11 -11
- package/dist/components/field.js +41 -61
- package/dist/components/file-explorer.d.ts +2 -2
- package/dist/components/file-explorer.js +89 -105
- package/dist/components/file-viewer.d.ts +10 -10
- package/dist/components/file-viewer.js +112 -140
- package/dist/components/form.d.ts +7 -7
- package/dist/components/form.js +24 -28
- package/dist/components/glass-banner.d.ts +3 -3
- package/dist/components/glass-banner.js +21 -24
- package/dist/components/gradient-banner.d.ts +5 -5
- package/dist/components/gradient-banner.js +13 -22
- package/dist/components/hover-card.d.ts +4 -4
- package/dist/components/hover-card.js +6 -6
- package/dist/components/input-group.d.ts +11 -11
- package/dist/components/input-group.js +22 -36
- package/dist/components/input-otp.d.ts +10 -10
- package/dist/components/input-otp.js +13 -15
- package/dist/components/input.d.ts +1 -1
- package/dist/components/input.js +7 -7
- package/dist/components/kbd.d.ts +3 -3
- package/dist/components/kbd.js +5 -5
- package/dist/components/label.d.ts +2 -2
- package/dist/components/label.js +2 -2
- package/dist/components/mention-list.d.ts +3 -3
- package/dist/components/mention-list.js +10 -10
- package/dist/components/menubar.d.ts +6 -6
- package/dist/components/menubar.js +22 -22
- package/dist/components/message-actions.d.ts +2 -2
- package/dist/components/message-actions.js +29 -31
- package/dist/components/message-response.d.ts +3 -3
- package/dist/components/message-response.js +18 -18
- package/dist/components/message-scroller.d.ts +12 -12
- package/dist/components/message-scroller.js +44 -56
- package/dist/components/message.d.ts +11 -11
- package/dist/components/message.js +25 -25
- package/dist/components/navigation-menu.d.ts +2 -2
- package/dist/components/navigation-menu.js +15 -15
- package/dist/components/notice-banner.d.ts +2 -2
- package/dist/components/notice-banner.js +2 -2
- package/dist/components/page-content.d.ts +2 -2
- package/dist/components/page-content.js +2 -2
- package/dist/components/page-header.d.ts +1 -1
- package/dist/components/page-header.js +16 -16
- package/dist/components/pagination.d.ts +9 -9
- package/dist/components/pagination.js +17 -17
- package/dist/components/plan-outline.d.ts +2 -2
- package/dist/components/plan-outline.js +43 -60
- package/dist/components/popover.d.ts +6 -6
- package/dist/components/popover.js +15 -15
- package/dist/components/presence-cursor.d.ts +2 -2
- package/dist/components/presence-cursor.js +3 -3
- package/dist/components/progress.d.ts +1 -1
- package/dist/components/progress.js +8 -8
- package/dist/components/prompt-list.d.ts +3 -3
- package/dist/components/prompt-list.js +6 -6
- package/dist/components/questionnaire.d.ts +19 -19
- package/dist/components/questionnaire.js +183 -242
- package/dist/components/radio-group.d.ts +2 -2
- package/dist/components/radio-group.js +6 -6
- package/dist/components/reasoning-effort.d.ts +3 -3
- package/dist/components/reasoning-effort.js +9 -12
- package/dist/components/record-list.d.ts +66 -0
- package/dist/components/record-list.js +151 -0
- package/dist/components/resizable.d.ts +5 -5
- package/dist/components/resizable.js +76 -102
- package/dist/components/result-card.d.ts +10 -5
- package/dist/components/result-card.js +42 -53
- package/dist/components/result-notice.d.ts +18 -0
- package/dist/components/result-notice.js +29 -0
- package/dist/components/review-card.d.ts +6 -6
- package/dist/components/review-card.js +18 -18
- package/dist/components/rich-text-editor.d.ts +2 -2
- package/dist/components/rich-text-editor.js +56 -72
- package/dist/components/schema-diagram.d.ts +3 -3
- package/dist/components/schema-diagram.js +39 -53
- package/dist/components/scroll-area.d.ts +1 -1
- package/dist/components/scroll-area.js +10 -14
- package/dist/components/search-dialog.d.ts +6 -6
- package/dist/components/search-dialog.js +16 -16
- package/dist/components/search-field.d.ts +1 -1
- package/dist/components/search-field.js +11 -11
- package/dist/components/select.d.ts +3 -3
- package/dist/components/select.js +20 -20
- package/dist/components/selection-slot.d.ts +2 -2
- package/dist/components/selection-slot.js +6 -9
- package/dist/components/separator.d.ts +15 -15
- package/dist/components/separator.js +22 -27
- package/dist/components/settings-list.d.ts +3 -3
- package/dist/components/settings-list.js +5 -5
- package/dist/components/sheet.d.ts +6 -6
- package/dist/components/sheet.js +27 -27
- package/dist/components/sidebar.d.ts +22 -22
- package/dist/components/sidebar.js +57 -58
- package/dist/components/skeleton.d.ts +5 -5
- package/dist/components/skeleton.js +14 -21
- package/dist/components/slider.d.ts +2 -2
- package/dist/components/slider.js +6 -6
- package/dist/components/spinner.d.ts +5 -5
- package/dist/components/spinner.js +22 -26
- package/dist/components/sql-viewer.d.ts +14 -14
- package/dist/components/sql-viewer.js +99 -128
- package/dist/components/state-panel-samples.d.ts +2 -2
- package/dist/components/state-panel-samples.js +209 -245
- package/dist/components/state-panel.d.ts +2 -35
- package/dist/components/state-panel.js +2 -29
- package/dist/components/state-sample.d.ts +7 -7
- package/dist/components/state-sample.js +18 -31
- package/dist/components/switch.d.ts +1 -1
- package/dist/components/switch.js +7 -7
- package/dist/components/table-nuqs.d.ts +2 -2
- package/dist/components/table-nuqs.js +11 -12
- package/dist/components/table.d.ts +4 -4
- package/dist/components/table.js +166 -235
- package/dist/components/tabs.d.ts +2 -2
- package/dist/components/tabs.js +12 -12
- package/dist/components/textarea.d.ts +2 -2
- package/dist/components/textarea.js +6 -8
- package/dist/components/timeline.d.ts +3 -0
- package/dist/components/timeline.js +3 -0
- package/dist/components/toast.d.ts +2 -2
- package/dist/components/toast.js +19 -25
- package/dist/components/toggle-group.d.ts +2 -2
- package/dist/components/toggle-group.js +18 -20
- package/dist/components/toggle.d.ts +2 -2
- package/dist/components/toggle.js +8 -8
- package/dist/components/tool-activity.d.ts +1 -1
- package/dist/components/tool-activity.js +83 -110
- package/dist/components/toolbar-status.d.ts +2 -2
- package/dist/components/toolbar-status.js +7 -7
- package/dist/components/tooltip.d.ts +5 -5
- package/dist/components/tooltip.js +12 -11
- package/dist/components/typed-text.d.ts +2 -2
- package/dist/components/typed-text.js +10 -12
- package/dist/components/view-switcher.d.ts +51 -0
- package/dist/components/view-switcher.js +114 -0
- package/dist/index.d.ts +98 -93
- package/dist/index.js +98 -93
- package/dist/internal/chart-kit.d.ts +142 -0
- package/dist/internal/chart-kit.js +200 -0
- package/dist/internal/charts/bars.d.ts +61 -0
- package/dist/internal/charts/bars.js +86 -0
- package/dist/internal/charts/lines.d.ts +67 -0
- package/dist/internal/charts/lines.js +70 -0
- package/dist/internal/charts/more.d.ts +77 -0
- package/dist/internal/charts/more.js +68 -0
- package/dist/internal/charts/parts.d.ts +54 -0
- package/dist/internal/charts/parts.js +82 -0
- package/dist/internal/charts/timeline-dates.d.ts +38 -0
- package/dist/internal/charts/timeline-dates.js +113 -0
- package/dist/internal/charts/timeline-window.d.ts +31 -0
- package/dist/internal/charts/timeline-window.js +26 -0
- package/dist/internal/charts/timeline.d.ts +72 -0
- package/dist/internal/charts/timeline.js +287 -0
- package/dist/internal/classes.d.ts +1 -1
- package/dist/internal/classes.js +7 -9
- package/dist/internal/code-tokens.d.ts +2 -2
- package/dist/internal/code-tokens.js +12 -12
- package/dist/internal/fieldset.d.ts +1 -1
- package/dist/internal/fieldset.js +6 -6
- package/dist/internal/file-kind.d.ts +1 -1
- package/dist/internal/file-kind.js +43 -51
- package/dist/internal/flow.d.ts +4 -4
- package/dist/internal/flow.js +20 -23
- package/dist/internal/languages.js +999 -999
- package/dist/internal/message-scroller.d.ts +3 -3
- package/dist/internal/message-scroller.js +64 -112
- package/dist/internal/pressable.d.ts +1 -1
- package/dist/internal/pressable.js +7 -7
- package/dist/internal/state-panel.d.ts +35 -0
- package/dist/internal/state-panel.js +22 -0
- package/dist/internal/syntax.d.ts +2 -2
- package/dist/internal/syntax.js +36 -47
- package/dist/styles/accordion.css +3 -5
- package/dist/styles/agent-fanout.css +64 -60
- package/dist/styles/alert-dialog.css +12 -26
- package/dist/styles/alert.css +10 -15
- package/dist/styles/attachment.css +51 -93
- package/dist/styles/avatar.css +17 -24
- package/dist/styles/badge.css +11 -36
- package/dist/styles/board.css +571 -0
- package/dist/styles/brand-icon.css +7 -8
- package/dist/styles/breadcrumb.css +4 -7
- package/dist/styles/button-group.css +8 -14
- package/dist/styles/button.css +22 -27
- package/dist/styles/calendar.css +24 -36
- package/dist/styles/canvas.css +2 -3
- package/dist/styles/card.css +7 -23
- package/dist/styles/carousel.css +11 -12
- package/dist/styles/chart.css +215 -31
- package/dist/styles/chat-input.css +15 -39
- package/dist/styles/chat-plan.css +3 -4
- package/dist/styles/chat-sources.css +3 -6
- package/dist/styles/checkbox.css +11 -25
- package/dist/styles/choice-list.css +17 -31
- package/dist/styles/code-block.css +11 -25
- package/dist/styles/collapsible.css +10 -15
- package/dist/styles/combobox.css +11 -15
- package/dist/styles/command.css +5 -8
- package/dist/styles/context-menu.css +2 -2
- package/dist/styles/dialog.css +5 -16
- package/dist/styles/dropdown-menu.css +2 -2
- package/dist/styles/field.css +15 -21
- package/dist/styles/file-explorer.css +19 -33
- package/dist/styles/file-viewer.css +13 -17
- package/dist/styles/form.css +3 -3
- package/dist/styles/glass-banner.css +12 -47
- package/dist/styles/gradient-banner.css +17 -35
- package/dist/styles/hover-card.css +9 -15
- package/dist/styles/index.css +116 -108
- package/dist/styles/input-group.css +25 -41
- package/dist/styles/input-otp.css +5 -6
- package/dist/styles/input.css +5 -5
- package/dist/styles/kbd.css +1 -1
- package/dist/styles/label.css +9 -30
- package/dist/styles/mention-list.css +6 -8
- package/dist/styles/menubar.css +5 -6
- package/dist/styles/message-actions.css +1 -1
- package/dist/styles/message-response.css +3 -5
- package/dist/styles/message-scroller.css +14 -21
- package/dist/styles/message.css +23 -60
- package/dist/styles/navigation-menu.css +14 -29
- package/dist/styles/notice-banner.css +1 -2
- package/dist/styles/page-header.css +7 -10
- package/dist/styles/pagination.css +1 -4
- package/dist/styles/plan-outline.css +20 -37
- package/dist/styles/popover.css +10 -19
- package/dist/styles/presence-cursor.css +1 -2
- package/dist/styles/progress.css +2 -4
- package/dist/styles/prompt-list.css +6 -17
- package/dist/styles/questionnaire.css +16 -40
- package/dist/styles/radio-group.css +12 -23
- package/dist/styles/reasoning-effort.css +8 -15
- package/dist/styles/record-list.css +243 -0
- package/dist/styles/resizable.css +10 -11
- package/dist/styles/result-card.css +17 -3
- package/dist/styles/result-notice.css +80 -0
- package/dist/styles/review-card.css +2 -3
- package/dist/styles/rich-text-editor.css +1 -2
- package/dist/styles/schema-diagram.css +12 -17
- package/dist/styles/scroll-area.css +8 -10
- package/dist/styles/search-dialog.css +1 -5
- package/dist/styles/search-field.css +1 -2
- package/dist/styles/select.css +7 -7
- package/dist/styles/selection-slot.css +1 -2
- package/dist/styles/separator.css +7 -8
- package/dist/styles/settings-list.css +1 -2
- package/dist/styles/sheet.css +40 -73
- package/dist/styles/sidebar.css +17 -21
- package/dist/styles/skeleton.css +9 -11
- package/dist/styles/slider.css +11 -21
- package/dist/styles/spinner.css +2 -2
- package/dist/styles/sql-viewer.css +29 -29
- package/dist/styles/state-panel.css +8 -9
- package/dist/styles/state-sample.css +20 -33
- package/dist/styles/switch.css +11 -18
- package/dist/styles/table.css +51 -77
- package/dist/styles/tabs.css +12 -16
- package/dist/styles/textarea.css +3 -3
- package/dist/styles/themes/chatgpt.css +11 -23
- package/dist/styles/themes/claude.css +12 -24
- package/dist/styles/themes/cloudflare.css +11 -23
- package/dist/styles/themes/discord.css +11 -23
- package/dist/styles/themes/github.css +11 -23
- package/dist/styles/themes/grok.css +11 -23
- package/dist/styles/themes/linear.css +12 -25
- package/dist/styles/themes/neutral.css +11 -23
- package/dist/styles/themes/notion.css +11 -23
- package/dist/styles/themes/perplexity.css +11 -23
- package/dist/styles/themes/raycast.css +11 -23
- package/dist/styles/themes/spotify.css +11 -23
- package/dist/styles/themes/stripe.css +11 -23
- package/dist/styles/themes/supabase.css +11 -23
- package/dist/styles/themes/tulipfarm.css +9 -10
- package/dist/styles/themes/vercel.css +12 -25
- package/dist/styles/timeline.css +276 -0
- package/dist/styles/toast.css +13 -20
- package/dist/styles/toggle-group.css +17 -23
- package/dist/styles/toggle.css +8 -8
- package/dist/styles/tool-activity.css +7 -13
- package/dist/styles/toolbar-status.css +2 -7
- package/dist/styles/tooltip.css +15 -21
- package/dist/styles/view-switcher.css +279 -0
- package/package.json +21 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export type MessageScrollerDefaultScrollPosition =
|
|
2
|
-
export type MessageScrollerScrollAlign =
|
|
1
|
+
export type MessageScrollerDefaultScrollPosition = 'start' | 'end' | 'last-anchor';
|
|
2
|
+
export type MessageScrollerScrollAlign = 'start' | 'center' | 'end' | 'nearest';
|
|
3
3
|
export interface MessageScrollerScrollOptions {
|
|
4
4
|
align?: MessageScrollerScrollAlign | undefined;
|
|
5
5
|
behavior?: ScrollBehavior | undefined;
|
|
@@ -64,7 +64,7 @@ export declare class MessageScrollerController {
|
|
|
64
64
|
setContent: (element: HTMLElement | null) => void;
|
|
65
65
|
setSpacer: (element: HTMLElement | null) => void;
|
|
66
66
|
registerMessage: (messageId: string, element: HTMLElement | null, previous: HTMLElement | null) => void;
|
|
67
|
-
scrollToStart: ({ behavior
|
|
67
|
+
scrollToStart: ({ behavior }?: MessageScrollerScrollOptions) => boolean;
|
|
68
68
|
scrollToEnd: ({ behavior }?: MessageScrollerScrollOptions) => boolean;
|
|
69
69
|
scrollToMessage: (messageId: string, options?: MessageScrollerScrollOptions) => boolean;
|
|
70
70
|
userScrollIntent: () => void;
|
|
@@ -3,15 +3,7 @@
|
|
|
3
3
|
// prepended, and reports which edges can still be scrolled to.
|
|
4
4
|
const epsilon = 0.5;
|
|
5
5
|
const autoscrollMs = 180;
|
|
6
|
-
export const scrollIntentKeys = new Set([
|
|
7
|
-
"ArrowDown",
|
|
8
|
-
"ArrowUp",
|
|
9
|
-
"End",
|
|
10
|
-
"Home",
|
|
11
|
-
"PageDown",
|
|
12
|
-
"PageUp",
|
|
13
|
-
" ",
|
|
14
|
-
]);
|
|
6
|
+
export const scrollIntentKeys = new Set(['ArrowDown', 'ArrowUp', 'End', 'Home', 'PageDown', 'PageUp', ' ']);
|
|
15
7
|
const noEdges = { start: false, end: false };
|
|
16
8
|
const noVisibility = {
|
|
17
9
|
currentAnchorId: null,
|
|
@@ -23,11 +15,11 @@ function createStore(initial, equal) {
|
|
|
23
15
|
return {
|
|
24
16
|
getSnapshot: () => value,
|
|
25
17
|
hasListeners: () => listeners.size > 0,
|
|
26
|
-
setSnapshot:
|
|
18
|
+
setSnapshot: next => {
|
|
27
19
|
if (equal(value, next))
|
|
28
20
|
return;
|
|
29
21
|
value = next;
|
|
30
|
-
listeners.forEach(
|
|
22
|
+
listeners.forEach(listener => listener());
|
|
31
23
|
},
|
|
32
24
|
subscribe: (listener, onFirst, onLast) => {
|
|
33
25
|
const first = listeners.size === 0;
|
|
@@ -47,7 +39,7 @@ const sameVisibility = (a, b) => a.currentAnchorId === b.currentAnchorId &&
|
|
|
47
39
|
a.visibleMessageIds.length === b.visibleMessageIds.length &&
|
|
48
40
|
a.visibleMessageIds.every((id, index) => id === b.visibleMessageIds[index]);
|
|
49
41
|
const pixels = (value) => {
|
|
50
|
-
const number = Number.parseFloat(value ??
|
|
42
|
+
const number = Number.parseFloat(value ?? '');
|
|
51
43
|
return Number.isFinite(number) ? number : 0;
|
|
52
44
|
};
|
|
53
45
|
function blockPadding(element) {
|
|
@@ -63,15 +55,13 @@ function rowGap(element) {
|
|
|
63
55
|
if (!element)
|
|
64
56
|
return 0;
|
|
65
57
|
const style = getComputedStyle(element);
|
|
66
|
-
return pixels(style.rowGap ===
|
|
58
|
+
return pixels(style.rowGap === 'normal' ? style.gap : style.rowGap);
|
|
67
59
|
}
|
|
68
|
-
const isAnchor = (element) => element?.dataset.scrollAnchor ===
|
|
60
|
+
const isAnchor = (element) => element?.dataset.scrollAnchor === 'true';
|
|
69
61
|
function itemsOf(content, spacer) {
|
|
70
62
|
return Array.from(content.children).filter((child) => child instanceof HTMLElement && child !== spacer);
|
|
71
63
|
}
|
|
72
|
-
const offsetIn = (element, viewport) => element.getBoundingClientRect().top -
|
|
73
|
-
viewport.getBoundingClientRect().top +
|
|
74
|
-
viewport.scrollTop;
|
|
64
|
+
const offsetIn = (element, viewport) => element.getBoundingClientRect().top - viewport.getBoundingClientRect().top + viewport.scrollTop;
|
|
75
65
|
const topIn = (element, viewport) => element.getBoundingClientRect().top - viewport.getBoundingClientRect().top;
|
|
76
66
|
const maxScroll = (viewport) => Math.max(0, viewport.scrollHeight - viewport.clientHeight);
|
|
77
67
|
function contentHeight(content, spacer, viewport) {
|
|
@@ -79,10 +69,7 @@ function contentHeight(content, spacer, viewport) {
|
|
|
79
69
|
const viewportTop = viewport.getBoundingClientRect().top;
|
|
80
70
|
let height = padding.start + padding.end;
|
|
81
71
|
for (const item of itemsOf(content, spacer))
|
|
82
|
-
height = Math.max(height, item.getBoundingClientRect().bottom -
|
|
83
|
-
viewportTop +
|
|
84
|
-
viewport.scrollTop +
|
|
85
|
-
padding.end);
|
|
72
|
+
height = Math.max(height, item.getBoundingClientRect().bottom - viewportTop + viewport.scrollTop + padding.end);
|
|
86
73
|
return height;
|
|
87
74
|
}
|
|
88
75
|
export class MessageScrollerController {
|
|
@@ -116,9 +103,8 @@ export class MessageScrollerController {
|
|
|
116
103
|
pendingFrame = null;
|
|
117
104
|
constructor(options) {
|
|
118
105
|
this.options = options;
|
|
119
|
-
this.mode = options.autoScroll ?
|
|
120
|
-
this.pendingDefaultStore = createStore(options.defaultScrollPosition ===
|
|
121
|
-
options.defaultScrollPosition === "last-anchor", Object.is);
|
|
106
|
+
this.mode = options.autoScroll ? 'following-bottom' : 'free-scrolling';
|
|
107
|
+
this.pendingDefaultStore = createStore(options.defaultScrollPosition === 'end' || options.defaultScrollPosition === 'last-anchor', Object.is);
|
|
122
108
|
}
|
|
123
109
|
setOptions(next) {
|
|
124
110
|
if (next.defaultScrollPosition !== this.options.defaultScrollPosition)
|
|
@@ -161,23 +147,23 @@ export class MessageScrollerController {
|
|
|
161
147
|
}
|
|
162
148
|
};
|
|
163
149
|
// Public scrolling
|
|
164
|
-
scrollToStart = ({ behavior =
|
|
150
|
+
scrollToStart = ({ behavior = 'auto' } = {}) => {
|
|
165
151
|
if (!this.viewport)
|
|
166
152
|
return false;
|
|
167
153
|
this.setSpacerHeight(0);
|
|
168
154
|
this.streamingTurn = null;
|
|
169
|
-
this.mode =
|
|
155
|
+
this.mode = 'free-scrolling';
|
|
170
156
|
this.scrollViewportTo(0, { behavior });
|
|
171
157
|
this.scheduleVisibility();
|
|
172
158
|
return true;
|
|
173
159
|
};
|
|
174
|
-
scrollToEnd = ({ behavior =
|
|
160
|
+
scrollToEnd = ({ behavior = 'auto' } = {}) => {
|
|
175
161
|
const viewport = this.viewport;
|
|
176
162
|
if (!viewport)
|
|
177
163
|
return false;
|
|
178
164
|
this.setSpacerHeight(0);
|
|
179
165
|
this.streamingTurn = null;
|
|
180
|
-
this.mode = this.options.autoScroll ?
|
|
166
|
+
this.mode = this.options.autoScroll ? 'following-bottom' : 'free-scrolling';
|
|
181
167
|
this.scrollViewportTo(maxScroll(viewport), {
|
|
182
168
|
autoscrolling: true,
|
|
183
169
|
behavior,
|
|
@@ -189,9 +175,7 @@ export class MessageScrollerController {
|
|
|
189
175
|
const element = this.messages.get(messageId);
|
|
190
176
|
if (element) {
|
|
191
177
|
this.markDefaultApplied();
|
|
192
|
-
this.pendingMessage = this.scrollToElement(element, options)
|
|
193
|
-
? null
|
|
194
|
-
: { messageId, options };
|
|
178
|
+
this.pendingMessage = this.scrollToElement(element, options) ? null : { messageId, options };
|
|
195
179
|
return true;
|
|
196
180
|
}
|
|
197
181
|
if (this.itemCount === 0) {
|
|
@@ -203,9 +187,9 @@ export class MessageScrollerController {
|
|
|
203
187
|
};
|
|
204
188
|
// Events from the parts
|
|
205
189
|
userScrollIntent = () => {
|
|
206
|
-
if (this.mode !==
|
|
190
|
+
if (this.mode !== 'free-scrolling') {
|
|
207
191
|
this.streamingTurn = null;
|
|
208
|
-
this.mode =
|
|
192
|
+
this.mode = 'free-scrolling';
|
|
209
193
|
}
|
|
210
194
|
};
|
|
211
195
|
syncAfterScroll = () => {
|
|
@@ -214,15 +198,13 @@ export class MessageScrollerController {
|
|
|
214
198
|
this.captureFirstVisible();
|
|
215
199
|
};
|
|
216
200
|
handleResize = () => {
|
|
217
|
-
if (this.mode ===
|
|
201
|
+
if (this.mode === 'following-bottom' && this.options.autoScroll) {
|
|
218
202
|
this.scrollToEnd();
|
|
219
203
|
return;
|
|
220
204
|
}
|
|
221
205
|
const previousSpacer = this.spacerHeight;
|
|
222
206
|
if (this.reanchor()) {
|
|
223
|
-
if (this.options.autoScroll &&
|
|
224
|
-
previousSpacer > 0 &&
|
|
225
|
-
this.spacerHeight === 0)
|
|
207
|
+
if (this.options.autoScroll && previousSpacer > 0 && this.spacerHeight === 0)
|
|
226
208
|
this.scrollToEnd();
|
|
227
209
|
return;
|
|
228
210
|
}
|
|
@@ -247,9 +229,7 @@ export class MessageScrollerController {
|
|
|
247
229
|
this.pendingDefaultStore.setSnapshot(false);
|
|
248
230
|
};
|
|
249
231
|
followOnAutoScroll = () => {
|
|
250
|
-
if (this.options.autoScroll &&
|
|
251
|
-
this.mode === "following-bottom" &&
|
|
252
|
-
this.itemCount > 0) {
|
|
232
|
+
if (this.options.autoScroll && this.mode === 'following-bottom' && this.itemCount > 0) {
|
|
253
233
|
this.scrollToEnd();
|
|
254
234
|
return;
|
|
255
235
|
}
|
|
@@ -258,13 +238,13 @@ export class MessageScrollerController {
|
|
|
258
238
|
observeVisibility = () => {
|
|
259
239
|
if (!this.viewport || !this.visibilityStore.hasListeners())
|
|
260
240
|
return;
|
|
261
|
-
if (typeof IntersectionObserver ===
|
|
241
|
+
if (typeof IntersectionObserver === 'undefined') {
|
|
262
242
|
this.scheduleVisibility();
|
|
263
243
|
return;
|
|
264
244
|
}
|
|
265
245
|
if (!this.observer) {
|
|
266
246
|
const inset = this.options.scrollMargin + this.options.scrollPreviousItemPeek;
|
|
267
|
-
this.observer = new IntersectionObserver(
|
|
247
|
+
this.observer = new IntersectionObserver(entries => {
|
|
268
248
|
for (const entry of entries) {
|
|
269
249
|
const id = entry.target.dataset.messageId;
|
|
270
250
|
if (!id)
|
|
@@ -281,7 +261,7 @@ export class MessageScrollerController {
|
|
|
281
261
|
threshold: [0, 0.01, 0.5, 1],
|
|
282
262
|
});
|
|
283
263
|
}
|
|
284
|
-
this.messages.forEach(
|
|
264
|
+
this.messages.forEach(element => this.observer?.observe(element));
|
|
285
265
|
this.scheduleVisibility();
|
|
286
266
|
};
|
|
287
267
|
unobserveVisibility = () => {
|
|
@@ -294,11 +274,7 @@ export class MessageScrollerController {
|
|
|
294
274
|
this.visibilityStore.setSnapshot(noVisibility);
|
|
295
275
|
};
|
|
296
276
|
dispose = () => {
|
|
297
|
-
for (const frame of [
|
|
298
|
-
this.stateFrame,
|
|
299
|
-
this.visibilityFrame,
|
|
300
|
-
this.pendingFrame,
|
|
301
|
-
])
|
|
277
|
+
for (const frame of [this.stateFrame, this.visibilityFrame, this.pendingFrame])
|
|
302
278
|
if (frame !== null)
|
|
303
279
|
cancelAnimationFrame(frame);
|
|
304
280
|
this.stateFrame = this.visibilityFrame = this.pendingFrame = null;
|
|
@@ -317,8 +293,7 @@ export class MessageScrollerController {
|
|
|
317
293
|
if (this.flushPendingMessage())
|
|
318
294
|
return;
|
|
319
295
|
if (previousCount === 0) {
|
|
320
|
-
if (this.applyDefault() ||
|
|
321
|
-
(items.length > 0 && this.options.autoScroll && this.scrollToEnd()))
|
|
296
|
+
if (this.applyDefault() || (items.length > 0 && this.options.autoScroll && this.scrollToEnd()))
|
|
322
297
|
return;
|
|
323
298
|
this.commit();
|
|
324
299
|
this.scheduleVisibility();
|
|
@@ -330,11 +305,10 @@ export class MessageScrollerController {
|
|
|
330
305
|
return;
|
|
331
306
|
}
|
|
332
307
|
if (items.length > previousCount) {
|
|
333
|
-
const anchor = items.slice(previousCount).find(
|
|
308
|
+
const anchor = items.slice(previousCount).find(item => isAnchor(item));
|
|
334
309
|
if (anchor) {
|
|
335
|
-
const following = this.options.autoScroll && this.mode ===
|
|
336
|
-
if (following &&
|
|
337
|
-
items.slice(previousCount).filter((item) => isAnchor(item)).length > 1) {
|
|
310
|
+
const following = this.options.autoScroll && this.mode === 'following-bottom';
|
|
311
|
+
if (following && items.slice(previousCount).filter(item => isAnchor(item)).length > 1) {
|
|
338
312
|
this.scrollToEnd();
|
|
339
313
|
return;
|
|
340
314
|
}
|
|
@@ -343,13 +317,13 @@ export class MessageScrollerController {
|
|
|
343
317
|
}
|
|
344
318
|
}
|
|
345
319
|
if (items.length === previousCount) {
|
|
346
|
-
const anchor = items.find(
|
|
320
|
+
const anchor = items.find(item => isAnchor(item) && !this.handledAnchors.has(item));
|
|
347
321
|
if (anchor) {
|
|
348
322
|
this.pinAnchor(anchor);
|
|
349
323
|
return;
|
|
350
324
|
}
|
|
351
325
|
}
|
|
352
|
-
if (this.mode ===
|
|
326
|
+
if (this.mode === 'following-bottom' && this.options.autoScroll)
|
|
353
327
|
this.scrollToEnd();
|
|
354
328
|
else {
|
|
355
329
|
this.commit();
|
|
@@ -357,7 +331,7 @@ export class MessageScrollerController {
|
|
|
357
331
|
}
|
|
358
332
|
}
|
|
359
333
|
pinAnchor(anchor) {
|
|
360
|
-
this.scrollToElement(anchor, { align:
|
|
334
|
+
this.scrollToElement(anchor, { align: 'start' }, true);
|
|
361
335
|
this.handledAnchors.add(anchor);
|
|
362
336
|
}
|
|
363
337
|
applyDefault() {
|
|
@@ -365,23 +339,19 @@ export class MessageScrollerController {
|
|
|
365
339
|
if (this.defaultApplied || this.itemCount === 0)
|
|
366
340
|
return false;
|
|
367
341
|
let done = false;
|
|
368
|
-
if (position ===
|
|
342
|
+
if (position === 'last-anchor') {
|
|
369
343
|
const content = this.content;
|
|
370
344
|
const viewport = this.viewport;
|
|
371
|
-
const anchor = content && viewport
|
|
372
|
-
? itemsOf(content, this.spacer).filter(isAnchor).pop()
|
|
373
|
-
: undefined;
|
|
345
|
+
const anchor = content && viewport ? itemsOf(content, this.spacer).filter(isAnchor).pop() : undefined;
|
|
374
346
|
if (!content || !viewport || !anchor)
|
|
375
347
|
done = this.scrollToEnd();
|
|
376
348
|
else
|
|
377
|
-
done = this.measuringFrom(anchor, () => contentHeight(content, this.spacer, viewport) -
|
|
378
|
-
offsetIn(anchor, viewport) <=
|
|
379
|
-
viewport.clientHeight
|
|
349
|
+
done = this.measuringFrom(anchor, () => contentHeight(content, this.spacer, viewport) - offsetIn(anchor, viewport) <= viewport.clientHeight
|
|
380
350
|
? this.scrollToEnd()
|
|
381
|
-
: this.scrollToElement(anchor, { align:
|
|
351
|
+
: this.scrollToElement(anchor, { align: 'start' }, true));
|
|
382
352
|
}
|
|
383
353
|
else
|
|
384
|
-
done = position ===
|
|
354
|
+
done = position === 'end' ? this.scrollToEnd() : this.scrollToStart();
|
|
385
355
|
if (done)
|
|
386
356
|
this.markDefaultApplied();
|
|
387
357
|
return done;
|
|
@@ -391,15 +361,11 @@ export class MessageScrollerController {
|
|
|
391
361
|
const viewport = this.viewport;
|
|
392
362
|
if (!content || !viewport || !content.contains(element))
|
|
393
363
|
return false;
|
|
394
|
-
const { align =
|
|
395
|
-
const top = this.targetTop(element, align, keepPreviousPeek
|
|
396
|
-
|
|
397
|
-
: scrollMargin);
|
|
398
|
-
this.setSpacerHeight(top +
|
|
399
|
-
viewport.clientHeight -
|
|
400
|
-
this.measuringFrom(element, () => contentHeight(content, this.spacer, viewport)));
|
|
364
|
+
const { align = 'start', behavior = 'auto', scrollMargin = this.options.scrollMargin } = options;
|
|
365
|
+
const top = this.targetTop(element, align, keepPreviousPeek ? scrollMargin + this.options.scrollPreviousItemPeek : scrollMargin);
|
|
366
|
+
this.setSpacerHeight(top + viewport.clientHeight - this.measuringFrom(element, () => contentHeight(content, this.spacer, viewport)));
|
|
401
367
|
this.prependRestore = { element, viewportTop: topIn(element, viewport) };
|
|
402
|
-
this.mode = keepPreviousPeek ?
|
|
368
|
+
this.mode = keepPreviousPeek ? 'anchored-to-message' : 'settling-jump';
|
|
403
369
|
this.streamingTurn = keepPreviousPeek ? element : null;
|
|
404
370
|
this.scrollViewportTo(top, { behavior });
|
|
405
371
|
this.scheduleVisibility();
|
|
@@ -409,14 +375,14 @@ export class MessageScrollerController {
|
|
|
409
375
|
measuringFrom(from, measure) {
|
|
410
376
|
const items = this.content ? itemsOf(this.content, this.spacer) : [];
|
|
411
377
|
const later = items.slice(Math.max(0, items.indexOf(from)));
|
|
412
|
-
const previous = later.map(
|
|
378
|
+
const previous = later.map(item => item.style.contentVisibility);
|
|
413
379
|
for (const item of later)
|
|
414
|
-
item.style.contentVisibility =
|
|
380
|
+
item.style.contentVisibility = 'visible';
|
|
415
381
|
try {
|
|
416
382
|
return measure();
|
|
417
383
|
}
|
|
418
384
|
finally {
|
|
419
|
-
later.forEach((item, index) => (item.style.contentVisibility = previous[index] ??
|
|
385
|
+
later.forEach((item, index) => (item.style.contentVisibility = previous[index] ?? ''));
|
|
420
386
|
}
|
|
421
387
|
}
|
|
422
388
|
targetTop(element, align, margin) {
|
|
@@ -424,13 +390,13 @@ export class MessageScrollerController {
|
|
|
424
390
|
const offset = offsetIn(element, viewport);
|
|
425
391
|
const height = element.getBoundingClientRect().height;
|
|
426
392
|
const padding = blockPadding(this.spacer?.parentElement);
|
|
427
|
-
if (align ===
|
|
393
|
+
if (align === 'center') {
|
|
428
394
|
const room = Math.max(0, viewport.clientHeight - padding.start - padding.end);
|
|
429
395
|
return offset - padding.start - (room - height) / 2 - margin;
|
|
430
396
|
}
|
|
431
|
-
if (align ===
|
|
397
|
+
if (align === 'end')
|
|
432
398
|
return offset - viewport.clientHeight + height + padding.end + margin;
|
|
433
|
-
if (align ===
|
|
399
|
+
if (align === 'nearest') {
|
|
434
400
|
const top = viewport.scrollTop + padding.start;
|
|
435
401
|
const bottom = viewport.scrollTop + viewport.clientHeight - padding.end;
|
|
436
402
|
if (offset >= top && offset + height <= bottom)
|
|
@@ -443,9 +409,9 @@ export class MessageScrollerController {
|
|
|
443
409
|
}
|
|
444
410
|
reanchor() {
|
|
445
411
|
const element = this.streamingTurn;
|
|
446
|
-
if (!element || !element.isConnected || this.mode !==
|
|
412
|
+
if (!element || !element.isConnected || this.mode !== 'anchored-to-message')
|
|
447
413
|
return false;
|
|
448
|
-
return this.scrollToElement(element, { align:
|
|
414
|
+
return this.scrollToElement(element, { align: 'start' }, true);
|
|
449
415
|
}
|
|
450
416
|
flushPendingMessage() {
|
|
451
417
|
const pending = this.pendingMessage;
|
|
@@ -477,7 +443,7 @@ export class MessageScrollerController {
|
|
|
477
443
|
this.spacerHeight = height;
|
|
478
444
|
spacer.hidden = height === 0;
|
|
479
445
|
spacer.style.height = `${height}px`;
|
|
480
|
-
spacer.style.marginTop = height > 0 ? `${-this.spacerGap}px` :
|
|
446
|
+
spacer.style.marginTop = height > 0 ? `${-this.spacerGap}px` : '';
|
|
481
447
|
}
|
|
482
448
|
setAutoscrolling(on) {
|
|
483
449
|
if (this.autoscrollTimer !== null)
|
|
@@ -494,7 +460,7 @@ export class MessageScrollerController {
|
|
|
494
460
|
this.commit();
|
|
495
461
|
}, autoscrollMs);
|
|
496
462
|
}
|
|
497
|
-
scrollViewportTo(value, { behavior =
|
|
463
|
+
scrollViewportTo(value, { behavior = 'auto', autoscrolling = false } = {}) {
|
|
498
464
|
const viewport = this.viewport;
|
|
499
465
|
if (!viewport)
|
|
500
466
|
return;
|
|
@@ -531,15 +497,13 @@ export class MessageScrollerController {
|
|
|
531
497
|
return;
|
|
532
498
|
}
|
|
533
499
|
const bounds = viewport.getBoundingClientRect();
|
|
534
|
-
const first = itemsOf(content, this.spacer).find(
|
|
500
|
+
const first = itemsOf(content, this.spacer).find(item => {
|
|
535
501
|
if (!item.dataset.messageId)
|
|
536
502
|
return false;
|
|
537
503
|
const rect = item.getBoundingClientRect();
|
|
538
504
|
return rect.bottom > bounds.top && rect.top < bounds.bottom;
|
|
539
505
|
});
|
|
540
|
-
this.prependRestore = first
|
|
541
|
-
? { element: first, viewportTop: topIn(first, viewport) }
|
|
542
|
-
: null;
|
|
506
|
+
this.prependRestore = first ? { element: first, viewportTop: topIn(first, viewport) } : null;
|
|
543
507
|
}
|
|
544
508
|
readEdges() {
|
|
545
509
|
const { content, viewport } = this;
|
|
@@ -556,35 +520,27 @@ export class MessageScrollerController {
|
|
|
556
520
|
const top = this.viewport?.scrollTop ?? 0;
|
|
557
521
|
const scrolledUp = top < this.lastScrollTop - epsilon;
|
|
558
522
|
this.lastScrollTop = top;
|
|
559
|
-
if (this.options.autoScroll &&
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
this.mode
|
|
563
|
-
this.mode = "following-bottom";
|
|
564
|
-
else if (this.mode === "following-bottom" &&
|
|
565
|
-
edges.end &&
|
|
566
|
-
scrolledUp &&
|
|
567
|
-
!this.autoscrolling)
|
|
568
|
-
this.mode = "free-scrolling";
|
|
523
|
+
if (this.options.autoScroll && !edges.end && this.mode !== 'settling-jump' && this.mode !== 'anchored-to-message')
|
|
524
|
+
this.mode = 'following-bottom';
|
|
525
|
+
else if (this.mode === 'following-bottom' && edges.end && scrolledUp && !this.autoscrolling)
|
|
526
|
+
this.mode = 'free-scrolling';
|
|
569
527
|
}
|
|
570
528
|
applyAttributes(edges) {
|
|
571
|
-
const value = [edges.start &&
|
|
572
|
-
.filter(Boolean)
|
|
573
|
-
.join(" ");
|
|
529
|
+
const value = [edges.start && 'start', edges.end && 'end'].filter(Boolean).join(' ');
|
|
574
530
|
for (const element of [this.root, this.viewport]) {
|
|
575
531
|
if (!element)
|
|
576
532
|
continue;
|
|
577
533
|
if (value)
|
|
578
|
-
element.setAttribute(
|
|
534
|
+
element.setAttribute('data-scrollable', value);
|
|
579
535
|
else
|
|
580
|
-
element.removeAttribute(
|
|
581
|
-
element.toggleAttribute(
|
|
536
|
+
element.removeAttribute('data-scrollable');
|
|
537
|
+
element.toggleAttribute('data-autoscrolling', this.autoscrolling);
|
|
582
538
|
}
|
|
583
539
|
}
|
|
584
540
|
commit() {
|
|
585
541
|
const edges = this.readEdges();
|
|
586
542
|
this.updateMode(edges);
|
|
587
|
-
const shown = this.mode ===
|
|
543
|
+
const shown = this.mode === 'following-bottom' ? { ...edges, end: false } : edges;
|
|
588
544
|
this.applyAttributes(shown);
|
|
589
545
|
this.stateStore.setSnapshot(shown);
|
|
590
546
|
}
|
|
@@ -610,10 +566,8 @@ export class MessageScrollerController {
|
|
|
610
566
|
if (!content || !viewport)
|
|
611
567
|
return noVisibility;
|
|
612
568
|
const bounds = viewport.getBoundingClientRect();
|
|
613
|
-
const line = bounds.top +
|
|
614
|
-
|
|
615
|
-
this.options.scrollPreviousItemPeek;
|
|
616
|
-
const measure = typeof IntersectionObserver === "undefined";
|
|
569
|
+
const line = bounds.top + this.options.scrollMargin + this.options.scrollPreviousItemPeek;
|
|
570
|
+
const measure = typeof IntersectionObserver === 'undefined';
|
|
617
571
|
const visibleMessageIds = [];
|
|
618
572
|
let currentAnchorId = null;
|
|
619
573
|
for (const item of itemsOf(content, this.spacer)) {
|
|
@@ -622,9 +576,7 @@ export class MessageScrollerController {
|
|
|
622
576
|
continue;
|
|
623
577
|
const anchor = isAnchor(item);
|
|
624
578
|
const rect = anchor || measure ? item.getBoundingClientRect() : null;
|
|
625
|
-
const visible = measure && rect
|
|
626
|
-
? rect.bottom > line && rect.top < bounds.bottom
|
|
627
|
-
: this.visibleIds.has(id);
|
|
579
|
+
const visible = measure && rect ? rect.bottom > line && rect.top < bounds.bottom : this.visibleIds.has(id);
|
|
628
580
|
if (visible)
|
|
629
581
|
visibleMessageIds.push(id);
|
|
630
582
|
if (anchor && rect && rect.top <= line + epsilon)
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Button } from
|
|
1
|
+
import { Button } from '@base-ui/react/button';
|
|
2
2
|
export declare function Pressable({ nativeButton, render, ref, className, disabled, focusableWhenDisabled, onClick, ...props }: Button.Props): import("react").JSX.Element | null;
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { Button } from
|
|
4
|
-
import { useRender } from
|
|
3
|
+
import { Button } from '@base-ui/react/button';
|
|
4
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
5
5
|
// Base UI gives non-native renders role="button"; navigation needs real link semantics.
|
|
6
6
|
export function Pressable({ nativeButton = true, render, ref, className, disabled = false, focusableWhenDisabled = false, onClick, ...props }) {
|
|
7
7
|
const link = useRender({
|
|
8
8
|
enabled: !nativeButton,
|
|
9
|
-
defaultTagName:
|
|
9
|
+
defaultTagName: 'a',
|
|
10
10
|
render,
|
|
11
11
|
ref,
|
|
12
12
|
state: { disabled },
|
|
13
13
|
props: {
|
|
14
14
|
...props,
|
|
15
|
-
className: typeof className ===
|
|
16
|
-
|
|
15
|
+
className: typeof className === 'function' ? className({ disabled }) : className,
|
|
16
|
+
'aria-disabled': disabled || undefined,
|
|
17
17
|
tabIndex: disabled && !focusableWhenDisabled ? -1 : props.tabIndex,
|
|
18
|
-
onClick: (
|
|
18
|
+
onClick: (event => {
|
|
19
19
|
if (disabled) {
|
|
20
20
|
event.preventDefault();
|
|
21
21
|
event.stopPropagation();
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ComponentType, HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export declare const statePanelKindNames: readonly ["empty", "loading", "success", "unavailable", "error"];
|
|
3
|
+
export type StatePanelKind = (typeof statePanelKindNames)[number];
|
|
4
|
+
export type StatePanelHeading = 'h1' | 'h2' | 'h3' | 'h4';
|
|
5
|
+
export type StatePanelIcon = ComponentType<{
|
|
6
|
+
size?: number;
|
|
7
|
+
}>;
|
|
8
|
+
interface StatePanelBaseProps extends Omit<HTMLAttributes<HTMLElement>, 'title' | 'children' | 'role'> {
|
|
9
|
+
title: ReactNode;
|
|
10
|
+
description: ReactNode;
|
|
11
|
+
/** Heading element for `title`. Match the surrounding document outline. */
|
|
12
|
+
heading?: StatePanelHeading | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Icon for `empty` and `unavailable`. Pass `null` to show no icon.
|
|
15
|
+
* Other kinds use a fixed icon.
|
|
16
|
+
*/
|
|
17
|
+
icon?: StatePanelIcon | null | undefined;
|
|
18
|
+
/** Actions or guidance shown below the description. */
|
|
19
|
+
children?: ReactNode;
|
|
20
|
+
}
|
|
21
|
+
export type StatePanelProps = StatePanelBaseProps & ({
|
|
22
|
+
kind: 'empty';
|
|
23
|
+
/** Decorative preview of the filled state. Switches to the split layout. */
|
|
24
|
+
sample?: ReactNode;
|
|
25
|
+
} | {
|
|
26
|
+
kind: 'loading' | 'success' | 'unavailable';
|
|
27
|
+
sample?: never;
|
|
28
|
+
} | {
|
|
29
|
+
kind: 'error';
|
|
30
|
+
/** Errors always offer a recovery action or guidance. */
|
|
31
|
+
children: ReactNode;
|
|
32
|
+
sample?: never;
|
|
33
|
+
});
|
|
34
|
+
export declare function StatePanel({ kind, title, description, heading: Heading, icon, children, sample, className, ...props }: StatePanelProps): import("react").JSX.Element;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Check } from 'reicon-react/icons/Check';
|
|
3
|
+
import { Inbox } from 'reicon-react/icons/Inbox';
|
|
4
|
+
import { Warning } from 'reicon-react/icons/Warning';
|
|
5
|
+
import { cn } from './classes.js';
|
|
6
|
+
import { Spinner } from '../components/spinner.js';
|
|
7
|
+
export const statePanelKindNames = ['empty', 'loading', 'success', 'unavailable', 'error'];
|
|
8
|
+
const roles = {
|
|
9
|
+
error: 'alert',
|
|
10
|
+
loading: 'status',
|
|
11
|
+
success: 'status',
|
|
12
|
+
};
|
|
13
|
+
function Media({ kind, Icon }) {
|
|
14
|
+
return (_jsx("div", { "data-slot": "state-panel-media", className: "sprout-state-panel-media", "aria-hidden": "true", children: kind === 'loading' ? (_jsx(Spinner, { "aria-hidden": "true" })) : kind === 'success' ? (_jsx(Check, { size: 20 })) : kind === 'error' ? (_jsx(Warning, { size: 20, className: "sprout-state-panel-danger" })) : (_jsx(Icon, { size: 20 })) }));
|
|
15
|
+
}
|
|
16
|
+
export function StatePanel({ kind, title, description, heading: Heading = 'h2', icon = Inbox, children, sample, className, ...props }) {
|
|
17
|
+
const media = icon === null && (kind === 'empty' || kind === 'unavailable') ? null : _jsx(Media, { kind: kind, Icon: icon ?? Inbox });
|
|
18
|
+
const hasActions = children !== undefined && children !== null && children !== false;
|
|
19
|
+
if (sample)
|
|
20
|
+
return (_jsx("section", { "data-slot": "state-panel", "data-kind": kind, "data-layout": "sample", ...props, className: cn('sprout-state-panel', className), children: _jsxs("div", { className: "sprout-state-panel-card", children: [_jsxs("div", { className: "sprout-state-panel-copy", children: [media, _jsxs("div", { className: "sprout-state-panel-text", children: [_jsx(Heading, { className: "sprout-state-panel-title", children: title }), _jsx("p", { className: "sprout-state-panel-description", children: description })] }), hasActions && (_jsx("div", { "data-slot": "state-panel-actions", className: "sprout-state-panel-actions", children: children }))] }), _jsx("div", { "data-slot": "state-panel-sample", className: "sprout-state-panel-sample", "aria-hidden": "true", inert: true, children: _jsx("div", { className: "sprout-state-panel-sample-window", children: sample }) })] }) }));
|
|
21
|
+
return (_jsxs("div", { "data-slot": "state-panel", "data-kind": kind, "data-layout": "centered", ...props, className: cn('sprout-state-panel', className), children: [media, _jsxs("div", { role: roles[kind], "aria-atomic": "true", className: "sprout-state-panel-text", children: [_jsx(Heading, { className: "sprout-state-panel-title", children: title }), _jsx("p", { className: "sprout-state-panel-description", children: description })] }), hasActions && (_jsx("div", { "data-slot": "state-panel-actions", className: "sprout-state-panel-actions", children: children }))] }));
|
|
22
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ThemedToken } from
|
|
2
|
-
import { type CodeLanguage } from
|
|
1
|
+
import type { ThemedToken } from 'shiki/core';
|
|
2
|
+
import { type CodeLanguage } from './languages.js';
|
|
3
3
|
/** The Shiki language for a file name, from its whole name or its extension. */
|
|
4
4
|
export declare function languageForFilename(name: string): CodeLanguage | null;
|
|
5
5
|
/** Resolves a language name or alias, falling back to the file name. `null` means plain text. */
|