@nsaa/core 0.1.0-alpha.1 → 0.1.0-alpha.3
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 +30 -8
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/accordion/accordion.d.ts +7 -0
- package/dist/accordion/accordion.js +54 -0
- package/dist/accordion/index.d.ts +3 -0
- package/dist/alert/alert.d.ts +19 -0
- package/dist/alert/alert.js +58 -0
- package/dist/alert/index.d.ts +3 -0
- package/dist/alert-dialog/alert-dialog.d.ts +19 -0
- package/dist/alert-dialog/alert-dialog.js +106 -0
- package/dist/alert-dialog/index.d.ts +3 -0
- package/dist/avatar/avatar.d.ts +12 -0
- package/dist/avatar/avatar.js +50 -0
- package/dist/avatar/index.d.ts +3 -0
- package/dist/badge/badge.d.ts +8 -0
- package/dist/badge/badge.js +29 -0
- package/dist/badge/index.d.ts +3 -0
- package/dist/button/button.d.ts +25 -0
- package/dist/button/button.js +136 -0
- package/dist/button/index.d.ts +3 -0
- package/dist/calendar/calendar.d.ts +11 -0
- package/dist/calendar/calendar.js +131 -0
- package/dist/calendar/index.d.ts +3 -0
- package/dist/card/card.d.ts +12 -0
- package/dist/card/card.js +55 -0
- package/dist/card/index.d.ts +3 -0
- package/dist/checkbox/checkbox.d.ts +4 -0
- package/dist/checkbox/checkbox.js +35 -0
- package/dist/checkbox/index.d.ts +3 -0
- package/dist/collapsible/collapsible.d.ts +6 -0
- package/dist/collapsible/collapsible.js +24 -0
- package/dist/collapsible/index.d.ts +3 -0
- package/dist/combobox/combobox.d.ts +27 -0
- package/dist/combobox/combobox.js +226 -0
- package/dist/combobox/index.d.ts +3 -0
- package/dist/command/command.d.ts +20 -0
- package/dist/command/command.js +116 -0
- package/dist/command/index.d.ts +3 -0
- package/dist/context-menu/context-menu.d.ts +30 -0
- package/dist/context-menu/context-menu.js +173 -0
- package/dist/context-menu/index.d.ts +3 -0
- package/dist/dialog/dialog.d.ts +18 -0
- package/dist/dialog/dialog.js +112 -0
- package/dist/dialog/index.d.ts +3 -0
- package/dist/direction.d.ts +3 -0
- package/dist/direction.js +2 -0
- package/dist/drawer/drawer.d.ts +17 -0
- package/dist/drawer/drawer.js +136 -0
- package/dist/drawer/index.d.ts +3 -0
- package/dist/dropdown-menu/dropdown-menu.d.ts +30 -0
- package/dist/dropdown-menu/dropdown-menu.js +177 -0
- package/dist/dropdown-menu/index.d.ts +3 -0
- package/dist/empty/empty.d.ts +35 -0
- package/dist/empty/empty.js +93 -0
- package/dist/empty/index.d.ts +3 -0
- package/dist/field/field.d.ts +26 -0
- package/dist/field/field.js +109 -0
- package/dist/field/index.d.ts +3 -0
- package/dist/index.d.ts +90 -674
- package/dist/index.js +50 -3877
- package/dist/input/index.d.ts +3 -0
- package/dist/input/input.d.ts +4 -0
- package/dist/input/input.js +14 -0
- package/dist/input-group/index.d.ts +3 -0
- package/dist/input-group/input-group.d.ts +19 -0
- package/dist/input-group/input-group.js +78 -0
- package/dist/input-otp/index.d.ts +3 -0
- package/dist/input-otp/input-otp.d.ts +12 -0
- package/dist/input-otp/input-otp.js +73 -0
- package/dist/kbd/index.d.ts +3 -0
- package/dist/kbd/kbd.d.ts +5 -0
- package/dist/kbd/kbd.js +19 -0
- package/dist/label/index.d.ts +3 -0
- package/dist/label/label.d.ts +4 -0
- package/dist/label/label.js +13 -0
- package/dist/legacy/icon-button/icon-swap.js +58 -0
- package/dist/lib/cn.d.ts +3 -0
- package/dist/{cn-DxFBFdwT.js → lib/cn.js} +1 -1
- package/dist/lib/control-defaults.js +8 -0
- package/dist/lib/icon-swap.d.ts +15 -0
- package/dist/lib/icon-swap.js +26 -0
- package/dist/lib/input-modality.js +39 -0
- package/dist/lib/merge-refs.js +21 -0
- package/dist/lib/opener.js +29 -0
- package/dist/lib/shortcut.js +50 -0
- package/dist/lib/track-input-modality.d.ts +2 -0
- package/dist/lib/track-input-modality.js +4 -0
- package/dist/lib/tv.js +7 -0
- package/dist/lib/use-press.js +48 -0
- package/dist/lib/user-action.js +13 -0
- package/dist/loaders/arc.d.ts +6 -0
- package/dist/loaders/arc.js +31 -0
- package/dist/loaders/atom.d.ts +5 -0
- package/dist/loaders/atom.js +70 -0
- package/dist/loaders/blocks.d.ts +8 -0
- package/dist/loaders/blocks.js +74 -0
- package/dist/loaders/bouncing-dots.d.ts +3 -0
- package/dist/loaders/bouncing-dots.js +45 -0
- package/dist/loaders/cap.d.ts +6 -0
- package/dist/loaders/cap.js +7 -0
- package/dist/loaders/cascade.d.ts +5 -0
- package/dist/loaders/cascade.js +50 -0
- package/dist/loaders/circular-dots.d.ts +3 -0
- package/dist/loaders/circular-dots.js +40 -0
- package/dist/loaders/classic-v2.d.ts +3 -0
- package/dist/loaders/classic-v2.js +41 -0
- package/dist/loaders/classic.d.ts +3 -0
- package/dist/loaders/classic.js +48 -0
- package/dist/loaders/clock.d.ts +5 -0
- package/dist/loaders/clock.js +31 -0
- package/dist/loaders/comet.d.ts +5 -0
- package/dist/loaders/comet.js +52 -0
- package/dist/loaders/compass.d.ts +3 -0
- package/dist/loaders/compass.js +39 -0
- package/dist/loaders/dual.d.ts +6 -0
- package/dist/loaders/dual.js +47 -0
- package/dist/loaders/easing.d.ts +6 -0
- package/dist/loaders/easing.js +34 -0
- package/dist/loaders/eclipse.d.ts +3 -0
- package/dist/loaders/eclipse.js +69 -0
- package/dist/loaders/fade.js +28 -0
- package/dist/loaders/flip.d.ts +3 -0
- package/dist/loaders/flip.js +41 -0
- package/dist/{frame-CK9IBOZB.js → loaders/frame.js} +2 -50
- package/dist/loaders/gather.d.ts +3 -0
- package/dist/loaders/gather.js +85 -0
- package/dist/loaders/leap.d.ts +3 -0
- package/dist/loaders/leap.js +67 -0
- package/dist/loaders/linear-dots.d.ts +3 -0
- package/dist/loaders/linear-dots.js +54 -0
- package/dist/loaders/loading.d.ts +3 -0
- package/dist/loaders/loading.js +64 -0
- package/dist/loaders/morph.d.ts +3 -0
- package/dist/loaders/morph.js +40 -0
- package/dist/loaders/motion.d.ts +35 -0
- package/dist/loaders/motion.js +51 -0
- package/dist/loaders/orbit.d.ts +5 -0
- package/dist/loaders/orbit.js +44 -0
- package/dist/loaders/pulse.d.ts +3 -0
- package/dist/loaders/pulse.js +52 -0
- package/dist/loaders/radar.d.ts +5 -0
- package/dist/loaders/radar.js +64 -0
- package/dist/loaders/ring.d.ts +6 -0
- package/dist/loaders/ring.js +38 -0
- package/dist/loaders/ripple.d.ts +8 -0
- package/dist/loaders/ripple.js +57 -0
- package/dist/loaders/slide.d.ts +3 -0
- package/dist/loaders/slide.js +74 -0
- package/dist/loaders/snake.d.ts +6 -0
- package/dist/loaders/snake.js +59 -0
- package/dist/loaders/spinners.d.ts +61 -0
- package/dist/loaders/spinners.js +63 -0
- package/dist/loaders/swirl.d.ts +3 -0
- package/dist/loaders/swirl.js +50 -0
- package/dist/loaders/text/shared.js +25 -0
- package/dist/loaders/text/text-loaders.d.ts +48 -0
- package/dist/loaders/text/text-loaders.js +723 -0
- package/dist/loaders/trace.d.ts +6 -0
- package/dist/loaders/trace.js +46 -0
- package/dist/loaders/types.d.ts +10 -0
- package/dist/loaders/wave.d.ts +8 -0
- package/dist/loaders/wave.js +59 -0
- package/dist/loaders-text.d.ts +2 -47
- package/dist/loaders-text.js +1 -743
- package/dist/loaders.d.ts +36 -132
- package/dist/loaders.js +35 -1096
- package/dist/native-select/index.d.ts +3 -0
- package/dist/native-select/native-select.d.ts +9 -0
- package/dist/native-select/native-select.js +44 -0
- package/dist/pagination/index.d.ts +3 -0
- package/dist/pagination/pagination.d.ts +18 -0
- package/dist/pagination/pagination.js +134 -0
- package/dist/popover/index.d.ts +3 -0
- package/dist/popover/popover.d.ts +10 -0
- package/dist/popover/popover.js +54 -0
- package/dist/radio-group/index.d.ts +3 -0
- package/dist/radio-group/radio-group.d.ts +6 -0
- package/dist/radio-group/radio-group.js +33 -0
- package/dist/select/index.d.ts +3 -0
- package/dist/select/select.d.ts +16 -0
- package/dist/select/select.js +148 -0
- package/dist/separator/index.d.ts +3 -0
- package/dist/separator/separator.d.ts +4 -0
- package/dist/separator/separator.js +15 -0
- package/dist/skeleton/index.d.ts +3 -0
- package/dist/skeleton/skeleton.d.ts +10 -0
- package/dist/skeleton/skeleton.js +24 -0
- package/dist/slider/index.d.ts +3 -0
- package/dist/slider/slider.d.ts +4 -0
- package/dist/slider/slider.js +39 -0
- package/dist/sound/lazy-uisfx.d.ts +20 -0
- package/dist/sound/lazy-uisfx.js +68 -0
- package/dist/sound/sound-map.d.ts +72 -0
- package/dist/sound/sound-map.js +76 -0
- package/dist/sound/sound.d.ts +38 -0
- package/dist/sound/sound.js +136 -0
- package/dist/sound/uisfx.d.ts +41 -0
- package/dist/sound/uisfx.js +59 -0
- package/dist/sound-uisfx.d.ts +2 -37
- package/dist/sound-uisfx.js +1 -58
- package/dist/sources/accordion.css +3 -0
- package/dist/sources/alert-dialog.css +26 -0
- package/dist/sources/alert.css +8 -0
- package/dist/sources/avatar.css +3 -0
- package/dist/sources/badge.css +3 -0
- package/dist/sources/button.css +24 -0
- package/dist/sources/calendar.css +25 -0
- package/dist/sources/card.css +3 -0
- package/dist/sources/checkbox.css +6 -0
- package/dist/sources/collapsible.css +2 -0
- package/dist/sources/combobox.css +28 -0
- package/dist/sources/command.css +30 -0
- package/dist/sources/context-menu.css +6 -0
- package/dist/sources/dialog.css +26 -0
- package/dist/sources/drawer.css +6 -0
- package/dist/sources/dropdown-menu.css +6 -0
- package/dist/sources/empty.css +3 -0
- package/dist/sources/field.css +5 -0
- package/dist/sources/input-group.css +27 -0
- package/dist/sources/input-otp.css +8 -0
- package/dist/sources/input.css +3 -0
- package/dist/sources/kbd.css +3 -0
- package/dist/sources/label.css +3 -0
- package/dist/sources/loaders-text.css +8 -0
- package/dist/sources/loaders.css +40 -0
- package/dist/sources/native-select.css +3 -0
- package/dist/sources/pagination.css +25 -0
- package/dist/sources/popover.css +3 -0
- package/dist/sources/radio-group.css +6 -0
- package/dist/sources/select.css +6 -0
- package/dist/sources/separator.css +3 -0
- package/dist/sources/skeleton.css +3 -0
- package/dist/sources/slider.css +6 -0
- package/dist/sources/spinner.css +20 -0
- package/dist/sources/switch.css +6 -0
- package/dist/sources/table.css +3 -0
- package/dist/sources/tabs.css +3 -0
- package/dist/sources/textarea.css +3 -0
- package/dist/sources/toast.css +25 -0
- package/dist/sources/toggle-group.css +32 -0
- package/dist/sources/toolbar.css +34 -0
- package/dist/sources/tooltip.css +3 -0
- package/dist/spinner/index.d.ts +5 -0
- package/dist/spinner/loader-provider.d.ts +16 -0
- package/dist/spinner/loader-provider.js +28 -0
- package/dist/spinner/registry.d.ts +9 -0
- package/dist/spinner/registry.js +15 -0
- package/dist/spinner/spinner.d.ts +26 -0
- package/dist/spinner/spinner.js +143 -0
- package/dist/switch/index.d.ts +3 -0
- package/dist/switch/switch.d.ts +6 -0
- package/dist/switch/switch.js +25 -0
- package/dist/table/index.d.ts +3 -0
- package/dist/table/table.d.ts +17 -0
- package/dist/table/table.js +66 -0
- package/dist/tabs/index.d.ts +3 -0
- package/dist/tabs/tabs.d.ts +11 -0
- package/dist/tabs/tabs.js +46 -0
- package/dist/textarea/index.d.ts +3 -0
- package/dist/textarea/textarea.d.ts +4 -0
- package/dist/textarea/textarea.js +12 -0
- package/dist/toast/index.d.ts +3 -0
- package/dist/toast/toast.d.ts +17 -0
- package/dist/toast/toast.js +211 -0
- package/dist/toggle-group/index.d.ts +3 -0
- package/dist/toggle-group/toggle-group.d.ts +64 -0
- package/dist/toggle-group/toggle-group.js +95 -0
- package/dist/tokens/dist/motion.d.ts +24 -0
- package/dist/{motion-NQq2BA78.js → tokens/dist/motion.js} +1 -1
- package/dist/toolbar/index.d.ts +3 -0
- package/dist/toolbar/overflow.d.ts +4 -0
- package/dist/toolbar/overflow.js +242 -0
- package/dist/toolbar/toolbar-item.d.ts +29 -0
- package/dist/toolbar/toolbar-item.js +71 -0
- package/dist/toolbar/toolbar.d.ts +73 -0
- package/dist/toolbar/toolbar.js +250 -0
- package/dist/tooltip/index.d.ts +3 -0
- package/dist/tooltip/tooltip.d.ts +7 -0
- package/dist/tooltip/tooltip.js +41 -0
- package/package.json +9 -5
- package/src/feel.css +52 -0
- package/src/styles-base.css +142 -0
- package/src/styles.css +3 -133
- package/dist/registry-2PyPW9Xw.js +0 -390
- package/dist/registry-DjfWNw3R.d.ts +0 -18
- package/dist/sound-DiYNAnR_.d.ts +0 -61
package/README.md
CHANGED
|
@@ -17,7 +17,20 @@ import { Button, SoundProvider } from "@nsaa/core";
|
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Fonts are yours to load: the tokens name Geist (body), Newsreader (the editorial theme) and Geist
|
|
20
|
-
Mono, and fall back to the system sans.
|
|
20
|
+
Mono, and fall back to the system sans. Self-host them with Fontsource (works under a strict CSP such
|
|
21
|
+
as `font-src 'self'`; the tokens list the Fontsource names first, so no `@font-face` is needed):
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
pnpm add @fontsource-variable/geist @fontsource-variable/geist-mono @fontsource-variable/newsreader
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```css
|
|
28
|
+
@import "@fontsource-variable/geist";
|
|
29
|
+
@import "@fontsource-variable/geist-mono";
|
|
30
|
+
@import "@fontsource-variable/newsreader"; /* editorial theme only */
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or link Google Fonts in your HTML `<head>`:
|
|
21
34
|
|
|
22
35
|
```html
|
|
23
36
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
@@ -28,12 +41,21 @@ Mono, and fall back to the system sans. For example, in your HTML `<head>`:
|
|
|
28
41
|
/>
|
|
29
42
|
```
|
|
30
43
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
44
|
+
Sound: `lazyUisfxPlayer()` (recommended) loads the UISFX engine on the first interaction;
|
|
45
|
+
`createUisfxPlayer()` from `@nsaa/core/sound-uisfx` loads it up front.
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
const player = lazyUisfxPlayer();
|
|
49
|
+
<SoundProvider player={player}>…</SoundProvider>;
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
| Entry | What |
|
|
53
|
+
| ---------------------------- | ------------------------------------------------------------------------------------ |
|
|
54
|
+
| `@nsaa/core` | components, `SoundProvider`, `lazyUisfxPlayer`, `LoaderProvider`, `Spinner` |
|
|
55
|
+
| `@nsaa/core/loaders` | all 29 loading.dev loaders, `registerLoaders` |
|
|
56
|
+
| `@nsaa/core/loaders/text` | text and AI loaders (ShimmerText, Typing, …) |
|
|
57
|
+
| `@nsaa/core/sound-uisfx` | the UISFX sound engine for `SoundProvider` |
|
|
58
|
+
| `@nsaa/core/styles.css` | tokens, the shadcn alias layer, the feel layer, every component's sources |
|
|
59
|
+
| `@nsaa/core/styles-base.css` | the same without Tailwind sources; add `@nsaa/core/sources/<name>.css` per component |
|
|
38
60
|
|
|
39
61
|
Peer dependencies: `react` and `react-dom` 19. MIT; third-party notices in `NOTICE`.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
// \0rolldown/runtime.js
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __exportAll = (all, no_symbols) => {
|
|
5
|
+
let target = {};
|
|
6
|
+
for (var name in all) __defProp(target, name, {
|
|
7
|
+
get: all[name],
|
|
8
|
+
enumerable: true
|
|
9
|
+
});
|
|
10
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
11
|
+
return target;
|
|
12
|
+
};
|
|
13
|
+
export { __exportAll };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
|
|
2
|
+
import { Accordion } from "@base-ui/react/accordion";
|
|
3
|
+
declare function Accordion$1({ className, ...props }: Accordion.Root.Props): import("react").JSX.Element;
|
|
4
|
+
declare function AccordionItem({ className, ...props }: Accordion.Item.Props): import("react").JSX.Element;
|
|
5
|
+
declare function AccordionTrigger({ className, children, ...props }: Accordion.Trigger.Props): import("react").JSX.Element;
|
|
6
|
+
declare function AccordionContent({ className, children, ...props }: Accordion.Panel.Props): import("react").JSX.Element;
|
|
7
|
+
export { Accordion$1 as Accordion, AccordionContent, AccordionItem, AccordionTrigger };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { Accordion } from "@base-ui/react/accordion";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
// src/accordion/accordion.tsx
|
|
6
|
+
function Accordion$1({ className, ...props }) {
|
|
7
|
+
return /* @__PURE__ */ jsx(Accordion.Root, {
|
|
8
|
+
"data-slot": "accordion",
|
|
9
|
+
className: cn("flex w-full flex-col", className),
|
|
10
|
+
...props
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function AccordionItem({ className, ...props }) {
|
|
14
|
+
return /* @__PURE__ */ jsx(Accordion.Item, {
|
|
15
|
+
"data-slot": "accordion-item",
|
|
16
|
+
className: cn("not-last:border-b", className),
|
|
17
|
+
...props
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function AccordionTrigger({ className, children, ...props }) {
|
|
21
|
+
return /* @__PURE__ */ jsx(Accordion.Header, {
|
|
22
|
+
className: "flex",
|
|
23
|
+
children: /* @__PURE__ */ jsxs(Accordion.Trigger, {
|
|
24
|
+
"data-slot": "accordion-trigger",
|
|
25
|
+
className: cn("group/accordion-trigger relative flex flex-1 items-start justify-between rounded-lg border border-transparent py-2.5 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:after:border-ring aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground", className),
|
|
26
|
+
...props,
|
|
27
|
+
children: [children, /* @__PURE__ */ jsx("svg", {
|
|
28
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
29
|
+
viewBox: "0 0 24 24",
|
|
30
|
+
fill: "none",
|
|
31
|
+
stroke: "currentColor",
|
|
32
|
+
strokeWidth: "2",
|
|
33
|
+
strokeLinecap: "round",
|
|
34
|
+
strokeLinejoin: "round",
|
|
35
|
+
"data-slot": "accordion-trigger-icon",
|
|
36
|
+
className: "pointer-events-none shrink-0",
|
|
37
|
+
"aria-hidden": "true",
|
|
38
|
+
children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
|
|
39
|
+
})]
|
|
40
|
+
})
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function AccordionContent({ className, children, ...props }) {
|
|
44
|
+
return /* @__PURE__ */ jsx(Accordion.Panel, {
|
|
45
|
+
"data-slot": "accordion-content",
|
|
46
|
+
className: "overflow-hidden text-sm data-open:animate-accordion-down data-closed:animate-accordion-up",
|
|
47
|
+
...props,
|
|
48
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
49
|
+
className: cn("h-(--accordion-panel-height) pt-0 pb-2.5 data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4", className),
|
|
50
|
+
children
|
|
51
|
+
})
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
export { Accordion$1 as Accordion, AccordionContent, AccordionItem, AccordionTrigger };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
import { VariantProps } from "class-variance-authority";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
declare const alertVariants: (props?: ({
|
|
5
|
+
variant?: "success" | "warning" | "default" | "destructive" | "info" | null | undefined;
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
+
declare function Alert({ className, variant, announce, ...props }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants> & {
|
|
8
|
+
/**
|
|
9
|
+
* The error sound (feedback.error) when the Alert appears (#114). Left unset it's automatic: a
|
|
10
|
+
* destructive Alert plays it when a person's action caused it (within the browser's transient
|
|
11
|
+
* activation window), never on load. `true` always plays it, `false` never does. Success and
|
|
12
|
+
* warning are silent unless `announce` is set, then play feedback.success / feedback.warning.
|
|
13
|
+
*/
|
|
14
|
+
announce?: boolean;
|
|
15
|
+
}): React.JSX.Element;
|
|
16
|
+
declare function AlertTitle({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
17
|
+
declare function AlertDescription({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
18
|
+
declare function AlertAction({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
19
|
+
export { Alert, AlertAction, AlertDescription, AlertTitle };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { recentUserAction } from "../lib/user-action.js";
|
|
4
|
+
import { useCue } from "../sound/sound-map.js";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
import { cva } from "class-variance-authority";
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
// src/alert/alert.tsx
|
|
9
|
+
const alertVariants = cva("group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4", {
|
|
10
|
+
variants: { variant: {
|
|
11
|
+
default: "bg-card text-card-foreground",
|
|
12
|
+
destructive: "bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current",
|
|
13
|
+
success: "border-positive-subtle-active bg-positive-subtle text-on-positive-subtle-foreground *:data-[slot=alert-description]:text-on-positive-subtle-foreground",
|
|
14
|
+
warning: "border-warning-subtle-active bg-warning-subtle text-on-warning-subtle-foreground *:data-[slot=alert-description]:text-on-warning-subtle-foreground",
|
|
15
|
+
info: "border-info-subtle-active bg-info-subtle text-on-info-subtle-foreground *:data-[slot=alert-description]:text-on-info-subtle-foreground"
|
|
16
|
+
} },
|
|
17
|
+
defaultVariants: { variant: "default" }
|
|
18
|
+
});
|
|
19
|
+
function Alert({ className, variant, announce, ...props }) {
|
|
20
|
+
const cue = useCue("alert");
|
|
21
|
+
const destructive = variant === "destructive";
|
|
22
|
+
const announceCue = variant === "success" || variant === "warning" ? variant : "destructive";
|
|
23
|
+
const appear = React.useEffectEvent(() => {
|
|
24
|
+
if (variant === "info") return;
|
|
25
|
+
if (announce === true || destructive && recentUserAction()) cue(announceCue);
|
|
26
|
+
});
|
|
27
|
+
React.useEffect(() => {
|
|
28
|
+
if (announce !== false && (destructive || announce)) appear();
|
|
29
|
+
}, [destructive, announce]);
|
|
30
|
+
return /* @__PURE__ */ jsx("div", {
|
|
31
|
+
"data-slot": "alert",
|
|
32
|
+
role: "alert",
|
|
33
|
+
className: cn(alertVariants({ variant }), className),
|
|
34
|
+
...props
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function AlertTitle({ className, ...props }) {
|
|
38
|
+
return /* @__PURE__ */ jsx("div", {
|
|
39
|
+
"data-slot": "alert-title",
|
|
40
|
+
className: cn("font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground", className),
|
|
41
|
+
...props
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function AlertDescription({ className, ...props }) {
|
|
45
|
+
return /* @__PURE__ */ jsx("div", {
|
|
46
|
+
"data-slot": "alert-description",
|
|
47
|
+
className: cn("text-sm text-balance text-muted-foreground md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4", className),
|
|
48
|
+
...props
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function AlertAction({ className, ...props }) {
|
|
52
|
+
return /* @__PURE__ */ jsx("div", {
|
|
53
|
+
"data-slot": "alert-action",
|
|
54
|
+
className: cn("absolute top-2 right-2", className),
|
|
55
|
+
...props
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
export { Alert, AlertAction, AlertDescription, AlertTitle };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
import { Button } from "../button/button.js";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { AlertDialog } from "@base-ui/react/alert-dialog";
|
|
5
|
+
declare function AlertDialog$1({ onOpenChange, ...props }: AlertDialog.Root.Props): React.JSX.Element;
|
|
6
|
+
declare function AlertDialogTrigger({ ...props }: AlertDialog.Trigger.Props): React.JSX.Element;
|
|
7
|
+
declare function AlertDialogPortal({ ...props }: AlertDialog.Portal.Props): React.JSX.Element;
|
|
8
|
+
declare function AlertDialogOverlay({ className, ...props }: AlertDialog.Backdrop.Props): React.JSX.Element;
|
|
9
|
+
declare function AlertDialogContent({ className, size, ...props }: AlertDialog.Popup.Props & {
|
|
10
|
+
size?: "default" | "sm";
|
|
11
|
+
}): React.JSX.Element;
|
|
12
|
+
declare function AlertDialogHeader({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
13
|
+
declare function AlertDialogFooter({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
14
|
+
declare function AlertDialogMedia({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
15
|
+
declare function AlertDialogTitle({ className, ...props }: React.ComponentProps<typeof AlertDialog.Title>): React.JSX.Element;
|
|
16
|
+
declare function AlertDialogDescription({ className, ...props }: React.ComponentProps<typeof AlertDialog.Description>): React.JSX.Element;
|
|
17
|
+
declare function AlertDialogAction({ className, ...props }: React.ComponentProps<typeof Button>): React.JSX.Element;
|
|
18
|
+
declare function AlertDialogCancel({ className, variant, size, ...props }: AlertDialog.Close.Props & Pick<React.ComponentProps<typeof Button>, "variant" | "size">): React.JSX.Element;
|
|
19
|
+
export { AlertDialog$1 as AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import { cn } from "../lib/cn.js";
|
|
4
|
+
import { useCue } from "../sound/sound-map.js";
|
|
5
|
+
import { Button } from "../button/button.js";
|
|
6
|
+
import { OpenerContext, useFinalFocus, useOpener } from "../lib/opener.js";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { AlertDialog } from "@base-ui/react/alert-dialog";
|
|
9
|
+
// src/alert-dialog/alert-dialog.tsx
|
|
10
|
+
function AlertDialog$1({ onOpenChange, ...props }) {
|
|
11
|
+
const cue = useCue("alert-dialog");
|
|
12
|
+
const opener = useOpener(props.open);
|
|
13
|
+
return /* @__PURE__ */ jsx(OpenerContext.Provider, {
|
|
14
|
+
value: opener,
|
|
15
|
+
children: /* @__PURE__ */ jsx(AlertDialog.Root, {
|
|
16
|
+
"data-slot": "alert-dialog",
|
|
17
|
+
onOpenChange: (open, details) => {
|
|
18
|
+
onOpenChange?.(open, details);
|
|
19
|
+
if (!details.isCanceled) cue(open ? "open" : "close");
|
|
20
|
+
},
|
|
21
|
+
...props
|
|
22
|
+
})
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function AlertDialogTrigger({ ...props }) {
|
|
26
|
+
return /* @__PURE__ */ jsx(AlertDialog.Trigger, {
|
|
27
|
+
"data-slot": "alert-dialog-trigger",
|
|
28
|
+
...props
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function AlertDialogPortal({ ...props }) {
|
|
32
|
+
return /* @__PURE__ */ jsx(AlertDialog.Portal, {
|
|
33
|
+
"data-slot": "alert-dialog-portal",
|
|
34
|
+
...props
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function AlertDialogOverlay({ className, ...props }) {
|
|
38
|
+
return /* @__PURE__ */ jsx(AlertDialog.Backdrop, {
|
|
39
|
+
"data-slot": "alert-dialog-overlay",
|
|
40
|
+
className: cn("fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0", className),
|
|
41
|
+
...props
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function AlertDialogContent({ className, size = "default", ...props }) {
|
|
45
|
+
props.finalFocus = useFinalFocus(props.finalFocus);
|
|
46
|
+
return /* @__PURE__ */ jsxs(AlertDialogPortal, { children: [/* @__PURE__ */ jsx(AlertDialogOverlay, {}), /* @__PURE__ */ jsx(AlertDialog.Popup, {
|
|
47
|
+
"data-slot": "alert-dialog-content",
|
|
48
|
+
"data-size": size,
|
|
49
|
+
className: cn("group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className),
|
|
50
|
+
...props
|
|
51
|
+
})] });
|
|
52
|
+
}
|
|
53
|
+
function AlertDialogHeader({ className, ...props }) {
|
|
54
|
+
return /* @__PURE__ */ jsx("div", {
|
|
55
|
+
"data-slot": "alert-dialog-header",
|
|
56
|
+
className: cn("grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]", className),
|
|
57
|
+
...props
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function AlertDialogFooter({ className, ...props }) {
|
|
61
|
+
return /* @__PURE__ */ jsx("div", {
|
|
62
|
+
"data-slot": "alert-dialog-footer",
|
|
63
|
+
className: cn("-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end", className),
|
|
64
|
+
...props
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function AlertDialogMedia({ className, ...props }) {
|
|
68
|
+
return /* @__PURE__ */ jsx("div", {
|
|
69
|
+
"data-slot": "alert-dialog-media",
|
|
70
|
+
className: cn("mb-2 inline-flex size-10 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6", className),
|
|
71
|
+
...props
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function AlertDialogTitle({ className, ...props }) {
|
|
75
|
+
return /* @__PURE__ */ jsx(AlertDialog.Title, {
|
|
76
|
+
"data-slot": "alert-dialog-title",
|
|
77
|
+
className: cn("cn-font-heading text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2", className),
|
|
78
|
+
...props
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function AlertDialogDescription({ className, ...props }) {
|
|
82
|
+
return /* @__PURE__ */ jsx(AlertDialog.Description, {
|
|
83
|
+
"data-slot": "alert-dialog-description",
|
|
84
|
+
className: cn("text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground", className),
|
|
85
|
+
...props
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
function AlertDialogAction({ className, ...props }) {
|
|
89
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
90
|
+
"data-slot": "alert-dialog-action",
|
|
91
|
+
className: cn(className),
|
|
92
|
+
...props
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function AlertDialogCancel({ className, variant = "outline", size = "default", ...props }) {
|
|
96
|
+
return /* @__PURE__ */ jsx(AlertDialog.Close, {
|
|
97
|
+
"data-slot": "alert-dialog-cancel",
|
|
98
|
+
className: cn(className),
|
|
99
|
+
render: /* @__PURE__ */ jsx(Button, {
|
|
100
|
+
variant,
|
|
101
|
+
size
|
|
102
|
+
}),
|
|
103
|
+
...props
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
export { AlertDialog$1 as AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
|
|
2
|
+
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger } from "./alert-dialog.js";
|
|
3
|
+
export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Avatar } from "@base-ui/react/avatar";
|
|
4
|
+
declare function Avatar$1({ className, size, ...props }: Avatar.Root.Props & {
|
|
5
|
+
size?: "default" | "sm" | "lg";
|
|
6
|
+
}): React.JSX.Element;
|
|
7
|
+
declare function AvatarImage({ className, ...props }: Avatar.Image.Props): React.JSX.Element;
|
|
8
|
+
declare function AvatarFallback({ className, ...props }: Avatar.Fallback.Props): React.JSX.Element;
|
|
9
|
+
declare function AvatarBadge({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
|
|
10
|
+
declare function AvatarGroup({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
11
|
+
declare function AvatarGroupCount({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
12
|
+
export { Avatar$1 as Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import { cn } from "../lib/cn.js";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { Avatar } from "@base-ui/react/avatar";
|
|
6
|
+
// src/avatar/avatar.tsx
|
|
7
|
+
function Avatar$1({ className, size = "default", ...props }) {
|
|
8
|
+
return /* @__PURE__ */ jsx(Avatar.Root, {
|
|
9
|
+
"data-slot": "avatar",
|
|
10
|
+
"data-size": size,
|
|
11
|
+
className: cn("group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten", className),
|
|
12
|
+
...props
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function AvatarImage({ className, ...props }) {
|
|
16
|
+
return /* @__PURE__ */ jsx(Avatar.Image, {
|
|
17
|
+
"data-slot": "avatar-image",
|
|
18
|
+
className: cn("aspect-square size-full rounded-full object-cover", className),
|
|
19
|
+
...props
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function AvatarFallback({ className, ...props }) {
|
|
23
|
+
return /* @__PURE__ */ jsx(Avatar.Fallback, {
|
|
24
|
+
"data-slot": "avatar-fallback",
|
|
25
|
+
className: cn("flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs", className),
|
|
26
|
+
...props
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function AvatarBadge({ className, ...props }) {
|
|
30
|
+
return /* @__PURE__ */ jsx("span", {
|
|
31
|
+
"data-slot": "avatar-badge",
|
|
32
|
+
className: cn("absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none", "group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden", "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2", "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2", className),
|
|
33
|
+
...props
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function AvatarGroup({ className, ...props }) {
|
|
37
|
+
return /* @__PURE__ */ jsx("div", {
|
|
38
|
+
"data-slot": "avatar-group",
|
|
39
|
+
className: cn("group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background", className),
|
|
40
|
+
...props
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function AvatarGroupCount({ className, ...props }) {
|
|
44
|
+
return /* @__PURE__ */ jsx("div", {
|
|
45
|
+
"data-slot": "avatar-group-count",
|
|
46
|
+
className: cn("relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3", className),
|
|
47
|
+
...props
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
export { Avatar$1 as Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
|
|
2
|
+
import { VariantProps } from "class-variance-authority";
|
|
3
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
4
|
+
declare const badgeVariants: (props?: ({
|
|
5
|
+
variant?: "default" | "destructive" | "link" | "secondary" | "outline" | "ghost" | null | undefined;
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
+
declare function Badge({ className, variant, render, ...props }: useRender.ComponentProps<"span"> & VariantProps<typeof badgeVariants>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
8
|
+
export { Badge, badgeVariants };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { cva } from "class-variance-authority";
|
|
4
|
+
import { mergeProps } from "@base-ui/react/merge-props";
|
|
5
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
6
|
+
// src/badge/badge.tsx
|
|
7
|
+
const badgeVariants = cva("group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!", {
|
|
8
|
+
variants: { variant: {
|
|
9
|
+
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
|
10
|
+
secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
|
|
11
|
+
destructive: "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:text-destructive-hover-foreground",
|
|
12
|
+
outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
|
|
13
|
+
ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
|
|
14
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
15
|
+
} },
|
|
16
|
+
defaultVariants: { variant: "default" }
|
|
17
|
+
});
|
|
18
|
+
function Badge({ className, variant = "default", render, ...props }) {
|
|
19
|
+
return useRender({
|
|
20
|
+
defaultTagName: "span",
|
|
21
|
+
props: mergeProps({ className: cn(badgeVariants({ variant }), className) }, props),
|
|
22
|
+
render,
|
|
23
|
+
state: {
|
|
24
|
+
slot: "badge",
|
|
25
|
+
variant
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export { Badge, badgeVariants };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
import { VariantProps } from "class-variance-authority";
|
|
3
|
+
import { Button } from "@base-ui/react/button";
|
|
4
|
+
declare const buttonVariants: (props?: ({
|
|
5
|
+
variant?: "default" | "destructive" | "link" | "secondary" | "outline" | "ghost" | null | undefined;
|
|
6
|
+
size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
7
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
8
|
+
type LoadingPlacement = "auto" | "start" | "center";
|
|
9
|
+
declare function Button$1({ className, variant, size, loading, loadingLabel, loadingPlacement, children, onClick, onPointerDown, onPointerUp, onPointerLeave, onPointerCancel, ...props }: Button.Props & VariantProps<typeof buttonVariants> & {
|
|
10
|
+
/**
|
|
11
|
+
* Shows the Arc spinner in place of the start icon and ignores presses, keeping focus and the
|
|
12
|
+
* accessible name (`aria-busy`, `data-loading`; not `disabled`).
|
|
13
|
+
*/
|
|
14
|
+
loading?: boolean | undefined;
|
|
15
|
+
/** Announced through the spinner while loading. Default "Loading". */
|
|
16
|
+
loadingLabel?: string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Where the spinner goes while loading (#130). `start` takes the start icon's place, or sits
|
|
19
|
+
* before the label and the button grows; `center` overlays it and keeps the content's space, so
|
|
20
|
+
* the width never changes. `auto` (default): `start` with a start icon or on an icon size, else
|
|
21
|
+
* `center`. The resolved value is set as `data-loading-placement`.
|
|
22
|
+
*/
|
|
23
|
+
loadingPlacement?: LoadingPlacement | undefined;
|
|
24
|
+
}): import("react").JSX.Element;
|
|
25
|
+
export { Button$1 as Button, buttonVariants };
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { useCue } from "../sound/sound-map.js";
|
|
4
|
+
import { useControlDefaults } from "../lib/control-defaults.js";
|
|
5
|
+
import { usePress } from "../lib/use-press.js";
|
|
6
|
+
import { Spinner } from "../spinner/spinner.js";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { cva } from "class-variance-authority";
|
|
9
|
+
import { Children, isValidElement } from "react";
|
|
10
|
+
import { Button } from "@base-ui/react/button";
|
|
11
|
+
// src/button/button.tsx
|
|
12
|
+
const buttonVariants = cva("group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
|
|
13
|
+
variants: {
|
|
14
|
+
variant: {
|
|
15
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/80",
|
|
16
|
+
outline: "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
|
|
17
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
18
|
+
ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
|
|
19
|
+
destructive: "bg-destructive/10 text-destructive hover:text-destructive-hover-foreground focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40",
|
|
20
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
21
|
+
},
|
|
22
|
+
size: {
|
|
23
|
+
default: "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
24
|
+
xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
25
|
+
sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
|
|
26
|
+
lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
27
|
+
icon: "size-8",
|
|
28
|
+
"icon-xs": "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
|
|
29
|
+
"icon-sm": "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
|
|
30
|
+
"icon-lg": "size-9"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
defaultVariants: {
|
|
34
|
+
variant: "default",
|
|
35
|
+
size: "default"
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
const SPINNER_SIZE = {
|
|
39
|
+
default: "md",
|
|
40
|
+
xs: "xs",
|
|
41
|
+
sm: "sm",
|
|
42
|
+
lg: "md",
|
|
43
|
+
icon: "md",
|
|
44
|
+
"icon-xs": "xs",
|
|
45
|
+
"icon-sm": "md",
|
|
46
|
+
"icon-lg": "md"
|
|
47
|
+
};
|
|
48
|
+
function hasStartIcon(children) {
|
|
49
|
+
return Children.toArray(children).some((child) => isValidElement(child) && child.props["data-icon"] === "inline-start");
|
|
50
|
+
}
|
|
51
|
+
/** `auto` (#130): `start` with a start icon or on an icon size, else `center`. */
|
|
52
|
+
function resolvePlacement(placement, children, size) {
|
|
53
|
+
if (placement !== "auto") return placement;
|
|
54
|
+
return size.startsWith("icon") || hasStartIcon(children) ? "start" : "center";
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Loading content. `start` (#128): the Arc spinner takes the start icon's place at once, so the
|
|
58
|
+
* width stays the same; icon-only sizes swap their icon; with no start icon it sits before the
|
|
59
|
+
* label and the button grows. `center` (#130): the spinner sits over the middle and the content
|
|
60
|
+
* keeps its place, transparent (opacity, not visibility, so it still names the button).
|
|
61
|
+
*/
|
|
62
|
+
function loadingContent(children, size, label, placement) {
|
|
63
|
+
if (placement === "center") return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
64
|
+
"data-slot": "button-spinner",
|
|
65
|
+
className: "absolute inset-0 flex items-center justify-center",
|
|
66
|
+
children: /* @__PURE__ */ jsx(Spinner, {
|
|
67
|
+
size: SPINNER_SIZE[size],
|
|
68
|
+
label
|
|
69
|
+
})
|
|
70
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
71
|
+
"data-slot": "button-content",
|
|
72
|
+
className: "inline-flex items-center gap-[inherit] opacity-0",
|
|
73
|
+
children
|
|
74
|
+
})] });
|
|
75
|
+
const spinner = /* @__PURE__ */ jsx(Spinner, {
|
|
76
|
+
"data-icon": "inline-start",
|
|
77
|
+
size: SPINNER_SIZE[size],
|
|
78
|
+
label
|
|
79
|
+
}, "spinner");
|
|
80
|
+
if (size.startsWith("icon")) return spinner;
|
|
81
|
+
let swapped = false;
|
|
82
|
+
const rest = Children.map(children, (child) => {
|
|
83
|
+
if (!swapped && isValidElement(child) && child.props["data-icon"] === "inline-start") {
|
|
84
|
+
swapped = true;
|
|
85
|
+
return spinner;
|
|
86
|
+
}
|
|
87
|
+
return child;
|
|
88
|
+
});
|
|
89
|
+
return swapped ? rest : [spinner, ...rest ?? []];
|
|
90
|
+
}
|
|
91
|
+
function Button$1({ className, variant = "default", size = "default", loading = false, loadingLabel = "Loading", loadingPlacement = "auto", children, onClick, onPointerDown, onPointerUp, onPointerLeave, onPointerCancel, ...props }) {
|
|
92
|
+
const press = usePress();
|
|
93
|
+
const cue = useCue("button");
|
|
94
|
+
const { sound = true } = useControlDefaults();
|
|
95
|
+
const placement = loading ? resolvePlacement(loadingPlacement, children, size ?? "default") : null;
|
|
96
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
97
|
+
"data-slot": "button",
|
|
98
|
+
className: cn(buttonVariants({
|
|
99
|
+
variant,
|
|
100
|
+
size
|
|
101
|
+
}), placement === "center" && "relative", className),
|
|
102
|
+
"aria-busy": loading || void 0,
|
|
103
|
+
"data-loading": loading ? "" : void 0,
|
|
104
|
+
"data-loading-placement": placement ?? void 0,
|
|
105
|
+
onPointerDown: (event) => {
|
|
106
|
+
onPointerDown?.(event);
|
|
107
|
+
if (!loading) press.onPointerDown(event);
|
|
108
|
+
},
|
|
109
|
+
onPointerUp: (event) => {
|
|
110
|
+
onPointerUp?.(event);
|
|
111
|
+
press.onPointerUp();
|
|
112
|
+
},
|
|
113
|
+
onPointerLeave: (event) => {
|
|
114
|
+
onPointerLeave?.(event);
|
|
115
|
+
press.onPointerLeave();
|
|
116
|
+
},
|
|
117
|
+
onPointerCancel: (event) => {
|
|
118
|
+
onPointerCancel?.(event);
|
|
119
|
+
press.onPointerCancel();
|
|
120
|
+
},
|
|
121
|
+
onClick: (event) => {
|
|
122
|
+
if (loading) {
|
|
123
|
+
event.preventDefault();
|
|
124
|
+
event.preventBaseUIHandler();
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
onClick?.(event);
|
|
128
|
+
const el = event.currentTarget;
|
|
129
|
+
const trigger = el.hasAttribute("aria-haspopup") || el.hasAttribute("aria-expanded");
|
|
130
|
+
if (sound && !event.defaultPrevented && !trigger) cue("press", { yield: true });
|
|
131
|
+
},
|
|
132
|
+
...props,
|
|
133
|
+
children: placement ? loadingContent(children, size ?? "default", loadingLabel, placement) : children
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
export { Button$1 as Button, buttonVariants };
|