@arcfusionz/arc-primitive-ui 0.1.0 → 0.2.1
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/dist/components/AILoader/AILoader.d.ts +32 -0
- package/dist/components/AILoader/AILoader.js +157 -0
- package/dist/components/AILoader/index.d.ts +2 -0
- package/dist/components/AILoader/index.js +2 -0
- package/dist/components/Accordion/Accordion.d.ts +96 -0
- package/dist/components/Accordion/Accordion.js +149 -0
- package/dist/components/Accordion/index.d.ts +2 -0
- package/dist/components/Accordion/index.js +2 -0
- package/dist/components/Avatar/Avatar.d.ts +152 -0
- package/dist/components/Avatar/Avatar.js +216 -0
- package/dist/components/Avatar/index.d.ts +2 -0
- package/dist/components/Avatar/index.js +2 -0
- package/dist/components/Badge/Badge.d.ts +87 -0
- package/dist/components/Badge/Badge.js +118 -0
- package/dist/components/Badge/index.d.ts +2 -0
- package/dist/components/Badge/index.js +2 -0
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +109 -0
- package/dist/components/Breadcrumb/Breadcrumb.js +182 -0
- package/dist/components/Breadcrumb/index.d.ts +2 -0
- package/dist/components/Breadcrumb/index.js +2 -0
- package/dist/components/Button/Button.d.ts +57 -0
- package/dist/components/Button/Button.js +177 -0
- package/dist/components/Button/index.d.ts +2 -0
- package/dist/components/Button/index.js +2 -0
- package/dist/components/Calendar/Calendar.d.ts +140 -0
- package/dist/components/Calendar/Calendar.js +468 -0
- package/dist/components/Calendar/index.d.ts +2 -0
- package/dist/components/Calendar/index.js +2 -0
- package/dist/components/Checkbox/Checkbox.d.ts +60 -0
- package/dist/components/Checkbox/Checkbox.js +129 -0
- package/dist/components/Checkbox/index.d.ts +2 -0
- package/dist/components/Checkbox/index.js +2 -0
- package/dist/components/Combobox/Combobox.d.ts +251 -0
- package/dist/components/Combobox/Combobox.js +354 -0
- package/dist/components/Combobox/index.d.ts +2 -0
- package/dist/components/Combobox/index.js +2 -0
- package/dist/components/ContextMenu/ContextMenu.d.ts +129 -0
- package/dist/components/ContextMenu/ContextMenu.js +93 -0
- package/dist/components/ContextMenu/index.d.ts +2 -0
- package/dist/components/ContextMenu/index.js +2 -0
- package/dist/components/DatePicker/DatePicker.d.ts +109 -0
- package/dist/components/DatePicker/DatePicker.js +145 -0
- package/dist/components/DatePicker/index.d.ts +2 -0
- package/dist/components/DatePicker/index.js +2 -0
- package/dist/components/DateRangePicker/DateRangePicker.d.ts +107 -0
- package/dist/components/DateRangePicker/DateRangePicker.js +161 -0
- package/dist/components/DateRangePicker/index.d.ts +2 -0
- package/dist/components/DateRangePicker/index.js +2 -0
- package/dist/components/Dialog/Dialog.d.ts +112 -0
- package/dist/components/Dialog/Dialog.js +141 -0
- package/dist/components/Dialog/index.d.ts +2 -0
- package/dist/components/Dialog/index.js +2 -0
- package/dist/components/Drawer/Drawer.d.ts +188 -0
- package/dist/components/Drawer/Drawer.js +268 -0
- package/dist/components/Drawer/index.d.ts +2 -0
- package/dist/components/Drawer/index.js +2 -0
- package/dist/components/Field/Field.d.ts +123 -0
- package/dist/components/Field/Field.js +241 -0
- package/dist/components/Field/FieldContext.d.ts +43 -0
- package/dist/components/Field/FieldContext.js +28 -0
- package/dist/components/Field/index.d.ts +3 -0
- package/dist/components/Field/index.js +3 -0
- package/dist/components/Fieldset/Fieldset.d.ts +43 -0
- package/dist/components/Fieldset/Fieldset.js +48 -0
- package/dist/components/Fieldset/index.d.ts +2 -0
- package/dist/components/Fieldset/index.js +2 -0
- package/dist/components/Form/Form.d.ts +54 -0
- package/dist/components/Form/Form.js +57 -0
- package/dist/components/Form/index.d.ts +2 -0
- package/dist/components/Form/index.js +2 -0
- package/dist/components/Input/Input.d.ts +64 -0
- package/dist/components/Input/Input.js +111 -0
- package/dist/components/Input/index.d.ts +2 -0
- package/dist/components/Input/index.js +2 -0
- package/dist/components/Menu/Menu.d.ts +212 -0
- package/dist/components/Menu/Menu.js +255 -0
- package/dist/components/Menu/index.d.ts +2 -0
- package/dist/components/Menu/index.js +2 -0
- package/dist/components/Popover/Popover.d.ts +122 -0
- package/dist/components/Popover/Popover.js +116 -0
- package/dist/components/Popover/index.d.ts +2 -0
- package/dist/components/Popover/index.js +2 -0
- package/dist/components/Progress/Progress.d.ts +87 -0
- package/dist/components/Progress/Progress.js +73 -0
- package/dist/components/Progress/index.d.ts +2 -0
- package/dist/components/Progress/index.js +2 -0
- package/dist/components/Radio/Radio.d.ts +65 -0
- package/dist/components/Radio/Radio.js +93 -0
- package/dist/components/Radio/index.d.ts +2 -0
- package/dist/components/Radio/index.js +2 -0
- package/dist/components/Select/Select.d.ts +136 -0
- package/dist/components/Select/Select.js +219 -0
- package/dist/components/Select/index.d.ts +2 -0
- package/dist/components/Select/index.js +2 -0
- package/dist/components/Skeleton/Skeleton.d.ts +39 -0
- package/dist/components/Skeleton/Skeleton.js +44 -0
- package/dist/components/Skeleton/index.d.ts +2 -0
- package/dist/components/Skeleton/index.js +2 -0
- package/dist/components/Stepper/Stepper.d.ts +161 -0
- package/dist/components/Stepper/Stepper.js +344 -0
- package/dist/components/Stepper/index.d.ts +2 -0
- package/dist/components/Stepper/index.js +2 -0
- package/dist/components/Switch/Switch.d.ts +56 -0
- package/dist/components/Switch/Switch.js +87 -0
- package/dist/components/Switch/index.d.ts +2 -0
- package/dist/components/Switch/index.js +2 -0
- package/dist/components/Table/Table.d.ts +116 -0
- package/dist/components/Table/Table.js +143 -0
- package/dist/components/Table/index.d.ts +2 -0
- package/dist/components/Table/index.js +2 -0
- package/dist/components/Tabs/Tabs.d.ts +116 -0
- package/dist/components/Tabs/Tabs.js +158 -0
- package/dist/components/Tabs/index.d.ts +2 -0
- package/dist/components/Tabs/index.js +2 -0
- package/dist/components/Timeline/Timeline.d.ts +137 -0
- package/dist/components/Timeline/Timeline.js +243 -0
- package/dist/components/Timeline/index.d.ts +2 -0
- package/dist/components/Timeline/index.js +2 -0
- package/dist/components/Toast/Toast.d.ts +135 -0
- package/dist/components/Toast/Toast.js +314 -0
- package/dist/components/Toast/index.d.ts +2 -0
- package/dist/components/Toast/index.js +2 -0
- package/dist/components/Tooltip/Tooltip.d.ts +104 -0
- package/dist/components/Tooltip/Tooltip.js +95 -0
- package/dist/components/Tooltip/index.d.ts +2 -0
- package/dist/components/Tooltip/index.js +2 -0
- package/dist/components/Typography/Typography.d.ts +38 -0
- package/dist/components/Typography/Typography.js +53 -0
- package/dist/components/Typography/index.d.ts +2 -0
- package/dist/components/Typography/index.js +2 -0
- package/dist/index.d.ts +66 -3398
- package/dist/index.js +34 -5343
- package/dist/lib/cn.d.ts +6 -0
- package/dist/lib/cn.js +9 -0
- package/package.json +6 -2
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { cn } from "../../lib/cn.js";
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { Toast } from "@base-ui/react/toast";
|
|
5
|
+
//#region src/components/Toast/Toast.tsx
|
|
6
|
+
/**
|
|
7
|
+
* Creates an isolated toast manager for a scoped `<Toaster />` (a preview
|
|
8
|
+
* frame, a second stack with different placement, tests). Pass it to that
|
|
9
|
+
* Toaster's `toastManager` prop and call `manager.add/close/update/promise`
|
|
10
|
+
* on it directly — the `toast` helpers always target the built-in default
|
|
11
|
+
* manager, not scoped ones.
|
|
12
|
+
*/
|
|
13
|
+
const createToastManager = Toast.createToastManager;
|
|
14
|
+
const viewportBaseClasses = "fixed z-[60] w-[calc(100vw-2rem)] sm:w-[22.5rem] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring";
|
|
15
|
+
const viewportPositionClasses = {
|
|
16
|
+
"top-left": "top-4 left-4 sm:top-8 sm:left-8",
|
|
17
|
+
"top-center": "top-4 right-0 left-0 mx-auto sm:top-8",
|
|
18
|
+
"top-right": "top-4 right-4 sm:top-8 sm:right-8",
|
|
19
|
+
"bottom-left": "bottom-4 left-4 sm:bottom-8 sm:left-8",
|
|
20
|
+
"bottom-center": "bottom-4 right-0 left-0 mx-auto sm:bottom-8",
|
|
21
|
+
"bottom-right": "bottom-4 right-4 sm:bottom-8 sm:right-8"
|
|
22
|
+
};
|
|
23
|
+
const swipeDirections = {
|
|
24
|
+
"top-left": ["up", "left"],
|
|
25
|
+
"top-center": ["up"],
|
|
26
|
+
"top-right": ["up", "right"],
|
|
27
|
+
"bottom-left": ["down", "left"],
|
|
28
|
+
"bottom-center": ["down"],
|
|
29
|
+
"bottom-right": ["down", "right"]
|
|
30
|
+
};
|
|
31
|
+
const rootBaseClasses = "[--gap:0.75rem] [--peek:0.75rem] [--scale:calc(max(0,1-(var(--toast-index)*0.1)))] [--shrink:calc(1-var(--scale))] [--height:var(--toast-frontmost-height,var(--toast-height))] absolute right-0 left-0 z-[calc(1000-var(--toast-index))] mx-auto w-full select-none h-[var(--height)] data-expanded:h-[var(--toast-height)] rounded-md border border-border bg-background text-foreground shadow-lg focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring data-ending-style:opacity-0 data-limited:opacity-0 after:absolute after:left-0 after:h-[calc(var(--gap)+1px)] after:w-full after:content-[''] motion-safe:[transition:transform_0.5s_cubic-bezier(0.22,1,0.36,1),opacity_0.5s,height_0.15s] data-expanded:[transform:translateX(var(--toast-swipe-movement-x))_translateY(var(--offset-y))] data-ending-style:data-[swipe-direction=up]:[transform:translateY(calc(var(--toast-swipe-movement-y)-150%))] data-expanded:data-ending-style:data-[swipe-direction=up]:[transform:translateY(calc(var(--toast-swipe-movement-y)-150%))] data-ending-style:data-[swipe-direction=down]:[transform:translateY(calc(var(--toast-swipe-movement-y)+150%))] data-expanded:data-ending-style:data-[swipe-direction=down]:[transform:translateY(calc(var(--toast-swipe-movement-y)+150%))] data-ending-style:data-[swipe-direction=left]:[transform:translateX(calc(var(--toast-swipe-movement-x)-150%))_translateY(var(--offset-y))] data-expanded:data-ending-style:data-[swipe-direction=left]:[transform:translateX(calc(var(--toast-swipe-movement-x)-150%))_translateY(var(--offset-y))] data-ending-style:data-[swipe-direction=right]:[transform:translateX(calc(var(--toast-swipe-movement-x)+150%))_translateY(var(--offset-y))] data-expanded:data-ending-style:data-[swipe-direction=right]:[transform:translateX(calc(var(--toast-swipe-movement-x)+150%))_translateY(var(--offset-y))]";
|
|
32
|
+
const rootBottomClasses = "bottom-0 origin-bottom after:top-full [--offset-y:calc(var(--toast-offset-y)*-1+calc(var(--toast-index)*var(--gap)*-1)+var(--toast-swipe-movement-y))] [transform:translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)-(var(--toast-index)*var(--peek))-(var(--shrink)*var(--height))))_scale(var(--scale))] data-starting-style:[transform:translateY(150%)] [&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:[transform:translateY(150%)]";
|
|
33
|
+
const rootTopClasses = "top-0 origin-top after:bottom-full [--offset-y:calc(var(--toast-offset-y)+(var(--toast-index)*var(--gap))+var(--toast-swipe-movement-y))] [transform:translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)+(var(--toast-index)*var(--peek))+(var(--shrink)*var(--height))))_scale(var(--scale))] data-starting-style:[transform:translateY(-150%)] [&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:[transform:translateY(-150%)]";
|
|
34
|
+
const contentClasses = "flex h-full items-start gap-3 overflow-hidden p-4 motion-safe:[transition:opacity_250ms_cubic-bezier(0.22,1,0.36,1)] data-behind:opacity-0 data-expanded:opacity-100";
|
|
35
|
+
const iconSlotClasses = "flex shrink-0 items-center [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-5";
|
|
36
|
+
const titleClasses = "m-0 font-sans text-sm font-semibold text-foreground";
|
|
37
|
+
const descriptionClasses = "m-0 font-sans text-sm text-muted-foreground";
|
|
38
|
+
const actionClasses = "inline-flex h-7 shrink-0 cursor-pointer items-center justify-center rounded-md border border-border bg-background px-2.5 font-sans text-xs font-semibold whitespace-nowrap text-foreground transition-colors duration-150 hover:bg-muted active:bg-slate-200 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring";
|
|
39
|
+
const closeClasses = "inline-flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors duration-150 hover:bg-muted hover:text-foreground active:bg-slate-200 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring";
|
|
40
|
+
function SuccessIcon(props) {
|
|
41
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
42
|
+
viewBox: "0 0 24 24",
|
|
43
|
+
fill: "none",
|
|
44
|
+
stroke: "currentColor",
|
|
45
|
+
strokeWidth: 2,
|
|
46
|
+
strokeLinecap: "round",
|
|
47
|
+
strokeLinejoin: "round",
|
|
48
|
+
"aria-hidden": "true",
|
|
49
|
+
...props,
|
|
50
|
+
children: [/* @__PURE__ */ jsx("circle", {
|
|
51
|
+
cx: "12",
|
|
52
|
+
cy: "12",
|
|
53
|
+
r: "9"
|
|
54
|
+
}), /* @__PURE__ */ jsx("path", { d: "m8.5 12.4 2.4 2.4 4.6-5.2" })]
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function ErrorIcon(props) {
|
|
58
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
59
|
+
viewBox: "0 0 24 24",
|
|
60
|
+
fill: "none",
|
|
61
|
+
stroke: "currentColor",
|
|
62
|
+
strokeWidth: 2,
|
|
63
|
+
strokeLinecap: "round",
|
|
64
|
+
strokeLinejoin: "round",
|
|
65
|
+
"aria-hidden": "true",
|
|
66
|
+
...props,
|
|
67
|
+
children: [/* @__PURE__ */ jsx("circle", {
|
|
68
|
+
cx: "12",
|
|
69
|
+
cy: "12",
|
|
70
|
+
r: "9"
|
|
71
|
+
}), /* @__PURE__ */ jsx("path", { d: "m9.5 9.5 5 5m0-5-5 5" })]
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function WarningIcon(props) {
|
|
75
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
76
|
+
viewBox: "0 0 24 24",
|
|
77
|
+
fill: "none",
|
|
78
|
+
stroke: "currentColor",
|
|
79
|
+
strokeWidth: 2,
|
|
80
|
+
strokeLinecap: "round",
|
|
81
|
+
strokeLinejoin: "round",
|
|
82
|
+
"aria-hidden": "true",
|
|
83
|
+
...props,
|
|
84
|
+
children: [
|
|
85
|
+
/* @__PURE__ */ jsx("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 20h16a2 2 0 0 0 1.73-2Z" }),
|
|
86
|
+
/* @__PURE__ */ jsx("path", { d: "M12 9v4" }),
|
|
87
|
+
/* @__PURE__ */ jsx("path", { d: "M12 17h.01" })
|
|
88
|
+
]
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function InfoIcon(props) {
|
|
92
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
93
|
+
viewBox: "0 0 24 24",
|
|
94
|
+
fill: "none",
|
|
95
|
+
stroke: "currentColor",
|
|
96
|
+
strokeWidth: 2,
|
|
97
|
+
strokeLinecap: "round",
|
|
98
|
+
strokeLinejoin: "round",
|
|
99
|
+
"aria-hidden": "true",
|
|
100
|
+
...props,
|
|
101
|
+
children: [
|
|
102
|
+
/* @__PURE__ */ jsx("circle", {
|
|
103
|
+
cx: "12",
|
|
104
|
+
cy: "12",
|
|
105
|
+
r: "9"
|
|
106
|
+
}),
|
|
107
|
+
/* @__PURE__ */ jsx("path", { d: "M12 16v-4" }),
|
|
108
|
+
/* @__PURE__ */ jsx("path", { d: "M12 8h.01" })
|
|
109
|
+
]
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
function SpinnerIcon({ className, ...props }) {
|
|
113
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
114
|
+
viewBox: "0 0 24 24",
|
|
115
|
+
fill: "none",
|
|
116
|
+
"aria-hidden": "true",
|
|
117
|
+
className: cn("animate-spin", className),
|
|
118
|
+
...props,
|
|
119
|
+
children: [/* @__PURE__ */ jsx("circle", {
|
|
120
|
+
cx: "12",
|
|
121
|
+
cy: "12",
|
|
122
|
+
r: "10",
|
|
123
|
+
stroke: "currentColor",
|
|
124
|
+
strokeWidth: "4",
|
|
125
|
+
className: "opacity-25"
|
|
126
|
+
}), /* @__PURE__ */ jsx("path", {
|
|
127
|
+
fill: "currentColor",
|
|
128
|
+
className: "opacity-75",
|
|
129
|
+
d: "M4 12a8 8 0 0 1 8-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 0 1 4 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
130
|
+
})]
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function XIcon(props) {
|
|
134
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
135
|
+
viewBox: "0 0 16 16",
|
|
136
|
+
fill: "none",
|
|
137
|
+
stroke: "currentColor",
|
|
138
|
+
strokeWidth: 1.5,
|
|
139
|
+
strokeLinecap: "round",
|
|
140
|
+
"aria-hidden": "true",
|
|
141
|
+
className: "size-4",
|
|
142
|
+
...props,
|
|
143
|
+
children: /* @__PURE__ */ jsx("path", { d: "m3.5 3.5 9 9m-9 0 9-9" })
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
const typeIcons = {
|
|
147
|
+
success: /* @__PURE__ */ jsx(SuccessIcon, { className: "text-success" }),
|
|
148
|
+
error: /* @__PURE__ */ jsx(ErrorIcon, { className: "text-destructive" }),
|
|
149
|
+
warning: /* @__PURE__ */ jsx(WarningIcon, { className: "text-warning-700" }),
|
|
150
|
+
info: /* @__PURE__ */ jsx(InfoIcon, { className: "text-info" }),
|
|
151
|
+
loading: /* @__PURE__ */ jsx(SpinnerIcon, { className: "text-muted-foreground" })
|
|
152
|
+
};
|
|
153
|
+
const defaultToastManager = Toast.createToastManager();
|
|
154
|
+
function toTitleOptions(value) {
|
|
155
|
+
return typeof value === "string" ? { title: value } : value;
|
|
156
|
+
}
|
|
157
|
+
function normalizePromiseState(state) {
|
|
158
|
+
return typeof state === "function" ? (arg) => toTitleOptions(state(arg)) : toTitleOptions(state);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Imperative toast API, callable from anywhere — components, stores, fetch
|
|
162
|
+
* wrappers. Requires one default `<Toaster />` (no `toastManager` prop)
|
|
163
|
+
* mounted in the app. Every method accepts Base UI's full option set
|
|
164
|
+
* (`description`, `timeout`, `priority`, `onClose`, `actionProps`,
|
|
165
|
+
* `data.icon`, …); `add` with an existing `id` updates that toast in place,
|
|
166
|
+
* which is how repeated events deduplicate.
|
|
167
|
+
*/
|
|
168
|
+
const toast = {
|
|
169
|
+
/** Queue a toast with full control over its options. Returns the toast id. */
|
|
170
|
+
add(options) {
|
|
171
|
+
return defaultToastManager.add(options);
|
|
172
|
+
},
|
|
173
|
+
/** Success feedback: green check icon, polite announcement. */
|
|
174
|
+
success(title, options = {}) {
|
|
175
|
+
return defaultToastManager.add({
|
|
176
|
+
...options,
|
|
177
|
+
type: "success",
|
|
178
|
+
title
|
|
179
|
+
});
|
|
180
|
+
},
|
|
181
|
+
/** Informational notice: blue info icon, polite announcement. */
|
|
182
|
+
info(title, options = {}) {
|
|
183
|
+
return defaultToastManager.add({
|
|
184
|
+
...options,
|
|
185
|
+
type: "info",
|
|
186
|
+
title
|
|
187
|
+
});
|
|
188
|
+
},
|
|
189
|
+
/** Warning: amber triangle icon, polite announcement. */
|
|
190
|
+
warning(title, options = {}) {
|
|
191
|
+
return defaultToastManager.add({
|
|
192
|
+
...options,
|
|
193
|
+
type: "warning",
|
|
194
|
+
title
|
|
195
|
+
});
|
|
196
|
+
},
|
|
197
|
+
/**
|
|
198
|
+
* Failure feedback: red icon, announced assertively (`priority: "high"`)
|
|
199
|
+
* so screen readers interrupt with it, as errors warrant. For critical
|
|
200
|
+
* errors the user must act on, add `timeout: 0` so the toast persists.
|
|
201
|
+
*/
|
|
202
|
+
error(title, options = {}) {
|
|
203
|
+
return defaultToastManager.add({
|
|
204
|
+
priority: "high",
|
|
205
|
+
...options,
|
|
206
|
+
type: "error",
|
|
207
|
+
title
|
|
208
|
+
});
|
|
209
|
+
},
|
|
210
|
+
/**
|
|
211
|
+
* Spinner toast for manual async flows. Never auto-dismisses (the
|
|
212
|
+
* operation decides when it ends) — resolve it via
|
|
213
|
+
* `toast.update(id, { type: "success", … })` or `toast.close(id)`.
|
|
214
|
+
* Prefer `toast.promise` when a promise already models the operation.
|
|
215
|
+
*/
|
|
216
|
+
loading(title, options = {}) {
|
|
217
|
+
return defaultToastManager.add({
|
|
218
|
+
timeout: 0,
|
|
219
|
+
...options,
|
|
220
|
+
type: "loading",
|
|
221
|
+
title
|
|
222
|
+
});
|
|
223
|
+
},
|
|
224
|
+
/**
|
|
225
|
+
* One toast tracking a promise through loading → success/error, switching
|
|
226
|
+
* `type` (spinner → check/cross) at each step. States take a string
|
|
227
|
+
* (shorthand for the title), an options object, or — for
|
|
228
|
+
* `success`/`error` — a function of the resolved value/rejection reason.
|
|
229
|
+
* Returns the input promise's result, so it can be awaited in place.
|
|
230
|
+
*/
|
|
231
|
+
promise(promise, options) {
|
|
232
|
+
return defaultToastManager.promise(promise, {
|
|
233
|
+
loading: toTitleOptions(options.loading),
|
|
234
|
+
success: normalizePromiseState(options.success),
|
|
235
|
+
error: normalizePromiseState(options.error)
|
|
236
|
+
});
|
|
237
|
+
},
|
|
238
|
+
/** Update a queued toast in place (content, type, timing) by id. */
|
|
239
|
+
update(toastId, options) {
|
|
240
|
+
defaultToastManager.update(toastId, options);
|
|
241
|
+
},
|
|
242
|
+
/** Close one toast by id, or every toast when called with no argument. */
|
|
243
|
+
close(toastId) {
|
|
244
|
+
defaultToastManager.close(toastId);
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
function ToastIcon({ toastObject }) {
|
|
248
|
+
const icon = toastObject.data?.icon ?? (toastObject.type == null ? null : typeIcons[toastObject.type]);
|
|
249
|
+
if (icon == null) return null;
|
|
250
|
+
return /* @__PURE__ */ jsx("span", {
|
|
251
|
+
"aria-hidden": "true",
|
|
252
|
+
className: iconSlotClasses,
|
|
253
|
+
children: icon
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
function ToastList({ position, closeLabel }) {
|
|
257
|
+
const { toasts } = Toast.useToastManager();
|
|
258
|
+
return toasts.map((toastObject) => /* @__PURE__ */ jsx(Toast.Root, {
|
|
259
|
+
toast: toastObject,
|
|
260
|
+
swipeDirection: swipeDirections[position],
|
|
261
|
+
className: cn(rootBaseClasses, position.startsWith("top") ? rootTopClasses : rootBottomClasses),
|
|
262
|
+
children: /* @__PURE__ */ jsxs(Toast.Content, {
|
|
263
|
+
className: contentClasses,
|
|
264
|
+
children: [
|
|
265
|
+
/* @__PURE__ */ jsx(ToastIcon, { toastObject }),
|
|
266
|
+
/* @__PURE__ */ jsxs("div", {
|
|
267
|
+
className: "flex min-w-0 flex-1 flex-col gap-1",
|
|
268
|
+
children: [/* @__PURE__ */ jsx(Toast.Title, { className: titleClasses }), /* @__PURE__ */ jsx(Toast.Description, { className: descriptionClasses })]
|
|
269
|
+
}),
|
|
270
|
+
toastObject.actionProps != null && /* @__PURE__ */ jsx(Toast.Action, { className: actionClasses }),
|
|
271
|
+
/* @__PURE__ */ jsx(Toast.Close, {
|
|
272
|
+
"aria-label": closeLabel,
|
|
273
|
+
className: closeClasses,
|
|
274
|
+
children: /* @__PURE__ */ jsx(XIcon, {})
|
|
275
|
+
})
|
|
276
|
+
]
|
|
277
|
+
})
|
|
278
|
+
}, toastObject.id));
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* The toast stack. Mount one per app (typically at the root); after that,
|
|
282
|
+
* `toast.success("Saved")` & co. work from anywhere. Bundles Base UI's
|
|
283
|
+
* Provider, Portal, and Viewport with fully styled toasts: severity icon,
|
|
284
|
+
* title, description, optional action button, and an always-visible
|
|
285
|
+
* dismiss button.
|
|
286
|
+
*
|
|
287
|
+
* Collapsed toasts stack with a peek; hovering or focusing the stack
|
|
288
|
+
* expands it and pauses dismiss timers. Every toast can be dismissed by
|
|
289
|
+
* pointer (×), swipe, or keyboard, and F6 jumps focus into the stack.
|
|
290
|
+
* Announcements use the toast's `title`/`description` strings — polite by
|
|
291
|
+
* default, assertive for `priority: "high"`. The stack portals to `<body>`;
|
|
292
|
+
* consumer apps should set `isolation: isolate` on their root so page
|
|
293
|
+
* stacking contexts stay below it.
|
|
294
|
+
*/
|
|
295
|
+
const Toaster = forwardRef(({ position = "bottom-right", limit = 3, timeout = 5e3, toastManager, container, closeLabel = "Close", className, ...rest }, ref) => /* @__PURE__ */ jsx(Toast.Provider, {
|
|
296
|
+
limit,
|
|
297
|
+
timeout,
|
|
298
|
+
toastManager: toastManager ?? defaultToastManager,
|
|
299
|
+
children: /* @__PURE__ */ jsx(Toast.Portal, {
|
|
300
|
+
container,
|
|
301
|
+
children: /* @__PURE__ */ jsx(Toast.Viewport, {
|
|
302
|
+
ref,
|
|
303
|
+
className: cn(viewportBaseClasses, viewportPositionClasses[position], className),
|
|
304
|
+
...rest,
|
|
305
|
+
children: /* @__PURE__ */ jsx(ToastList, {
|
|
306
|
+
position,
|
|
307
|
+
closeLabel
|
|
308
|
+
})
|
|
309
|
+
})
|
|
310
|
+
})
|
|
311
|
+
}));
|
|
312
|
+
Toaster.displayName = "Toaster";
|
|
313
|
+
//#endregion
|
|
314
|
+
export { Toaster, createToastManager, toast };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { ToastData, ToastManager, ToastObject, ToastOptions, ToastPosition, ToastPromiseOptions, ToastType, ToastUpdateOptions, Toaster, ToasterProps, createToastManager, toast } from "./Toast.js";
|
|
2
|
+
export { type ToastData, type ToastManager, type ToastObject, type ToastOptions, type ToastPosition, type ToastPromiseOptions, type ToastType, type ToastUpdateOptions, Toaster, type ToasterProps, createToastManager, toast };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { ComponentPropsWithoutRef } from "react";
|
|
2
|
+
import { Tooltip } from "@base-ui/react/tooltip";
|
|
3
|
+
//#region src/components/Tooltip/Tooltip.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Shares tooltip timing for every tooltip inside it: `delay`/`closeDelay`
|
|
6
|
+
* set the subtree's defaults, and once one tooltip has shown, moving to a
|
|
7
|
+
* nearby trigger within `timeout` (400ms) opens the next tooltip instantly
|
|
8
|
+
* instead of re-waiting the open delay. Mount one around toolbars and icon
|
|
9
|
+
* rows (or once at the app root) — without it every tooltip waits the full
|
|
10
|
+
* delay on its own.
|
|
11
|
+
*/
|
|
12
|
+
declare const TooltipProvider: import("react").FC<import("@base-ui/react").TooltipProviderProps>;
|
|
13
|
+
type TooltipProviderProps = ComponentPropsWithoutRef<typeof Tooltip.Provider>;
|
|
14
|
+
/**
|
|
15
|
+
* Groups the tooltip parts and owns the open state. Accepts Base UI's Root
|
|
16
|
+
* props: `open`/`defaultOpen`/`onOpenChange` for control, `disabled` to keep
|
|
17
|
+
* the tooltip from opening, `trackCursorAxis` to follow the pointer (chart
|
|
18
|
+
* and canvas surfaces), `actionsRef` for imperative close, and
|
|
19
|
+
* `handle`/`triggerId` for detached triggers.
|
|
20
|
+
*/
|
|
21
|
+
declare const Tooltip$1: <Payload>(props: Tooltip.Root.Props<Payload>) => import("react").JSX.Element;
|
|
22
|
+
type TooltipProps = ComponentPropsWithoutRef<typeof Tooltip.Root>;
|
|
23
|
+
/**
|
|
24
|
+
* Creates a handle that links `Tooltip` with `TooltipTrigger`s rendered
|
|
25
|
+
* elsewhere in the tree (table rows, toolbars). Triggers may attach a
|
|
26
|
+
* `payload`, which the `Tooltip` children render function receives — one
|
|
27
|
+
* mounted tooltip serving many targets.
|
|
28
|
+
*/
|
|
29
|
+
declare const createTooltipHandle: typeof Tooltip.createHandle;
|
|
30
|
+
type TooltipHandle<Payload = unknown> = Tooltip.Handle<Payload>;
|
|
31
|
+
interface TooltipTriggerProps extends Omit<ComponentPropsWithoutRef<typeof Tooltip.Trigger>, "className"> {
|
|
32
|
+
className?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The element the tooltip describes. A `<button>` by default and unstyled on
|
|
36
|
+
* purpose — compose the real control via `render`:
|
|
37
|
+
*
|
|
38
|
+
* <TooltipTrigger render={<Button iconOnly aria-label="Delete" />}>
|
|
39
|
+
* <TrashIcon />
|
|
40
|
+
* </TooltipTrigger>
|
|
41
|
+
*
|
|
42
|
+
* The popup text is invisible to assistive technology (see `TooltipPopup`),
|
|
43
|
+
* so the trigger must carry its own accessible name — icon-only Buttons
|
|
44
|
+
* already enforce one at the type level. Non-interactive targets (truncated
|
|
45
|
+
* text, a wrapper around a disabled control) need `render={<span tabIndex={0} />}`
|
|
46
|
+
* so keyboard users can focus them to see the hint. Per-trigger timing comes
|
|
47
|
+
* from `delay`/`closeDelay` (600/0ms defaults); while its tooltip is open the
|
|
48
|
+
* element carries `data-popup-open` as a styling hook.
|
|
49
|
+
*/
|
|
50
|
+
declare const TooltipTrigger: import("react").ForwardRefExoticComponent<TooltipTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
51
|
+
type BasePositionerProps = ComponentPropsWithoutRef<typeof Tooltip.Positioner>;
|
|
52
|
+
type TooltipSide = NonNullable<BasePositionerProps["side"]>;
|
|
53
|
+
type TooltipAlign = NonNullable<BasePositionerProps["align"]>;
|
|
54
|
+
interface TooltipPopupVariantsOptions {
|
|
55
|
+
className?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Class list for an element styled as the tooltip chip — for floating hints
|
|
59
|
+
* that don't come from Base UI (chart hover tooltips, custom floating-ui
|
|
60
|
+
* popups) so every hint in the product shares one look.
|
|
61
|
+
*/
|
|
62
|
+
declare function tooltipPopupVariants({ className }?: TooltipPopupVariantsOptions): string;
|
|
63
|
+
interface TooltipPopupProps extends Omit<ComponentPropsWithoutRef<typeof Tooltip.Popup>, "className"> {
|
|
64
|
+
/** Side of the trigger to place the tooltip on; flips automatically when there is no room. */
|
|
65
|
+
side?: TooltipSide;
|
|
66
|
+
/** How the tooltip lines up along the chosen side. */
|
|
67
|
+
align?: TooltipAlign;
|
|
68
|
+
/** Gap between trigger and tooltip in pixels. The default 8px leaves room for the `arrow`. */
|
|
69
|
+
sideOffset?: BasePositionerProps["sideOffset"];
|
|
70
|
+
/** Additional shift along the alignment axis in pixels. */
|
|
71
|
+
alignOffset?: BasePositionerProps["alignOffset"];
|
|
72
|
+
/** Minimum space kept from the viewport (or collision boundary) edges when repositioning. */
|
|
73
|
+
collisionPadding?: BasePositionerProps["collisionPadding"];
|
|
74
|
+
/** Position against this element instead of the trigger (e.g. a chart point or a text selection). */
|
|
75
|
+
anchor?: BasePositionerProps["anchor"];
|
|
76
|
+
/** Keep the closed tooltip in the DOM — for measuring; closed tooltips normally unmount. */
|
|
77
|
+
keepMounted?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Portal destination. Defaults to `document.body`. When the tooltip renders
|
|
80
|
+
* open on first paint (`defaultOpen`) and the container mounts in the same
|
|
81
|
+
* commit, pass the element via callback-ref state — a `RefObject` to an
|
|
82
|
+
* ancestor is not attached yet when the portal first resolves.
|
|
83
|
+
*/
|
|
84
|
+
container?: ComponentPropsWithoutRef<typeof Tooltip.Portal>["container"];
|
|
85
|
+
/** Caret pointing at the trigger. On by default — it ties the hint to small targets in dense rows. */
|
|
86
|
+
arrow?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Applied to the popup chip. The chip is content-sized up to 17.5rem —
|
|
89
|
+
* set `max-w-*` to change the cap.
|
|
90
|
+
*/
|
|
91
|
+
className?: string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The floating hint, with the portal and positioning plumbing folded in.
|
|
95
|
+
* Text only: the popup never receives focus and Base UI exposes none of it
|
|
96
|
+
* to assistive technology, so it must stay a redundant visual label — never
|
|
97
|
+
* the sole carrier of essential information (tooltips also cannot open on
|
|
98
|
+
* touch), and never a host for links or buttons (that content belongs in a
|
|
99
|
+
* Popover). Stays open while the pointer is over the trigger or the popup,
|
|
100
|
+
* and Escape dismisses it (WCAG 1.4.13).
|
|
101
|
+
*/
|
|
102
|
+
declare const TooltipPopup: import("react").ForwardRefExoticComponent<TooltipPopupProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
103
|
+
//#endregion
|
|
104
|
+
export { Tooltip$1 as Tooltip, TooltipAlign, TooltipHandle, TooltipPopup, TooltipPopupProps, TooltipPopupVariantsOptions, TooltipProps, TooltipProvider, TooltipProviderProps, TooltipSide, TooltipTrigger, TooltipTriggerProps, createTooltipHandle, tooltipPopupVariants };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { cn } from "../../lib/cn.js";
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { Tooltip } from "@base-ui/react/tooltip";
|
|
5
|
+
//#region src/components/Tooltip/Tooltip.tsx
|
|
6
|
+
/**
|
|
7
|
+
* Shares tooltip timing for every tooltip inside it: `delay`/`closeDelay`
|
|
8
|
+
* set the subtree's defaults, and once one tooltip has shown, moving to a
|
|
9
|
+
* nearby trigger within `timeout` (400ms) opens the next tooltip instantly
|
|
10
|
+
* instead of re-waiting the open delay. Mount one around toolbars and icon
|
|
11
|
+
* rows (or once at the app root) — without it every tooltip waits the full
|
|
12
|
+
* delay on its own.
|
|
13
|
+
*/
|
|
14
|
+
const TooltipProvider = Tooltip.Provider;
|
|
15
|
+
/**
|
|
16
|
+
* Groups the tooltip parts and owns the open state. Accepts Base UI's Root
|
|
17
|
+
* props: `open`/`defaultOpen`/`onOpenChange` for control, `disabled` to keep
|
|
18
|
+
* the tooltip from opening, `trackCursorAxis` to follow the pointer (chart
|
|
19
|
+
* and canvas surfaces), `actionsRef` for imperative close, and
|
|
20
|
+
* `handle`/`triggerId` for detached triggers.
|
|
21
|
+
*/
|
|
22
|
+
const Tooltip$1 = Tooltip.Root;
|
|
23
|
+
/**
|
|
24
|
+
* Creates a handle that links `Tooltip` with `TooltipTrigger`s rendered
|
|
25
|
+
* elsewhere in the tree (table rows, toolbars). Triggers may attach a
|
|
26
|
+
* `payload`, which the `Tooltip` children render function receives — one
|
|
27
|
+
* mounted tooltip serving many targets.
|
|
28
|
+
*/
|
|
29
|
+
const createTooltipHandle = Tooltip.createHandle;
|
|
30
|
+
/**
|
|
31
|
+
* The element the tooltip describes. A `<button>` by default and unstyled on
|
|
32
|
+
* purpose — compose the real control via `render`:
|
|
33
|
+
*
|
|
34
|
+
* <TooltipTrigger render={<Button iconOnly aria-label="Delete" />}>
|
|
35
|
+
* <TrashIcon />
|
|
36
|
+
* </TooltipTrigger>
|
|
37
|
+
*
|
|
38
|
+
* The popup text is invisible to assistive technology (see `TooltipPopup`),
|
|
39
|
+
* so the trigger must carry its own accessible name — icon-only Buttons
|
|
40
|
+
* already enforce one at the type level. Non-interactive targets (truncated
|
|
41
|
+
* text, a wrapper around a disabled control) need `render={<span tabIndex={0} />}`
|
|
42
|
+
* so keyboard users can focus them to see the hint. Per-trigger timing comes
|
|
43
|
+
* from `delay`/`closeDelay` (600/0ms defaults); while its tooltip is open the
|
|
44
|
+
* element carries `data-popup-open` as a styling hook.
|
|
45
|
+
*/
|
|
46
|
+
const TooltipTrigger = forwardRef(({ className, ...rest }, ref) => /* @__PURE__ */ jsx(Tooltip.Trigger, {
|
|
47
|
+
ref,
|
|
48
|
+
className,
|
|
49
|
+
...rest
|
|
50
|
+
}));
|
|
51
|
+
TooltipTrigger.displayName = "TooltipTrigger";
|
|
52
|
+
const popupSurfaceClasses = "rounded-md bg-foreground px-3 py-1.5 font-sans text-xs text-balance text-background shadow-sm";
|
|
53
|
+
const popupBehaviorClasses = "origin-[var(--transform-origin)] max-w-[min(17.5rem,var(--available-width))] motion-safe:transition-[scale,opacity] motion-safe:duration-100 motion-safe:ease-out data-starting-style:scale-95 data-starting-style:opacity-0 data-ending-style:scale-95 data-ending-style:opacity-0 data-instant:transition-none!";
|
|
54
|
+
const arrowClasses = "relative block h-1.5 w-3 overflow-clip data-[side=bottom]:top-[-6px] data-[side=top]:bottom-[-6px] data-[side=top]:rotate-180 data-[side=left]:right-[-9px] data-[side=left]:rotate-90 data-[side=right]:left-[-9px] data-[side=right]:-rotate-90 before:absolute before:bottom-0 before:left-1/2 before:h-[calc(6px*sqrt(2))] before:w-[calc(6px*sqrt(2))] before:bg-foreground before:content-[''] before:[transform:translate(-50%,50%)_rotate(45deg)]";
|
|
55
|
+
const ARROW_PADDING = 8;
|
|
56
|
+
/**
|
|
57
|
+
* Class list for an element styled as the tooltip chip — for floating hints
|
|
58
|
+
* that don't come from Base UI (chart hover tooltips, custom floating-ui
|
|
59
|
+
* popups) so every hint in the product shares one look.
|
|
60
|
+
*/
|
|
61
|
+
function tooltipPopupVariants({ className } = {}) {
|
|
62
|
+
return cn(popupSurfaceClasses, className);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The floating hint, with the portal and positioning plumbing folded in.
|
|
66
|
+
* Text only: the popup never receives focus and Base UI exposes none of it
|
|
67
|
+
* to assistive technology, so it must stay a redundant visual label — never
|
|
68
|
+
* the sole carrier of essential information (tooltips also cannot open on
|
|
69
|
+
* touch), and never a host for links or buttons (that content belongs in a
|
|
70
|
+
* Popover). Stays open while the pointer is over the trigger or the popup,
|
|
71
|
+
* and Escape dismisses it (WCAG 1.4.13).
|
|
72
|
+
*/
|
|
73
|
+
const TooltipPopup = forwardRef(({ side = "top", align = "center", sideOffset = 8, alignOffset = 0, collisionPadding, anchor, keepMounted = false, container, arrow = true, className, children, ...rest }, ref) => /* @__PURE__ */ jsx(Tooltip.Portal, {
|
|
74
|
+
container,
|
|
75
|
+
keepMounted,
|
|
76
|
+
children: /* @__PURE__ */ jsx(Tooltip.Positioner, {
|
|
77
|
+
side,
|
|
78
|
+
align,
|
|
79
|
+
sideOffset,
|
|
80
|
+
alignOffset,
|
|
81
|
+
collisionPadding,
|
|
82
|
+
anchor,
|
|
83
|
+
arrowPadding: ARROW_PADDING,
|
|
84
|
+
className: "z-50",
|
|
85
|
+
children: /* @__PURE__ */ jsxs(Tooltip.Popup, {
|
|
86
|
+
ref,
|
|
87
|
+
className: cn(popupSurfaceClasses, popupBehaviorClasses, className),
|
|
88
|
+
...rest,
|
|
89
|
+
children: [arrow && /* @__PURE__ */ jsx(Tooltip.Arrow, { className: arrowClasses }), children]
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
}));
|
|
93
|
+
TooltipPopup.displayName = "TooltipPopup";
|
|
94
|
+
//#endregion
|
|
95
|
+
export { Tooltip$1 as Tooltip, TooltipPopup, TooltipProvider, TooltipTrigger, createTooltipHandle, tooltipPopupVariants };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { Tooltip, TooltipAlign, TooltipHandle, TooltipPopup, TooltipPopupProps, TooltipPopupVariantsOptions, TooltipProps, TooltipProvider, TooltipProviderProps, TooltipSide, TooltipTrigger, TooltipTriggerProps, createTooltipHandle, tooltipPopupVariants } from "./Tooltip.js";
|
|
2
|
+
export { Tooltip, type TooltipAlign, type TooltipHandle, TooltipPopup, type TooltipPopupProps, type TooltipPopupVariantsOptions, type TooltipProps, TooltipProvider, type TooltipProviderProps, type TooltipSide, TooltipTrigger, type TooltipTriggerProps, createTooltipHandle, tooltipPopupVariants };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ElementType, HTMLAttributes } from "react";
|
|
2
|
+
//#region src/components/Typography/Typography.d.ts
|
|
3
|
+
type TypographyVariant = "display" | "h1" | "h2" | "h3" | "h4" | "body-lg" | "body" | "body-sm" | "caption" | "overline";
|
|
4
|
+
interface TypographyVariantsOptions {
|
|
5
|
+
variant?: TypographyVariant;
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Class list for an element styled per the ArcFusion type scale.
|
|
10
|
+
*
|
|
11
|
+
* Use it where the element must stay native (form labels, `figcaption`,
|
|
12
|
+
* `time`) and inside other primitives — primitives must not nest
|
|
13
|
+
* `<Typography>` (it would block `render` composition), so they mirror the
|
|
14
|
+
* recipe instead:
|
|
15
|
+
*
|
|
16
|
+
* <label className={typographyVariants({ variant: "body-sm" })}>Email</label>
|
|
17
|
+
*/
|
|
18
|
+
declare function typographyVariants({ variant, className }?: TypographyVariantsOptions): string;
|
|
19
|
+
interface TypographyProps extends HTMLAttributes<HTMLElement> {
|
|
20
|
+
/**
|
|
21
|
+
* Text style from the ArcFusion type scale. `display`–`h4` render in
|
|
22
|
+
* Poppins ("the Brand Voice"); `body-lg` down to `overline` render in
|
|
23
|
+
* Inter ("the Context"). The variant also picks the default element:
|
|
24
|
+
* `display` → `h1`, headings → their level, body styles → `p`,
|
|
25
|
+
* `caption`/`overline` → `span`.
|
|
26
|
+
*/
|
|
27
|
+
variant?: TypographyVariant;
|
|
28
|
+
/**
|
|
29
|
+
* Override the rendered element without changing the visual style, e.g.
|
|
30
|
+
* `variant="h4" as="h2"` when the document outline needs a level-2 heading
|
|
31
|
+
* with a compact look. Heading levels must descend without skipping — pick
|
|
32
|
+
* `as` from the outline, `variant` from the design.
|
|
33
|
+
*/
|
|
34
|
+
as?: ElementType;
|
|
35
|
+
}
|
|
36
|
+
declare const Typography: import("react").ForwardRefExoticComponent<TypographyProps & import("react").RefAttributes<HTMLElement>>;
|
|
37
|
+
//#endregion
|
|
38
|
+
export { Typography, TypographyProps, TypographyVariant, TypographyVariantsOptions, typographyVariants };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { cn } from "../../lib/cn.js";
|
|
2
|
+
import { createElement, forwardRef } from "react";
|
|
3
|
+
//#region src/components/Typography/Typography.tsx
|
|
4
|
+
const variantClasses = {
|
|
5
|
+
display: "font-heading font-semibold text-6xl tracking-tight text-foreground",
|
|
6
|
+
h1: "font-heading font-semibold text-4xl tracking-tight text-foreground",
|
|
7
|
+
h2: "font-heading font-semibold text-3xl tracking-tight text-foreground",
|
|
8
|
+
h3: "font-heading font-semibold text-2xl text-foreground",
|
|
9
|
+
h4: "font-heading font-semibold text-xl text-foreground",
|
|
10
|
+
"body-lg": "font-sans text-lg text-foreground",
|
|
11
|
+
body: "font-sans text-base text-foreground",
|
|
12
|
+
"body-sm": "font-sans text-sm text-foreground",
|
|
13
|
+
caption: "font-sans text-xs text-muted-foreground",
|
|
14
|
+
overline: "font-sans text-xs font-medium uppercase tracking-widest text-muted-foreground"
|
|
15
|
+
};
|
|
16
|
+
const defaultElements = {
|
|
17
|
+
display: "h1",
|
|
18
|
+
h1: "h1",
|
|
19
|
+
h2: "h2",
|
|
20
|
+
h3: "h3",
|
|
21
|
+
h4: "h4",
|
|
22
|
+
"body-lg": "p",
|
|
23
|
+
body: "p",
|
|
24
|
+
"body-sm": "p",
|
|
25
|
+
caption: "span",
|
|
26
|
+
overline: "span"
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Class list for an element styled per the ArcFusion type scale.
|
|
30
|
+
*
|
|
31
|
+
* Use it where the element must stay native (form labels, `figcaption`,
|
|
32
|
+
* `time`) and inside other primitives — primitives must not nest
|
|
33
|
+
* `<Typography>` (it would block `render` composition), so they mirror the
|
|
34
|
+
* recipe instead:
|
|
35
|
+
*
|
|
36
|
+
* <label className={typographyVariants({ variant: "body-sm" })}>Email</label>
|
|
37
|
+
*/
|
|
38
|
+
function typographyVariants({ variant = "body", className } = {}) {
|
|
39
|
+
return cn(variantClasses[variant], className);
|
|
40
|
+
}
|
|
41
|
+
const Typography = forwardRef(({ variant = "body", as, className, ...rest }, ref) => {
|
|
42
|
+
return createElement(as ?? defaultElements[variant], {
|
|
43
|
+
ref,
|
|
44
|
+
className: typographyVariants({
|
|
45
|
+
variant,
|
|
46
|
+
className
|
|
47
|
+
}),
|
|
48
|
+
...rest
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
Typography.displayName = "Typography";
|
|
52
|
+
//#endregion
|
|
53
|
+
export { Typography, typographyVariants };
|