@nsaa/core 0.1.0-alpha.1 → 0.1.0-alpha.2
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/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 +18 -0
- package/dist/alert/alert.js +53 -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 +100 -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 +106 -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 +89 -674
- package/dist/index.js +48 -3876
- 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/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/sound-map.d.ts +70 -0
- package/dist/sound/sound-map.js +72 -0
- package/dist/sound/sound.d.ts +38 -0
- package/dist/sound/sound.js +136 -0
- package/dist/sound/uisfx.d.ts +37 -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/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 +4 -3
- package/dist/registry-2PyPW9Xw.js +0 -390
- package/dist/registry-DjfWNw3R.d.ts +0 -18
- package/dist/sound-DiYNAnR_.d.ts +0 -61
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { Input } from "@base-ui/react/input";
|
|
5
|
+
// src/input/input.tsx
|
|
6
|
+
function Input$1({ className, type, ...props }) {
|
|
7
|
+
return /* @__PURE__ */ jsx(Input, {
|
|
8
|
+
type,
|
|
9
|
+
"data-slot": "input",
|
|
10
|
+
className: cn("h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40", className),
|
|
11
|
+
...props
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
export { Input$1 as Input };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
import { Button } from "../button/button.js";
|
|
3
|
+
import { VariantProps } from "class-variance-authority";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
declare function InputGroup({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
6
|
+
declare const inputGroupAddonVariants: (props?: ({
|
|
7
|
+
align?: "inline-start" | "inline-end" | "block-start" | "block-end" | null | undefined;
|
|
8
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
9
|
+
declare function InputGroupAddon({ className, align, ...props }: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>): React.JSX.Element;
|
|
10
|
+
declare const inputGroupButtonVariants: (props?: ({
|
|
11
|
+
size?: "xs" | "sm" | "icon-xs" | "icon-sm" | null | undefined;
|
|
12
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
13
|
+
declare function InputGroupButton({ className, type, variant, size, ...props }: Omit<React.ComponentProps<typeof Button>, "size" | "type"> & VariantProps<typeof inputGroupButtonVariants> & {
|
|
14
|
+
type?: "button" | "submit" | "reset";
|
|
15
|
+
}): React.JSX.Element;
|
|
16
|
+
declare function InputGroupText({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
|
|
17
|
+
declare function InputGroupInput({ className, ...props }: React.ComponentProps<"input">): React.JSX.Element;
|
|
18
|
+
declare function InputGroupTextarea({ className, ...props }: React.ComponentProps<"textarea">): React.JSX.Element;
|
|
19
|
+
export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import { cn } from "../lib/cn.js";
|
|
4
|
+
import { Button } from "../button/button.js";
|
|
5
|
+
import { Input } from "../input/input.js";
|
|
6
|
+
import { Textarea } from "../textarea/textarea.js";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
import { cva } from "class-variance-authority";
|
|
9
|
+
// src/input-group/input-group.tsx
|
|
10
|
+
function InputGroup({ className, ...props }) {
|
|
11
|
+
return /* @__PURE__ */ jsx("div", {
|
|
12
|
+
"data-slot": "input-group",
|
|
13
|
+
role: "group",
|
|
14
|
+
className: cn("group/input-group relative flex h-8 w-full min-w-0 items-center rounded-lg border border-input transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:bg-input/50 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-disabled:bg-input/80 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5", className),
|
|
15
|
+
...props
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
const inputGroupAddonVariants = cva("flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4", {
|
|
19
|
+
variants: { align: {
|
|
20
|
+
"inline-start": "order-first pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem]",
|
|
21
|
+
"inline-end": "order-last pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem]",
|
|
22
|
+
"block-start": "order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2",
|
|
23
|
+
"block-end": "order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2"
|
|
24
|
+
} },
|
|
25
|
+
defaultVariants: { align: "inline-start" }
|
|
26
|
+
});
|
|
27
|
+
function InputGroupAddon({ className, align = "inline-start", ...props }) {
|
|
28
|
+
return /* @__PURE__ */ jsx("div", {
|
|
29
|
+
role: "group",
|
|
30
|
+
"data-slot": "input-group-addon",
|
|
31
|
+
"data-align": align,
|
|
32
|
+
className: cn(inputGroupAddonVariants({ align }), className),
|
|
33
|
+
onClick: (e) => {
|
|
34
|
+
if (e.target.closest("button")) return;
|
|
35
|
+
e.currentTarget.parentElement?.querySelector("input, textarea")?.focus();
|
|
36
|
+
},
|
|
37
|
+
...props
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
const inputGroupButtonVariants = cva("flex items-center gap-2 text-sm shadow-none", {
|
|
41
|
+
variants: { size: {
|
|
42
|
+
xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
|
|
43
|
+
sm: "",
|
|
44
|
+
"icon-xs": "size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0",
|
|
45
|
+
"icon-sm": "size-8 p-0 has-[>svg]:p-0"
|
|
46
|
+
} },
|
|
47
|
+
defaultVariants: { size: "xs" }
|
|
48
|
+
});
|
|
49
|
+
function InputGroupButton({ className, type = "button", variant = "ghost", size = "xs", ...props }) {
|
|
50
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
51
|
+
type,
|
|
52
|
+
"data-size": size,
|
|
53
|
+
variant,
|
|
54
|
+
className: cn(inputGroupButtonVariants({ size }), className),
|
|
55
|
+
...props
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function InputGroupText({ className, ...props }) {
|
|
59
|
+
return /* @__PURE__ */ jsx("span", {
|
|
60
|
+
className: cn("flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4", className),
|
|
61
|
+
...props
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function InputGroupInput({ className, ...props }) {
|
|
65
|
+
return /* @__PURE__ */ jsx(Input, {
|
|
66
|
+
"data-slot": "input-group-control",
|
|
67
|
+
className: cn("flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent", className),
|
|
68
|
+
...props
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function InputGroupTextarea({ className, ...props }) {
|
|
72
|
+
return /* @__PURE__ */ jsx(Textarea, {
|
|
73
|
+
"data-slot": "input-group-control",
|
|
74
|
+
className: cn("flex-1 resize-none rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent", className),
|
|
75
|
+
...props
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { OTPInput } from "input-otp";
|
|
4
|
+
declare function InputOTP({ className, containerClassName, ...props }: React.ComponentProps<typeof OTPInput> & {
|
|
5
|
+
containerClassName?: string;
|
|
6
|
+
}): React.JSX.Element;
|
|
7
|
+
declare function InputOTPGroup({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
8
|
+
declare function InputOTPSlot({ index, className, ...props }: React.ComponentProps<"div"> & {
|
|
9
|
+
index: number;
|
|
10
|
+
}): React.JSX.Element;
|
|
11
|
+
declare function InputOTPSeparator({ ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
12
|
+
export { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import { cn } from "../lib/cn.js";
|
|
4
|
+
import { recentUserAction } from "../lib/user-action.js";
|
|
5
|
+
import { useCue } from "../sound/sound-map.js";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
import { OTPInput, OTPInputContext } from "input-otp";
|
|
9
|
+
// src/input-otp/input-otp.tsx
|
|
10
|
+
function InputOTP({ className, containerClassName, ...props }) {
|
|
11
|
+
const cue = useCue("input-otp");
|
|
12
|
+
const invalid = props["aria-invalid"] === true || props["aria-invalid"] === "true";
|
|
13
|
+
const complete = typeof props.value === "string" && props.value.length === props.maxLength;
|
|
14
|
+
const wasInvalid = React.useRef(invalid);
|
|
15
|
+
React.useEffect(() => {
|
|
16
|
+
if (invalid && !wasInvalid.current && complete && recentUserAction()) cue("invalid");
|
|
17
|
+
wasInvalid.current = invalid;
|
|
18
|
+
}, [
|
|
19
|
+
invalid,
|
|
20
|
+
complete,
|
|
21
|
+
cue
|
|
22
|
+
]);
|
|
23
|
+
return /* @__PURE__ */ jsx(OTPInput, {
|
|
24
|
+
"data-slot": "input-otp",
|
|
25
|
+
containerClassName: cn("cn-input-otp flex items-center has-disabled:opacity-50", containerClassName),
|
|
26
|
+
spellCheck: false,
|
|
27
|
+
className: cn("disabled:cursor-not-allowed", className),
|
|
28
|
+
...props
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function InputOTPGroup({ className, ...props }) {
|
|
32
|
+
return /* @__PURE__ */ jsx("div", {
|
|
33
|
+
"data-slot": "input-otp-group",
|
|
34
|
+
className: cn("flex items-center rounded-lg has-aria-invalid:border-destructive has-aria-invalid:ring-3 has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40", className),
|
|
35
|
+
...props
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function InputOTPSlot({ index, className, ...props }) {
|
|
39
|
+
const { char, hasFakeCaret, isActive } = React.useContext(OTPInputContext)?.slots[index] ?? {};
|
|
40
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
41
|
+
"data-slot": "input-otp-slot",
|
|
42
|
+
"data-active": isActive,
|
|
43
|
+
className: cn("relative flex size-8 items-center justify-center border-y border-r border-input text-sm transition-all outline-none first:rounded-l-lg first:border-l last:rounded-r-lg aria-invalid:border-destructive data-[active=true]:z-10 data-[active=true]:border-ring data-[active=true]:ring-3 data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:border-destructive data-[active=true]:aria-invalid:ring-destructive/20 dark:bg-input/30 dark:data-[active=true]:aria-invalid:ring-destructive/40", className),
|
|
44
|
+
...props,
|
|
45
|
+
children: [char && /* @__PURE__ */ jsx("span", {
|
|
46
|
+
"data-slot": "input-otp-char",
|
|
47
|
+
children: char
|
|
48
|
+
}, char), hasFakeCaret && /* @__PURE__ */ jsx("div", {
|
|
49
|
+
className: "pointer-events-none absolute inset-0 flex items-center justify-center",
|
|
50
|
+
children: /* @__PURE__ */ jsx("div", { className: "h-4 w-px animate-caret-blink bg-foreground" })
|
|
51
|
+
})]
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function InputOTPSeparator({ ...props }) {
|
|
55
|
+
return /* @__PURE__ */ jsx("div", {
|
|
56
|
+
"data-slot": "input-otp-separator",
|
|
57
|
+
className: "flex items-center [&_svg:not([class*='size-'])]:size-4",
|
|
58
|
+
role: "separator",
|
|
59
|
+
...props,
|
|
60
|
+
children: /* @__PURE__ */ jsx("svg", {
|
|
61
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
62
|
+
viewBox: "0 0 24 24",
|
|
63
|
+
fill: "none",
|
|
64
|
+
stroke: "currentColor",
|
|
65
|
+
strokeWidth: "2",
|
|
66
|
+
strokeLinecap: "round",
|
|
67
|
+
strokeLinejoin: "round",
|
|
68
|
+
"aria-hidden": "true",
|
|
69
|
+
children: /* @__PURE__ */ jsx("path", { d: "M5 12h14" })
|
|
70
|
+
})
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
export { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot };
|
package/dist/kbd/kbd.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
// src/kbd/kbd.tsx
|
|
5
|
+
function Kbd({ className, ...props }) {
|
|
6
|
+
return /* @__PURE__ */ jsx("kbd", {
|
|
7
|
+
"data-slot": "kbd",
|
|
8
|
+
className: cn("pointer-events-none inline-flex h-5 w-fit min-w-5 items-center justify-center gap-1 rounded-sm bg-muted px-1 font-sans text-xs font-medium text-muted-foreground select-none in-data-[slot=tooltip-content]:bg-background/20 in-data-[slot=tooltip-content]:text-background dark:in-data-[slot=tooltip-content]:bg-background/10 [&_svg:not([class*='size-'])]:size-3", className),
|
|
9
|
+
...props
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function KbdGroup({ className, ...props }) {
|
|
13
|
+
return /* @__PURE__ */ jsx("kbd", {
|
|
14
|
+
"data-slot": "kbd-group",
|
|
15
|
+
className: cn("inline-flex items-center gap-1", className),
|
|
16
|
+
...props
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export { Kbd, KbdGroup };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import { cn } from "../lib/cn.js";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
// src/label/label.tsx
|
|
6
|
+
function Label({ className, ...props }) {
|
|
7
|
+
return /* @__PURE__ */ jsx("label", {
|
|
8
|
+
"data-slot": "label",
|
|
9
|
+
className: cn("flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50 peer-data-disabled:cursor-not-allowed peer-data-disabled:opacity-50", className),
|
|
10
|
+
...props
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export { Label };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
import { blur, scale, spring } from "../../tokens/dist/motion.js";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { AnimatePresence, motion } from "motion/react";
|
|
6
|
+
// src/legacy/icon-button/icon-swap.tsx
|
|
7
|
+
const INSTANT = { duration: 0 };
|
|
8
|
+
const blurred = (radius) => `blur(${radius}px)`;
|
|
9
|
+
/**
|
|
10
|
+
* Swap states, as functions of `custom`, so an exiting icon reads the latest instant / reduced
|
|
11
|
+
* values from AnimatePresence rather than the props it had when it was last rendered. Instant
|
|
12
|
+
* and reduced swaps never scale or blur, not even for a frame.
|
|
13
|
+
*/
|
|
14
|
+
const iconSwapVariants = {
|
|
15
|
+
hidden: ({ instant, reduced }) => ({
|
|
16
|
+
opacity: 0,
|
|
17
|
+
transform: `scale(${instant || reduced ? 1 : scale["icon-from"]})`,
|
|
18
|
+
filter: blurred(instant || reduced ? 0 : blur.icon),
|
|
19
|
+
transition: instant ? INSTANT : spring.icon
|
|
20
|
+
}),
|
|
21
|
+
shown: ({ instant }) => ({
|
|
22
|
+
opacity: 1,
|
|
23
|
+
transform: "scale(1)",
|
|
24
|
+
filter: blurred(0),
|
|
25
|
+
transition: instant ? INSTANT : spring.icon,
|
|
26
|
+
transitionEnd: { filter: "none" }
|
|
27
|
+
})
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Cross-fades between icons stacked in one grid cell, so the container never resizes. Nothing
|
|
31
|
+
* animates on mount (`initial={false}`); springs retarget from the live value when interrupted,
|
|
32
|
+
* and the latest content always wins.
|
|
33
|
+
*/
|
|
34
|
+
function IconSwap({ contentKey, instant, reduced, slot, layerClassName, className, children }) {
|
|
35
|
+
const custom = {
|
|
36
|
+
instant,
|
|
37
|
+
reduced
|
|
38
|
+
};
|
|
39
|
+
return /* @__PURE__ */ jsx("span", {
|
|
40
|
+
"aria-hidden": "true",
|
|
41
|
+
className: cn(className, "grid place-items-center"),
|
|
42
|
+
children: /* @__PURE__ */ jsx(AnimatePresence, {
|
|
43
|
+
initial: false,
|
|
44
|
+
custom,
|
|
45
|
+
children: /* @__PURE__ */ jsx(motion.span, {
|
|
46
|
+
"data-slot": slot,
|
|
47
|
+
custom,
|
|
48
|
+
variants: iconSwapVariants,
|
|
49
|
+
initial: "hidden",
|
|
50
|
+
animate: "shown",
|
|
51
|
+
exit: "hidden",
|
|
52
|
+
className: cn("inline-flex size-full items-center justify-center [grid-area:1/1] [&_svg]:size-full", layerClassName),
|
|
53
|
+
children
|
|
54
|
+
}, contentKey)
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
export { IconSwap, iconSwapVariants };
|
package/dist/lib/cn.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
// src/lib/control-defaults.tsx
|
|
4
|
+
const ControlDefaultsContext = createContext({});
|
|
5
|
+
function useControlDefaults() {
|
|
6
|
+
return useContext(ControlDefaultsContext);
|
|
7
|
+
}
|
|
8
|
+
export { ControlDefaultsContext, useControlDefaults };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
export interface IconSwapProps {
|
|
4
|
+
/** Changes when the shown icon changes; the old one cross-fades out on `spring.icon`. */
|
|
5
|
+
contentKey: string;
|
|
6
|
+
/** Classes for the stack, which sets the size (e.g. `size-4`). */
|
|
7
|
+
className?: string | undefined;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Cross-fades icons in one cell: scale 0.25 → 1, opacity, blur 4 → 0 on `spring.icon`. Instant
|
|
12
|
+
* after a key press (input modality, #71 (3)); an opacity fade only under reduced motion (the OS,
|
|
13
|
+
* a MotionConfig or `<html data-motion>`). Nothing animates on mount.
|
|
14
|
+
*/
|
|
15
|
+
export declare function IconSwap({ contentKey, className, children }: IconSwapProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { getInputModality } from "./input-modality.js";
|
|
3
|
+
import { IconSwap as IconSwap$1 } from "../legacy/icon-button/icon-swap.js";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { useReducedMotion, useReducedMotionConfig } from "motion/react";
|
|
6
|
+
// src/lib/icon-swap.tsx
|
|
7
|
+
/**
|
|
8
|
+
* Cross-fades icons in one cell: scale 0.25 → 1, opacity, blur 4 → 0 on `spring.icon`. Instant
|
|
9
|
+
* after a key press (input modality, #71 (3)); an opacity fade only under reduced motion (the OS,
|
|
10
|
+
* a MotionConfig or `<html data-motion>`). Nothing animates on mount.
|
|
11
|
+
*/
|
|
12
|
+
function IconSwap({ contentKey, className, children }) {
|
|
13
|
+
const prefersReduced = useReducedMotion() ?? false;
|
|
14
|
+
const configReduced = useReducedMotionConfig() ?? false;
|
|
15
|
+
const html = typeof document === "undefined" ? void 0 : document.documentElement.dataset.motion;
|
|
16
|
+
const reduced = html === "reduce" || html !== "full" && (prefersReduced || configReduced);
|
|
17
|
+
return /* @__PURE__ */ jsx(IconSwap$1, {
|
|
18
|
+
contentKey,
|
|
19
|
+
instant: getInputModality() === "keyboard",
|
|
20
|
+
reduced,
|
|
21
|
+
slot: "icon-swap",
|
|
22
|
+
className,
|
|
23
|
+
children
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export { IconSwap };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
// src/lib/input-modality.ts
|
|
3
|
+
let modality = "pointer";
|
|
4
|
+
let installed = false;
|
|
5
|
+
let interactedAt = null;
|
|
6
|
+
/** The attribute on <html> that feel.css reads: keyboard-opened surfaces open without motion (#71, #108). */
|
|
7
|
+
const MODALITY_ATTRIBUTE = "data-nsaa-input";
|
|
8
|
+
/**
|
|
9
|
+
* Tracks the latest input modality in the capture phase, so a state change driven by a page
|
|
10
|
+
* hotkey (Space, M, mod+B, mod+K) is known to be keyboard-initiated even though no button was
|
|
11
|
+
* clicked. A pointer that moves takes over again, so hovering after typing animates. Idempotent;
|
|
12
|
+
* `@nsaa/core` installs it when it loads.
|
|
13
|
+
*/
|
|
14
|
+
function trackInputModality() {
|
|
15
|
+
if (installed || typeof document === "undefined") return;
|
|
16
|
+
installed = true;
|
|
17
|
+
document.addEventListener("keydown", () => interact("keyboard"), true);
|
|
18
|
+
document.addEventListener("pointerdown", () => interact("pointer"), true);
|
|
19
|
+
document.addEventListener("pointermove", () => setInputModality("pointer"), true);
|
|
20
|
+
}
|
|
21
|
+
function interact(next) {
|
|
22
|
+
interactedAt = Date.now();
|
|
23
|
+
setInputModality(next);
|
|
24
|
+
}
|
|
25
|
+
/** When the person last pressed a key or a pointer (not a pointer move), or null before that. */
|
|
26
|
+
function lastInteractionAt() {
|
|
27
|
+
return interactedAt;
|
|
28
|
+
}
|
|
29
|
+
function setInputModality(next) {
|
|
30
|
+
if (next === modality && installed) {
|
|
31
|
+
if (document.documentElement.getAttribute("data-nsaa-input") === next) return;
|
|
32
|
+
}
|
|
33
|
+
modality = next;
|
|
34
|
+
if (typeof document !== "undefined") document.documentElement.setAttribute(MODALITY_ATTRIBUTE, next);
|
|
35
|
+
}
|
|
36
|
+
function getInputModality() {
|
|
37
|
+
return modality;
|
|
38
|
+
}
|
|
39
|
+
export { MODALITY_ATTRIBUTE, getInputModality, lastInteractionAt, setInputModality, trackInputModality };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
// src/lib/merge-refs.ts
|
|
3
|
+
/** Combines refs into one callback ref (React 19 cleanup-aware). */
|
|
4
|
+
function mergeRefs(...refs) {
|
|
5
|
+
return (node) => {
|
|
6
|
+
const cleanups = [];
|
|
7
|
+
for (const ref of refs) if (typeof ref === "function") {
|
|
8
|
+
const cleanup = ref(node);
|
|
9
|
+
cleanups.push(typeof cleanup === "function" ? cleanup : () => ref(null));
|
|
10
|
+
} else if (ref) {
|
|
11
|
+
ref.current = node;
|
|
12
|
+
cleanups.push(() => {
|
|
13
|
+
ref.current = null;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return () => {
|
|
17
|
+
for (const cleanup of cleanups) cleanup();
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export { mergeRefs };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
// src/lib/shortcut.ts
|
|
3
|
+
const APPLE = /Mac|iPhone|iPad|iPod/i;
|
|
4
|
+
function isApple() {
|
|
5
|
+
if (typeof navigator === "undefined") return false;
|
|
6
|
+
const nav = navigator;
|
|
7
|
+
return APPLE.test(nav.userAgentData?.platform ?? nav.platform ?? nav.userAgent);
|
|
8
|
+
}
|
|
9
|
+
const APPLE_KEYS = {
|
|
10
|
+
mod: "⌘",
|
|
11
|
+
ctrl: "⌃",
|
|
12
|
+
alt: "⌥",
|
|
13
|
+
shift: "⇧"
|
|
14
|
+
};
|
|
15
|
+
const OTHER_KEYS = {
|
|
16
|
+
mod: "Ctrl",
|
|
17
|
+
ctrl: "Ctrl",
|
|
18
|
+
alt: "Alt",
|
|
19
|
+
shift: "Shift"
|
|
20
|
+
};
|
|
21
|
+
const ARIA_KEYS = {
|
|
22
|
+
mod: ["Meta", "Control"],
|
|
23
|
+
ctrl: ["Control", "Control"],
|
|
24
|
+
alt: ["Alt", "Alt"],
|
|
25
|
+
shift: ["Shift", "Shift"]
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* The same shortcut for `aria-keyshortcuts` (`"mod+B"` → `"Meta+B"` on Apple, `"Control+B"`
|
|
29
|
+
* elsewhere), so assistive tech gets what the tooltip shows only visually.
|
|
30
|
+
*/
|
|
31
|
+
function ariaShortcut(shortcut, apple = isApple()) {
|
|
32
|
+
return shortcut.split("+").map((part) => {
|
|
33
|
+
const key = part.trim();
|
|
34
|
+
const named = ARIA_KEYS[key.toLowerCase()];
|
|
35
|
+
if (named) return apple ? named[0] : named[1];
|
|
36
|
+
return key.length === 1 ? key.toUpperCase() : key;
|
|
37
|
+
}).join("+");
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Formats a display-only shortcut such as `"mod+B"`: `⌘B` on Apple platforms, `Ctrl+B` elsewhere.
|
|
41
|
+
* The app binds the keys; this only shows them.
|
|
42
|
+
*/
|
|
43
|
+
function formatShortcut(shortcut, apple = isApple()) {
|
|
44
|
+
const keys = apple ? APPLE_KEYS : OTHER_KEYS;
|
|
45
|
+
return shortcut.split("+").map((part) => {
|
|
46
|
+
const key = part.trim();
|
|
47
|
+
return keys[key.toLowerCase()] ?? (key.length === 1 ? key.toUpperCase() : key);
|
|
48
|
+
}).join(apple ? "" : "+");
|
|
49
|
+
}
|
|
50
|
+
export { ariaShortcut, formatShortcut };
|
package/dist/lib/tv.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { scale, spring } from "../tokens/dist/motion.js";
|
|
3
|
+
import { useCallback, useRef } from "react";
|
|
4
|
+
import { animate, useReducedMotion, useReducedMotionConfig } from "motion/react";
|
|
5
|
+
// src/lib/use-press.ts
|
|
6
|
+
/**
|
|
7
|
+
* Parts of a larger shape, or high-frequency toggles: their buttons don't scale on their own
|
|
8
|
+
* (legacy `pressScale={false}`). A Toggle Group outside a Toolbar counts too (#128, alpha-4), and
|
|
9
|
+
* Pagination and the Calendar's day grid (#136).
|
|
10
|
+
*/
|
|
11
|
+
const SEGMENT = "[data-slot=\"input-group\"], [data-slot=\"button-group\"], [data-slot=\"toolbar\"], [data-slot=\"toggle-group\"], [data-slot=\"pagination-link\"], [data-slot=\"calendar\"]";
|
|
12
|
+
/**
|
|
13
|
+
* Pointer-only press: scale to `scale.press` on pointer-down and back on release, on `spring.snap`,
|
|
14
|
+
* interruptible from the live value. Never on hover, on keyboard activation, when disabled, under
|
|
15
|
+
* reduced motion (the OS or `<html data-motion>`), or inside a segmented shape.
|
|
16
|
+
*/
|
|
17
|
+
function usePress() {
|
|
18
|
+
const prefersReduced = useReducedMotion() ?? false;
|
|
19
|
+
const configReduced = useReducedMotionConfig() ?? false;
|
|
20
|
+
const pressed = useRef(null);
|
|
21
|
+
const reduced = useCallback(() => {
|
|
22
|
+
const html = document.documentElement.dataset.motion;
|
|
23
|
+
if (html === "reduce") return true;
|
|
24
|
+
if (html === "full") return false;
|
|
25
|
+
return prefersReduced || configReduced;
|
|
26
|
+
}, [prefersReduced, configReduced]);
|
|
27
|
+
const release = useCallback(() => {
|
|
28
|
+
const el = pressed.current;
|
|
29
|
+
if (!el) return;
|
|
30
|
+
pressed.current = null;
|
|
31
|
+
animate(el, { scale: 1 }, spring.snap);
|
|
32
|
+
}, []);
|
|
33
|
+
return {
|
|
34
|
+
onPointerDown: useCallback((event) => {
|
|
35
|
+
const el = event.currentTarget;
|
|
36
|
+
if (event.defaultPrevented || event.button !== 0 || reduced()) return;
|
|
37
|
+
if (el.matches(":disabled, [aria-disabled='true'], [data-disabled]")) return;
|
|
38
|
+
if (el.closest(SEGMENT)) return;
|
|
39
|
+
if (el.hasAttribute("aria-haspopup")) return;
|
|
40
|
+
pressed.current = el;
|
|
41
|
+
animate(el, { scale: scale.press }, spring.snap);
|
|
42
|
+
}, [reduced]),
|
|
43
|
+
onPointerUp: release,
|
|
44
|
+
onPointerLeave: release,
|
|
45
|
+
onPointerCancel: release
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export { usePress };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { lastInteractionAt } from "./input-modality.js";
|
|
3
|
+
// src/lib/user-action.ts
|
|
4
|
+
/** How long after a key press or pointer down something counts as its result (the browsers' own
|
|
5
|
+
* transient-activation window). */
|
|
6
|
+
const USER_ACTION_WINDOW_MS = 5e3;
|
|
7
|
+
/** True when the person pressed a key or a pointer within the window: a state that appears now is
|
|
8
|
+
* most likely their action's result (a failed payment Alert), not something on load. */
|
|
9
|
+
function recentUserAction(now = Date.now()) {
|
|
10
|
+
const at = lastInteractionAt();
|
|
11
|
+
return at !== null && now - at < 5e3;
|
|
12
|
+
}
|
|
13
|
+
export { USER_ACTION_WINDOW_MS, recentUserAction };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
|
|
2
|
+
import { SpinnerProps } from "./types.js";
|
|
3
|
+
import { CapProps } from "./cap.js";
|
|
4
|
+
import { EasingProps } from "./easing.js";
|
|
5
|
+
export interface ArcProps extends SpinnerProps, EasingProps, CapProps {}
|
|
6
|
+
export declare function Arc({ cap, easing, ...rest }: ArcProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { linecap } from "./cap.js";
|
|
3
|
+
import { rotationCss, spinClass } from "./easing.js";
|
|
4
|
+
import { SpinnerStyle, spinnerRoot } from "./frame.js";
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
// src/loaders/arc.tsx
|
|
7
|
+
const css = `
|
|
8
|
+
${rotationCss("arc")}
|
|
9
|
+
`;
|
|
10
|
+
function Arc({ cap, easing, ...rest }) {
|
|
11
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SpinnerStyle, {
|
|
12
|
+
name: "arc",
|
|
13
|
+
children: css
|
|
14
|
+
}), /* @__PURE__ */ jsx("svg", {
|
|
15
|
+
...spinnerRoot("arc", rest),
|
|
16
|
+
fill: "none",
|
|
17
|
+
role: "presentation",
|
|
18
|
+
viewBox: "0 0 24 24",
|
|
19
|
+
children: /* @__PURE__ */ jsx("circle", {
|
|
20
|
+
className: spinClass("arc", easing),
|
|
21
|
+
cx: "12",
|
|
22
|
+
cy: "12",
|
|
23
|
+
r: "10",
|
|
24
|
+
stroke: "currentColor",
|
|
25
|
+
strokeDasharray: "18 44.8",
|
|
26
|
+
strokeLinecap: linecap(cap),
|
|
27
|
+
strokeWidth: "2.5"
|
|
28
|
+
})
|
|
29
|
+
})] });
|
|
30
|
+
}
|
|
31
|
+
export { Arc };
|