@olympusoss/canvas 2.20.1 → 4.0.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 +41 -177
- package/src/cn.ts +3 -0
- package/src/index.ts +12 -603
- package/src/theme.ts +41 -0
- package/src/tokens.ts +11 -0
- package/styles/base.css +17 -0
- package/styles/canvas.css +69 -52
- package/styles/components/alert.css +66 -0
- package/styles/components/app-shell.css +46 -0
- package/styles/components/avatar.css +15 -0
- package/styles/components/badge.css +83 -0
- package/styles/components/breadcrumb.css +35 -0
- package/styles/components/button-group.css +23 -0
- package/styles/components/button.css +107 -0
- package/styles/components/calendar.css +73 -0
- package/styles/components/card.css +58 -0
- package/styles/components/checkbox.css +55 -0
- package/styles/components/code-block.css +18 -0
- package/styles/components/combobox.css +75 -0
- package/styles/components/command.css +94 -0
- package/styles/components/data-table.css +142 -0
- package/styles/components/dialog.css +72 -0
- package/styles/components/dropdown.css +54 -0
- package/styles/components/empty-state.css +17 -0
- package/styles/components/field.css +27 -0
- package/styles/components/filter-panel.css +58 -0
- package/styles/components/form.css +27 -0
- package/styles/components/icon.css +8 -0
- package/styles/components/input-group.css +45 -0
- package/styles/components/input.css +56 -0
- package/styles/components/kbd.css +15 -0
- package/styles/components/page-header.css +52 -0
- package/styles/components/pagination.css +48 -0
- package/styles/components/popover.css +14 -0
- package/styles/components/radio.css +28 -0
- package/styles/components/row-menu.css +69 -0
- package/styles/components/section-card.css +49 -0
- package/styles/components/select.css +57 -0
- package/styles/components/separator.css +32 -0
- package/styles/components/sheet.css +70 -0
- package/styles/components/sidebar.css +146 -0
- package/styles/components/skeleton.css +32 -0
- package/styles/components/spinner.css +26 -0
- package/styles/components/stat-card.css +71 -0
- package/styles/components/stepper.css +63 -0
- package/styles/components/switch.css +45 -0
- package/styles/components/tabs.css +40 -0
- package/styles/components/textarea.css +31 -0
- package/styles/components/toast.css +95 -0
- package/styles/components/tooltip.css +53 -0
- package/styles/components/topbar.css +24 -0
- package/styles/components/typography.css +105 -0
- package/styles/patterns/backdrops.css +35 -0
- package/styles/patterns/density.css +66 -0
- package/styles/patterns/focus.css +38 -0
- package/styles/patterns/glass.css +85 -0
- package/styles/patterns/high-contrast.css +70 -0
- package/styles/patterns/reduced-motion.css +12 -0
- package/styles/patterns/scrollbar.css +10 -0
- package/styles/reset.css +89 -0
- package/styles/tokens/colors.css +106 -0
- package/styles/tokens/motion.css +33 -0
- package/styles/tokens/radius.css +10 -0
- package/styles/tokens/shadows.css +35 -0
- package/styles/tokens/spacing.css +19 -0
- package/styles/tokens/typography.css +6 -0
- package/styles/tokens/z-index.css +12 -0
- package/tsconfig.json +20 -21
- package/README.md +0 -60
- package/src/components/atoms/README.md +0 -11
- package/src/components/atoms/aspect-ratio.tsx +0 -32
- package/src/components/atoms/avatar.tsx +0 -98
- package/src/components/atoms/badge.tsx +0 -44
- package/src/components/atoms/brand-mark.tsx +0 -74
- package/src/components/atoms/button.tsx +0 -105
- package/src/components/atoms/checkbox.tsx +0 -63
- package/src/components/atoms/flex-box.tsx +0 -105
- package/src/components/atoms/icon.tsx +0 -34
- package/src/components/atoms/input.tsx +0 -92
- package/src/components/atoms/label.tsx +0 -41
- package/src/components/atoms/logo.tsx +0 -89
- package/src/components/atoms/progress.tsx +0 -55
- package/src/components/atoms/radio-group.tsx +0 -122
- package/src/components/atoms/scroll-area.tsx +0 -106
- package/src/components/atoms/section.tsx +0 -48
- package/src/components/atoms/separator.tsx +0 -45
- package/src/components/atoms/skeleton.tsx +0 -17
- package/src/components/atoms/slider.tsx +0 -93
- package/src/components/atoms/spinner.tsx +0 -47
- package/src/components/atoms/switch.tsx +0 -60
- package/src/components/atoms/textarea.tsx +0 -78
- package/src/components/atoms/toggle.tsx +0 -80
- package/src/components/charts/activity-heatmap.tsx +0 -186
- package/src/components/charts/axes.tsx +0 -21
- package/src/components/charts/chart-container.tsx +0 -254
- package/src/components/charts/chart-legend.tsx +0 -67
- package/src/components/charts/chart-tooltip.tsx +0 -161
- package/src/components/charts/chart-types.tsx +0 -49
- package/src/components/charts/containers.tsx +0 -11
- package/src/components/charts/data.tsx +0 -16
- package/src/components/charts/details.tsx +0 -25
- package/src/components/charts/dot-pulse.tsx +0 -61
- package/src/components/charts/gauge.tsx +0 -106
- package/src/components/charts/grids.tsx +0 -8
- package/src/components/charts/index.ts +0 -62
- package/src/components/charts/labeled-bar-list.tsx +0 -85
- package/src/components/charts/metric-breakdown.tsx +0 -316
- package/src/components/charts/references.tsx +0 -8
- package/src/components/charts/service-health-list.tsx +0 -85
- package/src/components/charts/sparkline-area.tsx +0 -80
- package/src/components/charts/sparkline.tsx +0 -52
- package/src/components/charts/stacked-bar.tsx +0 -104
- package/src/components/charts/text.tsx +0 -10
- package/src/components/charts/world-heat-map-inner.tsx +0 -317
- package/src/components/charts/world-heat-map.tsx +0 -184
- package/src/components/molecules/README.md +0 -12
- package/src/components/molecules/action-bar.tsx +0 -73
- package/src/components/molecules/activity-item.tsx +0 -74
- package/src/components/molecules/alert.tsx +0 -86
- package/src/components/molecules/animated-background.tsx +0 -92
- package/src/components/molecules/auth-shell.tsx +0 -95
- package/src/components/molecules/brand-lockup.tsx +0 -48
- package/src/components/molecules/breadcrumb.tsx +0 -157
- package/src/components/molecules/button-group.tsx +0 -104
- package/src/components/molecules/calendar.tsx +0 -217
- package/src/components/molecules/card.tsx +0 -102
- package/src/components/molecules/client-brand.tsx +0 -95
- package/src/components/molecules/code-block.tsx +0 -86
- package/src/components/molecules/countdown-button.tsx +0 -92
- package/src/components/molecules/empty-state.tsx +0 -56
- package/src/components/molecules/error-state.tsx +0 -42
- package/src/components/molecules/field-display.tsx +0 -35
- package/src/components/molecules/input-otp.tsx +0 -74
- package/src/components/molecules/launcher-card.tsx +0 -152
- package/src/components/molecules/loading-state.tsx +0 -36
- package/src/components/molecules/notification-item.tsx +0 -67
- package/src/components/molecules/notification-list.tsx +0 -45
- package/src/components/molecules/number-badge.tsx +0 -53
- package/src/components/molecules/or-separator.tsx +0 -38
- package/src/components/molecules/page-header.tsx +0 -88
- package/src/components/molecules/page-tabs.tsx +0 -94
- package/src/components/molecules/pagination.tsx +0 -150
- package/src/components/molecules/password-input.tsx +0 -83
- package/src/components/molecules/password-strength-meter.tsx +0 -104
- package/src/components/molecules/phone-input.tsx +0 -200
- package/src/components/molecules/search-bar.tsx +0 -64
- package/src/components/molecules/secret-field.tsx +0 -158
- package/src/components/molecules/section-card.tsx +0 -91
- package/src/components/molecules/social-buttons.tsx +0 -165
- package/src/components/molecules/stat-card.tsx +0 -100
- package/src/components/molecules/status-badge.tsx +0 -42
- package/src/components/molecules/stepper.tsx +0 -96
- package/src/components/molecules/table.tsx +0 -157
- package/src/components/molecules/terminal.tsx +0 -74
- package/src/components/molecules/toggle-group.tsx +0 -145
- package/src/components/molecules/tooltip.tsx +0 -155
- package/src/components/molecules/user-avatar-chip.tsx +0 -71
- package/src/components/organisms/README.md +0 -14
- package/src/components/organisms/accordion.tsx +0 -154
- package/src/components/organisms/alert-dialog.tsx +0 -277
- package/src/components/organisms/carousel.tsx +0 -244
- package/src/components/organisms/collapsible.tsx +0 -69
- package/src/components/organisms/command.tsx +0 -144
- package/src/components/organisms/context-menu.tsx +0 -339
- package/src/components/organisms/dashboard-grid.tsx +0 -369
- package/src/components/organisms/data-table.tsx +0 -330
- package/src/components/organisms/dialog.tsx +0 -312
- package/src/components/organisms/drawer.tsx +0 -123
- package/src/components/organisms/dropdown-menu.tsx +0 -440
- package/src/components/organisms/editors/code-editor.tsx +0 -144
- package/src/components/organisms/editors/index.ts +0 -4
- package/src/components/organisms/editors/markdown-editor.tsx +0 -153
- package/src/components/organisms/editors/markdown-renderer.ts +0 -27
- package/src/components/organisms/editors/prose-canvas-classes.ts +0 -45
- package/src/components/organisms/editors/rich-text-editor.tsx +0 -126
- package/src/components/organisms/editors/toolbar/md-toolbar.tsx +0 -129
- package/src/components/organisms/editors/toolbar/rte-toolbar.tsx +0 -211
- package/src/components/organisms/editors/toolbar/toolbar-shell.tsx +0 -45
- package/src/components/organisms/editors/use-codemirror-theme.ts +0 -61
- package/src/components/organisms/error-boundary.tsx +0 -61
- package/src/components/organisms/form.tsx +0 -174
- package/src/components/organisms/hover-card.tsx +0 -115
- package/src/components/organisms/menubar.tsx +0 -498
- package/src/components/organisms/navbar.tsx +0 -104
- package/src/components/organisms/navigation-menu.tsx +0 -235
- package/src/components/organisms/popover.tsx +0 -149
- package/src/components/organisms/resizable.tsx +0 -58
- package/src/components/organisms/schema-form.tsx +0 -232
- package/src/components/organisms/select.tsx +0 -309
- package/src/components/organisms/sheet.tsx +0 -265
- package/src/components/organisms/sidebar.tsx +0 -1040
- package/src/components/organisms/sonner.tsx +0 -96
- package/src/components/organisms/tabs.tsx +0 -133
- package/src/components/organisms/theme-provider.tsx +0 -101
- package/src/hooks/use-mobile.tsx +0 -19
- package/src/lib/portal-container.tsx +0 -35
- package/src/lib/utils.ts +0 -6
- package/src/native.ts +0 -23
- package/src/tokens/colors.ts +0 -91
- package/src/tokens/index.ts +0 -3
- package/src/tokens/spacing.ts +0 -55
- package/src/tokens/typography.ts +0 -27
- package/styles/dashboard-grid.css +0 -47
- package/styles/fonts/Roboto-VariableFont_wdth_wght.ttf +0 -0
- package/styles/glass.css +0 -171
- package/styles/leaflet.css +0 -13
- package/styles/tokens.css +0 -317
- package/tailwind.config.ts +0 -70
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
|
|
4
|
-
import * as React from "react";
|
|
5
|
-
import { type DayButton, DayPicker, getDefaultClassNames } from "react-day-picker";
|
|
6
|
-
|
|
7
|
-
import { cn } from "../../lib/utils";
|
|
8
|
-
import { Button, buttonVariants } from "../atoms/button";
|
|
9
|
-
|
|
10
|
-
export type CalendarProps = React.ComponentProps<typeof DayPicker> & {
|
|
11
|
-
/**
|
|
12
|
-
* Variant applied to the prev/next month nav buttons. Maps to the
|
|
13
|
-
* `Button` atom's variants.
|
|
14
|
-
* @default "ghost"
|
|
15
|
-
*/
|
|
16
|
-
buttonVariant?: React.ComponentProps<typeof Button>["variant"];
|
|
17
|
-
/**
|
|
18
|
-
* Show days from the previous/next month as faded entries to fill the
|
|
19
|
-
* grid.
|
|
20
|
-
* @default true
|
|
21
|
-
*/
|
|
22
|
-
showOutsideDays?: boolean;
|
|
23
|
-
/**
|
|
24
|
-
* How the month/year heading renders. `label` is plain text, the
|
|
25
|
-
* dropdown variants render selectable controls.
|
|
26
|
-
* @default "label"
|
|
27
|
-
*/
|
|
28
|
-
captionLayout?: "label" | "dropdown" | "dropdown-months" | "dropdown-years";
|
|
29
|
-
className?: string;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
function Calendar({
|
|
33
|
-
className,
|
|
34
|
-
classNames,
|
|
35
|
-
showOutsideDays = true,
|
|
36
|
-
captionLayout = "label",
|
|
37
|
-
buttonVariant = "ghost",
|
|
38
|
-
formatters,
|
|
39
|
-
components,
|
|
40
|
-
...props
|
|
41
|
-
}: CalendarProps) {
|
|
42
|
-
const defaultClassNames = getDefaultClassNames();
|
|
43
|
-
|
|
44
|
-
return (
|
|
45
|
-
<DayPicker
|
|
46
|
-
showOutsideDays={showOutsideDays}
|
|
47
|
-
data-slot="calendar"
|
|
48
|
-
className={cn(
|
|
49
|
-
"bg-background group/calendar p-4 [--cell-size:2rem] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
|
|
50
|
-
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
|
|
51
|
-
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
|
|
52
|
-
className,
|
|
53
|
-
)}
|
|
54
|
-
captionLayout={captionLayout}
|
|
55
|
-
formatters={{
|
|
56
|
-
formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
|
|
57
|
-
...formatters,
|
|
58
|
-
}}
|
|
59
|
-
classNames={{
|
|
60
|
-
root: cn("w-fit", defaultClassNames.root),
|
|
61
|
-
months: cn("relative flex flex-col gap-4 md:flex-row", defaultClassNames.months),
|
|
62
|
-
month: cn("flex w-full flex-col gap-3", defaultClassNames.month),
|
|
63
|
-
nav: cn(
|
|
64
|
-
"absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
|
|
65
|
-
defaultClassNames.nav,
|
|
66
|
-
),
|
|
67
|
-
button_previous: cn(
|
|
68
|
-
buttonVariants({ variant: buttonVariant }),
|
|
69
|
-
"h-[var(--cell-size)] w-[var(--cell-size)] select-none p-0 aria-disabled:opacity-50",
|
|
70
|
-
defaultClassNames.button_previous,
|
|
71
|
-
),
|
|
72
|
-
button_next: cn(
|
|
73
|
-
buttonVariants({ variant: buttonVariant }),
|
|
74
|
-
"h-[var(--cell-size)] w-[var(--cell-size)] select-none p-0 aria-disabled:opacity-50",
|
|
75
|
-
defaultClassNames.button_next,
|
|
76
|
-
),
|
|
77
|
-
month_caption: cn(
|
|
78
|
-
"flex h-[var(--cell-size)] w-full items-center justify-center px-[var(--cell-size)]",
|
|
79
|
-
defaultClassNames.month_caption,
|
|
80
|
-
),
|
|
81
|
-
dropdowns: cn(
|
|
82
|
-
"flex h-[var(--cell-size)] w-full items-center justify-center gap-1.5 text-sm font-medium",
|
|
83
|
-
defaultClassNames.dropdowns,
|
|
84
|
-
),
|
|
85
|
-
dropdown_root: cn(
|
|
86
|
-
"has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border",
|
|
87
|
-
defaultClassNames.dropdown_root,
|
|
88
|
-
),
|
|
89
|
-
dropdown: cn("bg-popover absolute inset-0 opacity-0", defaultClassNames.dropdown),
|
|
90
|
-
caption_label: cn(
|
|
91
|
-
"select-none font-semibold tracking-tight text-foreground",
|
|
92
|
-
captionLayout === "label"
|
|
93
|
-
? "text-sm"
|
|
94
|
-
: "[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5",
|
|
95
|
-
defaultClassNames.caption_label,
|
|
96
|
-
),
|
|
97
|
-
table: "w-full border-collapse",
|
|
98
|
-
weekdays: cn("flex border-b border-border pb-1.5", defaultClassNames.weekdays),
|
|
99
|
-
weekday: cn(
|
|
100
|
-
"text-muted-foreground flex-1 select-none rounded-md text-[0.7rem] font-medium uppercase tracking-wider",
|
|
101
|
-
defaultClassNames.weekday,
|
|
102
|
-
),
|
|
103
|
-
week: cn("mt-1.5 flex w-full", defaultClassNames.week),
|
|
104
|
-
week_number_header: cn(
|
|
105
|
-
"w-[var(--cell-size)] select-none",
|
|
106
|
-
defaultClassNames.week_number_header,
|
|
107
|
-
),
|
|
108
|
-
week_number: cn(
|
|
109
|
-
"text-muted-foreground select-none text-[0.8rem]",
|
|
110
|
-
defaultClassNames.week_number,
|
|
111
|
-
),
|
|
112
|
-
day: cn(
|
|
113
|
-
"group/day relative aspect-square h-full w-full select-none p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md",
|
|
114
|
-
defaultClassNames.day,
|
|
115
|
-
),
|
|
116
|
-
range_start: cn("bg-brand/10 rounded-l-md", defaultClassNames.range_start),
|
|
117
|
-
range_middle: cn("bg-brand/10 rounded-none", defaultClassNames.range_middle),
|
|
118
|
-
range_end: cn("bg-brand/10 rounded-r-md", defaultClassNames.range_end),
|
|
119
|
-
today: cn(
|
|
120
|
-
"text-brand font-semibold data-[selected=true]:rounded-none",
|
|
121
|
-
defaultClassNames.today,
|
|
122
|
-
),
|
|
123
|
-
outside: cn(
|
|
124
|
-
"text-muted-foreground/50 aria-selected:text-muted-foreground",
|
|
125
|
-
defaultClassNames.outside,
|
|
126
|
-
),
|
|
127
|
-
disabled: cn("text-muted-foreground opacity-40", defaultClassNames.disabled),
|
|
128
|
-
hidden: cn("invisible", defaultClassNames.hidden),
|
|
129
|
-
...classNames,
|
|
130
|
-
}}
|
|
131
|
-
components={{
|
|
132
|
-
Root: ({ className, rootRef, ...props }) => {
|
|
133
|
-
return <div data-slot="calendar" ref={rootRef} className={cn(className)} {...props} />;
|
|
134
|
-
},
|
|
135
|
-
Chevron: ({ className, orientation, ...props }) => {
|
|
136
|
-
if (orientation === "left") {
|
|
137
|
-
return <ChevronLeftIcon className={cn("size-4", className)} {...props} />;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (orientation === "right") {
|
|
141
|
-
return <ChevronRightIcon className={cn("size-4", className)} {...props} />;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return <ChevronDownIcon className={cn("size-4", className)} {...props} />;
|
|
145
|
-
},
|
|
146
|
-
DayButton: CalendarDayButton,
|
|
147
|
-
WeekNumber: ({ children, ...props }) => {
|
|
148
|
-
return (
|
|
149
|
-
<td {...props}>
|
|
150
|
-
<div className="flex size-[var(--cell-size)] items-center justify-center text-center">
|
|
151
|
-
{children}
|
|
152
|
-
</div>
|
|
153
|
-
</td>
|
|
154
|
-
);
|
|
155
|
-
},
|
|
156
|
-
...components,
|
|
157
|
-
}}
|
|
158
|
-
{...props}
|
|
159
|
-
/>
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function CalendarDayButton({
|
|
164
|
-
className,
|
|
165
|
-
day,
|
|
166
|
-
modifiers,
|
|
167
|
-
...props
|
|
168
|
-
}: React.ComponentProps<typeof DayButton>) {
|
|
169
|
-
const defaultClassNames = getDefaultClassNames();
|
|
170
|
-
|
|
171
|
-
const ref = React.useRef<HTMLButtonElement>(null);
|
|
172
|
-
React.useEffect(() => {
|
|
173
|
-
if (modifiers.focused) ref.current?.focus();
|
|
174
|
-
}, [modifiers.focused]);
|
|
175
|
-
|
|
176
|
-
return (
|
|
177
|
-
<Button
|
|
178
|
-
ref={ref}
|
|
179
|
-
variant="ghost"
|
|
180
|
-
size="icon"
|
|
181
|
-
data-day={day.date.toLocaleDateString()}
|
|
182
|
-
data-selected-single={
|
|
183
|
-
modifiers.selected &&
|
|
184
|
-
!modifiers.range_start &&
|
|
185
|
-
!modifiers.range_end &&
|
|
186
|
-
!modifiers.range_middle
|
|
187
|
-
}
|
|
188
|
-
data-range-start={modifiers.range_start}
|
|
189
|
-
data-range-end={modifiers.range_end}
|
|
190
|
-
data-range-middle={modifiers.range_middle}
|
|
191
|
-
className={cn(
|
|
192
|
-
// base size + typography (small inner inset so adjacent dates breathe)
|
|
193
|
-
"m-0.5 flex aspect-square h-auto w-[calc(100%-0.25rem)] min-w-[calc(var(--cell-size)-0.25rem)] items-center justify-center rounded-md text-sm font-normal leading-none transition-colors",
|
|
194
|
-
// hover (when not selected)
|
|
195
|
-
"hover:bg-accent hover:text-accent-foreground",
|
|
196
|
-
// today: keep brand text colour from row classNames; add subtle ring
|
|
197
|
-
"group-[[data-today=true]]/day:ring-1 group-[[data-today=true]]/day:ring-brand/40",
|
|
198
|
-
// single selection: brand fill, white text, full rounding
|
|
199
|
-
"data-[selected-single=true]:bg-brand data-[selected-single=true]:text-brand-foreground data-[selected-single=true]:hover:bg-brand/90 data-[selected-single=true]:hover:text-brand-foreground",
|
|
200
|
-
// range endpoints: brand fill, only outer corners rounded
|
|
201
|
-
"data-[range-start=true]:bg-brand data-[range-start=true]:text-brand-foreground data-[range-start=true]:hover:bg-brand/90 data-[range-start=true]:hover:text-brand-foreground data-[range-start=true]:rounded-r-none",
|
|
202
|
-
"data-[range-end=true]:bg-brand data-[range-end=true]:text-brand-foreground data-[range-end=true]:hover:bg-brand/90 data-[range-end=true]:hover:text-brand-foreground data-[range-end=true]:rounded-l-none",
|
|
203
|
-
// range middle: foreground stays default, no rounding
|
|
204
|
-
"data-[range-middle=true]:bg-transparent data-[range-middle=true]:text-foreground data-[range-middle=true]:rounded-none",
|
|
205
|
-
// focus ring (for keyboard nav)
|
|
206
|
-
"group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-brand/40 group-data-[focused=true]/day:border-brand",
|
|
207
|
-
// modifier label (e.g. holidays) sub-line
|
|
208
|
-
"[&>span]:text-xs [&>span]:opacity-70",
|
|
209
|
-
defaultClassNames.day,
|
|
210
|
-
className,
|
|
211
|
-
)}
|
|
212
|
-
{...props}
|
|
213
|
-
/>
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
export { Calendar, CalendarDayButton };
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
|
|
3
|
-
import { cn } from "../../lib/utils";
|
|
4
|
-
|
|
5
|
-
export interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
6
|
-
/** `<CardHeader>`, `<CardContent>`, `<CardFooter>` (or any custom layout). */
|
|
7
|
-
children?: React.ReactNode;
|
|
8
|
-
/**
|
|
9
|
-
* Tailwind / CSS classes merged onto the card via `cn()`. Default
|
|
10
|
-
* styling: `rounded-xl` (12px), `border`, `bg-card`, `shadow`.
|
|
11
|
-
*/
|
|
12
|
-
className?: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const Card = React.forwardRef<HTMLDivElement, CardProps>(({ className, ...props }, ref) => (
|
|
16
|
-
<div
|
|
17
|
-
ref={ref}
|
|
18
|
-
data-slot="card"
|
|
19
|
-
className={cn("rounded-xl border border-border bg-card text-card-foreground shadow", className)}
|
|
20
|
-
{...props}
|
|
21
|
-
/>
|
|
22
|
-
));
|
|
23
|
-
Card.displayName = "Card";
|
|
24
|
-
|
|
25
|
-
export interface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
26
|
-
/** Typically `<CardTitle>` + `<CardDescription>`. */
|
|
27
|
-
children?: React.ReactNode;
|
|
28
|
-
/** Tailwind / CSS classes merged onto the header via `cn()`. Default: `p-6 space-y-1.5`. */
|
|
29
|
-
className?: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const CardHeader = React.forwardRef<HTMLDivElement, CardHeaderProps>(
|
|
33
|
-
({ className, ...props }, ref) => (
|
|
34
|
-
<div ref={ref} className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} />
|
|
35
|
-
),
|
|
36
|
-
);
|
|
37
|
-
CardHeader.displayName = "CardHeader";
|
|
38
|
-
|
|
39
|
-
export interface CardTitleProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
40
|
-
/** The card heading. */
|
|
41
|
-
children?: React.ReactNode;
|
|
42
|
-
/** Tailwind / CSS classes merged onto the title via `cn()`. */
|
|
43
|
-
className?: string;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const CardTitle = React.forwardRef<HTMLDivElement, CardTitleProps>(
|
|
47
|
-
({ className, ...props }, ref) => (
|
|
48
|
-
<div
|
|
49
|
-
ref={ref}
|
|
50
|
-
className={cn("font-semibold leading-none tracking-tight", className)}
|
|
51
|
-
{...props}
|
|
52
|
-
/>
|
|
53
|
-
),
|
|
54
|
-
);
|
|
55
|
-
CardTitle.displayName = "CardTitle";
|
|
56
|
-
|
|
57
|
-
export interface CardDescriptionProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
58
|
-
/** Subtitle / supporting copy below the title. */
|
|
59
|
-
children?: React.ReactNode;
|
|
60
|
-
/** Tailwind / CSS classes merged onto the description via `cn()`. */
|
|
61
|
-
className?: string;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const CardDescription = React.forwardRef<HTMLDivElement, CardDescriptionProps>(
|
|
65
|
-
({ className, ...props }, ref) => (
|
|
66
|
-
<div ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
|
|
67
|
-
),
|
|
68
|
-
);
|
|
69
|
-
CardDescription.displayName = "CardDescription";
|
|
70
|
-
|
|
71
|
-
export interface CardContentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
72
|
-
/** Card body. */
|
|
73
|
-
children?: React.ReactNode;
|
|
74
|
-
/** Tailwind / CSS classes merged onto the content via `cn()`. Default: `p-6 pt-0`. */
|
|
75
|
-
className?: string;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const CardContent = React.forwardRef<HTMLDivElement, CardContentProps>(
|
|
79
|
-
({ className, ...props }, ref) => (
|
|
80
|
-
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
|
81
|
-
),
|
|
82
|
-
);
|
|
83
|
-
CardContent.displayName = "CardContent";
|
|
84
|
-
|
|
85
|
-
export interface CardFooterProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
86
|
-
/** Card actions / metadata row. */
|
|
87
|
-
children?: React.ReactNode;
|
|
88
|
-
/**
|
|
89
|
-
* Tailwind / CSS classes merged onto the footer via `cn()`. Default:
|
|
90
|
-
* `flex items-center p-6 pt-0`.
|
|
91
|
-
*/
|
|
92
|
-
className?: string;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const CardFooter = React.forwardRef<HTMLDivElement, CardFooterProps>(
|
|
96
|
-
({ className, ...props }, ref) => (
|
|
97
|
-
<div ref={ref} className={cn("flex items-center p-6 pt-0", className)} {...props} />
|
|
98
|
-
),
|
|
99
|
-
);
|
|
100
|
-
CardFooter.displayName = "CardFooter";
|
|
101
|
-
|
|
102
|
-
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
|
|
5
|
-
import { cn } from "../../lib/utils";
|
|
6
|
-
|
|
7
|
-
export interface ClientBrandProps {
|
|
8
|
-
/** OAuth2 client display name (e.g. "Questrade", "Athena"). */
|
|
9
|
-
clientName: string;
|
|
10
|
-
/**
|
|
11
|
-
* Optional logo URI. Renders as an `<img>` next to the wordmark when
|
|
12
|
-
* present. When absent, a tinted monogram tile is rendered using the
|
|
13
|
-
* first letter of `clientName`.
|
|
14
|
-
*/
|
|
15
|
-
clientLogoUri?: string;
|
|
16
|
-
/**
|
|
17
|
-
* Pixel size of the logo/monogram tile.
|
|
18
|
-
* @default 36
|
|
19
|
-
*/
|
|
20
|
-
size?: number;
|
|
21
|
-
/**
|
|
22
|
-
* Show the wordmark next to the logo.
|
|
23
|
-
* @default true
|
|
24
|
-
*/
|
|
25
|
-
showWordmark?: boolean;
|
|
26
|
-
/**
|
|
27
|
-
* Background colour applied to the monogram fallback tile. Honours
|
|
28
|
-
* Tailwind classes or a raw CSS colour.
|
|
29
|
-
* @default "bg-foreground text-background"
|
|
30
|
-
*/
|
|
31
|
-
monogramClassName?: string;
|
|
32
|
-
/** Tailwind / CSS classes merged onto the root via `cn()`. */
|
|
33
|
-
className?: string;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* OAuth2 client lockup. Renders the requesting application's logo + name
|
|
38
|
-
* so users see "you're signing in to [App]", not the identity-provider
|
|
39
|
-
* platform underneath.
|
|
40
|
-
*
|
|
41
|
-
* Provide `clientLogoUri` to render the client's logo image. Falls back to
|
|
42
|
-
* a monogram tile when no URI is supplied or the image fails to load.
|
|
43
|
-
*
|
|
44
|
-
* Designed for the brand slot of `AuthShell` / sign-in pages. Stays a thin
|
|
45
|
-
* presentation primitive: no client-registry lookups, no fetches. Pass the
|
|
46
|
-
* shaped data in from your auth backend.
|
|
47
|
-
*/
|
|
48
|
-
const ClientBrand = React.forwardRef<HTMLDivElement, ClientBrandProps>(
|
|
49
|
-
(
|
|
50
|
-
{ clientName, clientLogoUri, size = 36, showWordmark = true, monogramClassName, className },
|
|
51
|
-
ref,
|
|
52
|
-
) => {
|
|
53
|
-
const [imgFailed, setImgFailed] = React.useState(false);
|
|
54
|
-
const showImage = !!clientLogoUri && !imgFailed;
|
|
55
|
-
const initial = (clientName?.trim()?.[0] || "?").toUpperCase();
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<div
|
|
59
|
-
ref={ref}
|
|
60
|
-
role="img"
|
|
61
|
-
aria-label={`Signing in to ${clientName}`}
|
|
62
|
-
className={cn("flex items-center gap-2.5", className)}
|
|
63
|
-
>
|
|
64
|
-
{showImage ? (
|
|
65
|
-
<img
|
|
66
|
-
src={clientLogoUri}
|
|
67
|
-
alt=""
|
|
68
|
-
width={size}
|
|
69
|
-
height={size}
|
|
70
|
-
className="shrink-0 rounded-lg object-contain"
|
|
71
|
-
style={{ width: size, height: size }}
|
|
72
|
-
onError={() => setImgFailed(true)}
|
|
73
|
-
/>
|
|
74
|
-
) : (
|
|
75
|
-
<div
|
|
76
|
-
className={cn(
|
|
77
|
-
"flex shrink-0 items-center justify-center rounded-lg font-semibold",
|
|
78
|
-
monogramClassName || "bg-foreground text-background",
|
|
79
|
-
)}
|
|
80
|
-
style={{ width: size, height: size, fontSize: Math.round(size * 0.5) }}
|
|
81
|
-
aria-hidden
|
|
82
|
-
>
|
|
83
|
-
{initial}
|
|
84
|
-
</div>
|
|
85
|
-
)}
|
|
86
|
-
{showWordmark && (
|
|
87
|
-
<span className="text-lg font-semibold tracking-tight text-foreground">{clientName}</span>
|
|
88
|
-
)}
|
|
89
|
-
</div>
|
|
90
|
-
);
|
|
91
|
-
},
|
|
92
|
-
);
|
|
93
|
-
ClientBrand.displayName = "ClientBrand";
|
|
94
|
-
|
|
95
|
-
export { ClientBrand };
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { Check, Copy } from "lucide-react";
|
|
4
|
-
import * as React from "react";
|
|
5
|
-
|
|
6
|
-
import { cn } from "../../lib/utils";
|
|
7
|
-
import { Button } from "../atoms/button";
|
|
8
|
-
|
|
9
|
-
export interface CodeBlockProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
10
|
-
code: string;
|
|
11
|
-
language?: string;
|
|
12
|
-
showCopy?: boolean;
|
|
13
|
-
/**
|
|
14
|
-
* `"light"` (default) renders against `bg-muted`; `"dark"` switches to a
|
|
15
|
-
* near-black terminal palette (`#0a0a0b` background, `#e4e4e7` text) for
|
|
16
|
-
* use on marketing surfaces.
|
|
17
|
-
*/
|
|
18
|
-
theme?: "light" | "dark";
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const CodeBlock = React.forwardRef<HTMLDivElement, CodeBlockProps>(
|
|
22
|
-
({ code, language, showCopy = true, theme = "light", className, ...props }, ref) => {
|
|
23
|
-
const [copied, setCopied] = React.useState(false);
|
|
24
|
-
const isDark = theme === "dark";
|
|
25
|
-
|
|
26
|
-
const handleCopy = React.useCallback(async () => {
|
|
27
|
-
await navigator.clipboard.writeText(code);
|
|
28
|
-
setCopied(true);
|
|
29
|
-
setTimeout(() => setCopied(false), 2000);
|
|
30
|
-
}, [code]);
|
|
31
|
-
|
|
32
|
-
return (
|
|
33
|
-
<div
|
|
34
|
-
ref={ref}
|
|
35
|
-
data-slot="code-block"
|
|
36
|
-
className={cn(
|
|
37
|
-
"relative overflow-hidden rounded-md",
|
|
38
|
-
isDark ? "border border-border" : "bg-muted",
|
|
39
|
-
className,
|
|
40
|
-
)}
|
|
41
|
-
style={isDark ? { background: "#0a0a0b" } : undefined}
|
|
42
|
-
{...props}
|
|
43
|
-
>
|
|
44
|
-
{(language || showCopy) && (
|
|
45
|
-
<div
|
|
46
|
-
className={cn(
|
|
47
|
-
"flex items-center justify-between px-4 py-2",
|
|
48
|
-
isDark ? undefined : "border-b",
|
|
49
|
-
)}
|
|
50
|
-
style={isDark ? { borderBottom: "1px solid #222" } : undefined}
|
|
51
|
-
>
|
|
52
|
-
{language ? (
|
|
53
|
-
<span
|
|
54
|
-
className={cn("text-xs font-medium", !isDark && "text-muted-foreground")}
|
|
55
|
-
style={isDark ? { color: "#6b7280" } : undefined}
|
|
56
|
-
>
|
|
57
|
-
{language}
|
|
58
|
-
</span>
|
|
59
|
-
) : (
|
|
60
|
-
<span />
|
|
61
|
-
)}
|
|
62
|
-
{showCopy && (
|
|
63
|
-
<Button
|
|
64
|
-
variant="ghost"
|
|
65
|
-
size="icon"
|
|
66
|
-
className={cn(
|
|
67
|
-
"h-6 w-6",
|
|
68
|
-
isDark && "text-zinc-400 hover:bg-white/5 hover:text-zinc-100",
|
|
69
|
-
)}
|
|
70
|
-
onClick={handleCopy}
|
|
71
|
-
>
|
|
72
|
-
{copied ? <Check className="h-3 w-3" /> : <Copy className="h-3 w-3" />}
|
|
73
|
-
</Button>
|
|
74
|
-
)}
|
|
75
|
-
</div>
|
|
76
|
-
)}
|
|
77
|
-
<pre className="overflow-x-auto p-4" style={isDark ? { color: "#e4e4e7" } : undefined}>
|
|
78
|
-
<code className="text-sm">{code}</code>
|
|
79
|
-
</pre>
|
|
80
|
-
</div>
|
|
81
|
-
);
|
|
82
|
-
},
|
|
83
|
-
);
|
|
84
|
-
CodeBlock.displayName = "CodeBlock";
|
|
85
|
-
|
|
86
|
-
export { CodeBlock };
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
|
|
5
|
-
import { cn } from "../../lib/utils";
|
|
6
|
-
import { Button, type ButtonProps } from "../atoms/button";
|
|
7
|
-
|
|
8
|
-
export interface CountdownButtonProps
|
|
9
|
-
extends Omit<ButtonProps, "disabled" | "onClick" | "children"> {
|
|
10
|
-
/**
|
|
11
|
-
* Seconds to wait before the button becomes clickable. The countdown
|
|
12
|
-
* starts when the component mounts and resets every time `triggerKey`
|
|
13
|
-
* changes.
|
|
14
|
-
* @default 30
|
|
15
|
-
*/
|
|
16
|
-
duration?: number;
|
|
17
|
-
/**
|
|
18
|
-
* Bump this value to restart the countdown (e.g. after a successful
|
|
19
|
-
* resend, set it to `Date.now()` so the button locks out again).
|
|
20
|
-
*/
|
|
21
|
-
triggerKey?: string | number;
|
|
22
|
-
/** Called when the button is clicked and the countdown has elapsed. */
|
|
23
|
-
onClick?: () => void;
|
|
24
|
-
/**
|
|
25
|
-
* Render-prop for the button label. Receives `secondsLeft` (0 when
|
|
26
|
-
* ready). Default renders `"Resend"` / `"Resend in 23s"`.
|
|
27
|
-
*/
|
|
28
|
-
children?: React.ReactNode | ((secondsLeft: number) => React.ReactNode);
|
|
29
|
-
/**
|
|
30
|
-
* Action verb shown in the default label. Used as `${verb}` when ready
|
|
31
|
-
* and `${verb} in Ns` while counting down.
|
|
32
|
-
* @default "Resend"
|
|
33
|
-
*/
|
|
34
|
-
verb?: string;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Button that locks out for a duration after mount or after `triggerKey`
|
|
39
|
-
* changes. Renders countdown text while disabled.
|
|
40
|
-
*
|
|
41
|
-
* Use for "resend code" / "resend email" flows where the user shouldn't be
|
|
42
|
-
* able to spam the action. Triggering a new send from elsewhere should
|
|
43
|
-
* update `triggerKey` to restart the lockout.
|
|
44
|
-
*/
|
|
45
|
-
const CountdownButton = React.forwardRef<HTMLButtonElement, CountdownButtonProps>(
|
|
46
|
-
(
|
|
47
|
-
{ duration = 30, triggerKey, onClick, children, verb = "Resend", className, ...buttonProps },
|
|
48
|
-
ref,
|
|
49
|
-
) => {
|
|
50
|
-
const [secondsLeft, setSecondsLeft] = React.useState(duration);
|
|
51
|
-
|
|
52
|
-
React.useEffect(() => {
|
|
53
|
-
setSecondsLeft(duration);
|
|
54
|
-
const interval = setInterval(() => {
|
|
55
|
-
setSecondsLeft((s) => {
|
|
56
|
-
if (s <= 1) {
|
|
57
|
-
clearInterval(interval);
|
|
58
|
-
return 0;
|
|
59
|
-
}
|
|
60
|
-
return s - 1;
|
|
61
|
-
});
|
|
62
|
-
}, 1000);
|
|
63
|
-
return () => clearInterval(interval);
|
|
64
|
-
}, [duration, triggerKey]);
|
|
65
|
-
|
|
66
|
-
const ready = secondsLeft <= 0;
|
|
67
|
-
const labelNode =
|
|
68
|
-
typeof children === "function"
|
|
69
|
-
? children(secondsLeft)
|
|
70
|
-
: children !== undefined
|
|
71
|
-
? children
|
|
72
|
-
: ready
|
|
73
|
-
? verb
|
|
74
|
-
: `${verb} in ${secondsLeft}s`;
|
|
75
|
-
|
|
76
|
-
return (
|
|
77
|
-
<Button
|
|
78
|
-
ref={ref}
|
|
79
|
-
type="button"
|
|
80
|
-
disabled={!ready}
|
|
81
|
-
onClick={() => ready && onClick?.()}
|
|
82
|
-
className={cn(className)}
|
|
83
|
-
{...buttonProps}
|
|
84
|
-
>
|
|
85
|
-
{labelNode}
|
|
86
|
-
</Button>
|
|
87
|
-
);
|
|
88
|
-
},
|
|
89
|
-
);
|
|
90
|
-
CountdownButton.displayName = "CountdownButton";
|
|
91
|
-
|
|
92
|
-
export { CountdownButton };
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { Inbox } from "lucide-react";
|
|
4
|
-
import * as React from "react";
|
|
5
|
-
|
|
6
|
-
import { cn } from "../../lib/utils";
|
|
7
|
-
import { Button } from "../atoms/button";
|
|
8
|
-
|
|
9
|
-
export interface EmptyStateProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
10
|
-
icon?: React.ReactNode;
|
|
11
|
-
/** Primary message. Renders below the icon pill, 15px font-medium. */
|
|
12
|
-
title?: string;
|
|
13
|
-
/**
|
|
14
|
-
* @deprecated Use `title`. Retained as an alias so existing call sites
|
|
15
|
-
* (e.g. DataTable's empty fallback) keep working.
|
|
16
|
-
*/
|
|
17
|
-
message?: string;
|
|
18
|
-
description?: string;
|
|
19
|
-
action?: {
|
|
20
|
-
label: string;
|
|
21
|
-
onClick: () => void;
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const EmptyState = React.forwardRef<HTMLDivElement, EmptyStateProps>(
|
|
26
|
-
({ icon, title, message, description, action, className, ...props }, ref) => {
|
|
27
|
-
const heading = title ?? message ?? "No items found";
|
|
28
|
-
return (
|
|
29
|
-
<div
|
|
30
|
-
ref={ref}
|
|
31
|
-
data-slot="empty-state"
|
|
32
|
-
className={cn(
|
|
33
|
-
"flex flex-col items-center justify-center gap-3 py-12 text-muted-foreground",
|
|
34
|
-
className,
|
|
35
|
-
)}
|
|
36
|
-
{...props}
|
|
37
|
-
>
|
|
38
|
-
<div className="mb-1 inline-flex rounded-full bg-muted p-3 text-muted-foreground">
|
|
39
|
-
{icon ?? <Inbox className="h-5 w-5" />}
|
|
40
|
-
</div>
|
|
41
|
-
<div className="text-center">
|
|
42
|
-
<p className="text-[15px] font-medium text-foreground">{heading}</p>
|
|
43
|
-
{description && <p className="mt-1 text-xs text-muted-foreground">{description}</p>}
|
|
44
|
-
</div>
|
|
45
|
-
{action && (
|
|
46
|
-
<Button variant="outline" size="sm" onClick={action.onClick}>
|
|
47
|
-
{action.label}
|
|
48
|
-
</Button>
|
|
49
|
-
)}
|
|
50
|
-
</div>
|
|
51
|
-
);
|
|
52
|
-
},
|
|
53
|
-
);
|
|
54
|
-
EmptyState.displayName = "EmptyState";
|
|
55
|
-
|
|
56
|
-
export { EmptyState };
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { AlertCircle } from "lucide-react";
|
|
4
|
-
import * as React from "react";
|
|
5
|
-
|
|
6
|
-
import { cn } from "../../lib/utils";
|
|
7
|
-
import { Button } from "../atoms/button";
|
|
8
|
-
|
|
9
|
-
export interface ErrorStateProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
10
|
-
message?: string;
|
|
11
|
-
onRetry?: () => void;
|
|
12
|
-
retryLabel?: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const ErrorState = React.forwardRef<HTMLDivElement, ErrorStateProps>(
|
|
16
|
-
(
|
|
17
|
-
{ message = "Something went wrong.", onRetry, retryLabel = "Try again", className, ...props },
|
|
18
|
-
ref,
|
|
19
|
-
) => {
|
|
20
|
-
return (
|
|
21
|
-
<div
|
|
22
|
-
ref={ref}
|
|
23
|
-
className={cn(
|
|
24
|
-
"flex flex-col items-center justify-center gap-3 py-8 text-muted-foreground",
|
|
25
|
-
className,
|
|
26
|
-
)}
|
|
27
|
-
{...props}
|
|
28
|
-
>
|
|
29
|
-
<AlertCircle className="h-8 w-8 text-destructive" />
|
|
30
|
-
<p className="text-sm">{message}</p>
|
|
31
|
-
{onRetry && (
|
|
32
|
-
<Button variant="outline" size="sm" onClick={onRetry}>
|
|
33
|
-
{retryLabel}
|
|
34
|
-
</Button>
|
|
35
|
-
)}
|
|
36
|
-
</div>
|
|
37
|
-
);
|
|
38
|
-
},
|
|
39
|
-
);
|
|
40
|
-
ErrorState.displayName = "ErrorState";
|
|
41
|
-
|
|
42
|
-
export { ErrorState };
|