@nexub/react 4.1.0 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/accessibility.json +23 -1
- package/dist/components/Aurora/Aurora.d.ts +3 -0
- package/dist/components/Aurora/Aurora.js +12 -0
- package/dist/components/Aurora/index.d.ts +2 -0
- package/dist/components/Aurora/index.js +4 -0
- package/dist/components/Button/Button.d.ts +3 -0
- package/dist/components/Button/Button.js +8 -0
- package/dist/components/Card/Card.d.ts +3 -2
- package/dist/components/Card/Card.js +3 -2
- package/dist/components/Celebrate/Celebrate.d.ts +9 -0
- package/dist/components/Celebrate/Celebrate.js +31 -0
- package/dist/components/Celebrate/index.d.ts +2 -0
- package/dist/components/Celebrate/index.js +4 -0
- package/dist/hooks/usePointerSheen.js +2 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/styles.css +1 -1
- package/package.json +6 -6
package/accessibility.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "4.
|
|
2
|
+
"version": "4.3.0",
|
|
3
3
|
"standard": "WCAG 2.2 Level AA",
|
|
4
4
|
"method": {
|
|
5
5
|
"automated": "axe-core rules tagged wcag2a, wcag2aa, wcag21a, wcag21aa and wcag22aa, run on every Storybook story in light and dark on every pull request; a new violation fails the build.",
|
|
@@ -69,6 +69,17 @@
|
|
|
69
69
|
"keyboard": [],
|
|
70
70
|
"screenReader": []
|
|
71
71
|
},
|
|
72
|
+
{
|
|
73
|
+
"slug": "aurora",
|
|
74
|
+
"name": "Aurora",
|
|
75
|
+
"package": "@nexub/react",
|
|
76
|
+
"automated": "pass",
|
|
77
|
+
"exceptions": [],
|
|
78
|
+
"keyboard": [],
|
|
79
|
+
"screenReader": [
|
|
80
|
+
"Decorative: the whole layer is `aria-hidden`."
|
|
81
|
+
]
|
|
82
|
+
},
|
|
72
83
|
{
|
|
73
84
|
"slug": "autocomplete",
|
|
74
85
|
"name": "Autocomplete",
|
|
@@ -183,6 +194,17 @@
|
|
|
183
194
|
"Prefer CardLink over wrapping the whole card in `<a>`: the link’s accessible name stays the title instead of every word on the card."
|
|
184
195
|
]
|
|
185
196
|
},
|
|
197
|
+
{
|
|
198
|
+
"slug": "celebrate",
|
|
199
|
+
"name": "Celebrate",
|
|
200
|
+
"package": "@nexub/react",
|
|
201
|
+
"automated": "pass",
|
|
202
|
+
"exceptions": [],
|
|
203
|
+
"keyboard": [],
|
|
204
|
+
"screenReader": [
|
|
205
|
+
"Decorative (`aria-hidden`). Announce the win in text, for example in a Toast or a status message."
|
|
206
|
+
]
|
|
207
|
+
},
|
|
186
208
|
{
|
|
187
209
|
"slug": "checkbox-card",
|
|
188
210
|
"name": "Checkbox Card",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
|
+
const Aurora = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs("div", { ref, "aria-hidden": "true", className: cn("nx-aurora", className), ...props, children: [
|
|
5
|
+
/* @__PURE__ */ jsx("span", {}),
|
|
6
|
+
/* @__PURE__ */ jsx("span", {}),
|
|
7
|
+
/* @__PURE__ */ jsx("span", {})
|
|
8
|
+
] }));
|
|
9
|
+
Aurora.displayName = "Aurora";
|
|
10
|
+
export {
|
|
11
|
+
Aurora
|
|
12
|
+
};
|
|
@@ -26,5 +26,8 @@ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElemen
|
|
|
26
26
|
leadingIcon?: React.ReactNode;
|
|
27
27
|
trailingIcon?: React.ReactNode;
|
|
28
28
|
asChild?: boolean;
|
|
29
|
+
/** 4.3: the button drifts a few pixels toward the pointer on hover. For one key action per screen.
|
|
30
|
+
* Off for touch and reduced motion. */
|
|
31
|
+
magnetic?: boolean;
|
|
29
32
|
}
|
|
30
33
|
export declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -4,6 +4,7 @@ import * as React from "react";
|
|
|
4
4
|
import { Slot } from "@radix-ui/react-slot";
|
|
5
5
|
import { Loader2 } from "@nexub/icons";
|
|
6
6
|
import { cva } from "class-variance-authority";
|
|
7
|
+
import { usePointerSheen } from "../../hooks/usePointerSheen.js";
|
|
7
8
|
import { cn } from "../../utils/cn.js";
|
|
8
9
|
import { disabledContainer, disabledText, pressable } from "../../utils/control.js";
|
|
9
10
|
import { glassSurfaceClass } from "../../utils/glass.js";
|
|
@@ -81,20 +82,27 @@ const Button = React.forwardRef(
|
|
|
81
82
|
leadingIcon,
|
|
82
83
|
trailingIcon,
|
|
83
84
|
asChild = false,
|
|
85
|
+
magnetic = false,
|
|
84
86
|
disabled,
|
|
85
87
|
onClick,
|
|
88
|
+
onPointerMove,
|
|
86
89
|
children,
|
|
87
90
|
...props
|
|
88
91
|
}, ref) => {
|
|
89
92
|
const status = statusProp ?? (loading ? "loading" : "idle");
|
|
93
|
+
const handlePointerMove = usePointerSheen(magnetic, onPointerMove);
|
|
90
94
|
const sharedProps = {
|
|
91
95
|
className: cn(
|
|
92
96
|
buttonVariants({ variant, size, fullWidth }),
|
|
93
97
|
tone ? toneClasses[tone] : "",
|
|
94
98
|
!asChild && status === "error" && "nx-shake",
|
|
99
|
+
magnetic && "nx-magnetic",
|
|
95
100
|
className
|
|
96
101
|
),
|
|
102
|
+
onPointerMove: handlePointerMove,
|
|
97
103
|
"data-tone": tone,
|
|
104
|
+
// Styling hook for opt-in layers (vivid, marketing); no styles depend on it by default.
|
|
105
|
+
"data-variant": variant ?? "primary",
|
|
98
106
|
...variant === "glass" && { "data-material": "glass", "data-glass-thickness": "thin" },
|
|
99
107
|
...props
|
|
100
108
|
};
|
|
@@ -8,8 +8,9 @@ export declare const cardVariants: (props?: ({
|
|
|
8
8
|
export interface CardProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof cardVariants> {
|
|
9
9
|
tone?: ToneValue;
|
|
10
10
|
surface?: 'solid' | 'glass';
|
|
11
|
-
/** `sheen`: a soft light follows the pointer (
|
|
12
|
-
|
|
11
|
+
/** `sheen`: a soft light follows the pointer. `tilt` (4.3): the card also leans toward the pointer in 3D.
|
|
12
|
+
* Opt-in; off for touch and reduced motion. */
|
|
13
|
+
effect?: 'none' | 'sheen' | 'tilt';
|
|
13
14
|
/** Product accent for `variant="showcase"`: a coloured top edge and tint in marketing mode. Sets `data-product`. */
|
|
14
15
|
accent?: 'leap' | 'bookub' | 'payub' | 'founderub';
|
|
15
16
|
asChild?: boolean;
|
|
@@ -52,15 +52,16 @@ const Card = React.forwardRef(
|
|
|
52
52
|
({ className, variant = "flat", surface = "solid", effect = "none", tone, accent, asChild = false, onPointerMove, children, ...props }, ref) => {
|
|
53
53
|
const Comp = asChild ? Slot : "div";
|
|
54
54
|
const toneStyle = tone ? toneBorderMap[tone] : "";
|
|
55
|
-
const sheen = effect === "sheen";
|
|
55
|
+
const sheen = effect === "sheen" || effect === "tilt";
|
|
56
56
|
const handlePointerMove = usePointerSheen(sheen, onPointerMove);
|
|
57
57
|
return /* @__PURE__ */ jsx(
|
|
58
58
|
Comp,
|
|
59
59
|
{
|
|
60
60
|
ref,
|
|
61
|
-
className: cn(cardVariants({ variant, surface }), toneStyle, sheen && "nx-sheen", className),
|
|
61
|
+
className: cn(cardVariants({ variant, surface }), toneStyle, sheen && "nx-sheen", effect === "tilt" && "nx-tilt", className),
|
|
62
62
|
onPointerMove: handlePointerMove,
|
|
63
63
|
"data-tone": tone,
|
|
64
|
+
"data-variant": variant ?? "flat",
|
|
64
65
|
"data-product": accent,
|
|
65
66
|
"data-material": surface === "glass" ? "glass" : void 0,
|
|
66
67
|
...props,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface CelebrateProps {
|
|
3
|
+
/** Bursts each time this goes from false to true. */
|
|
4
|
+
active: boolean;
|
|
5
|
+
/** Number of pieces. @default 28 */
|
|
6
|
+
count?: number;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function Celebrate({ active, count, className }: CelebrateProps): React.JSX.Element | null;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "../../utils/cn.js";
|
|
5
|
+
const COLORS = ["bg-chart-1", "bg-chart-2", "bg-chart-3", "bg-chart-4", "bg-chart-5", "bg-chart-6", "bg-chart-7", "bg-chart-8"];
|
|
6
|
+
function Celebrate({ active, count = 28, className }) {
|
|
7
|
+
const ref = React.useRef(null);
|
|
8
|
+
const [burst, setBurst] = React.useState(0);
|
|
9
|
+
const was = React.useRef(false);
|
|
10
|
+
React.useEffect(() => {
|
|
11
|
+
if (active && !was.current) setBurst((b) => b + 1);
|
|
12
|
+
was.current = active;
|
|
13
|
+
}, [active]);
|
|
14
|
+
React.useLayoutEffect(() => {
|
|
15
|
+
const el = ref.current;
|
|
16
|
+
if (!burst || !el) return;
|
|
17
|
+
for (const piece of Array.from(el.children)) {
|
|
18
|
+
const angle = Math.random() * Math.PI * 2;
|
|
19
|
+
const distance = 60 + Math.random() * 90;
|
|
20
|
+
piece.style.setProperty("--x", `${Math.cos(angle) * distance}px`);
|
|
21
|
+
piece.style.setProperty("--y", `${Math.sin(angle) * distance + 40}px`);
|
|
22
|
+
piece.style.setProperty("--r", `${Math.random() * 540 - 270}deg`);
|
|
23
|
+
piece.style.setProperty("--d", `${Math.random() * 90}ms`);
|
|
24
|
+
}
|
|
25
|
+
}, [burst]);
|
|
26
|
+
if (!burst) return null;
|
|
27
|
+
return /* @__PURE__ */ jsx("div", { ref, "aria-hidden": "true", className: cn("nx-celebrate", className), children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx("span", { className: COLORS[i % COLORS.length] }, i)) }, burst);
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
Celebrate
|
|
31
|
+
};
|
|
@@ -14,6 +14,8 @@ function usePointerSheen(enabled, onPointerMove) {
|
|
|
14
14
|
const r = el.getBoundingClientRect();
|
|
15
15
|
el.style.setProperty("--nx-mx", `${clientX - r.left}px`);
|
|
16
16
|
el.style.setProperty("--nx-my", `${clientY - r.top}px`);
|
|
17
|
+
el.style.setProperty("--nx-px", String(r.width ? (clientX - r.left) / r.width : 0.5));
|
|
18
|
+
el.style.setProperty("--nx-py", String(r.height ? (clientY - r.top) / r.height : 0.5));
|
|
17
19
|
});
|
|
18
20
|
},
|
|
19
21
|
[onPointerMove]
|
package/dist/index.d.ts
CHANGED
|
@@ -36,6 +36,10 @@ export type { NumberInputProps } from './components/NumberInput/index.js';
|
|
|
36
36
|
export { MoneyInput } from './components/MoneyInput/index.js';
|
|
37
37
|
export type { MoneyInputProps } from './components/MoneyInput/index.js';
|
|
38
38
|
export { Amount } from './components/Amount/index.js';
|
|
39
|
+
export { Celebrate } from './components/Celebrate/index.js';
|
|
40
|
+
export type { CelebrateProps } from './components/Celebrate/index.js';
|
|
41
|
+
export { Aurora } from './components/Aurora/index.js';
|
|
42
|
+
export type { AuroraProps } from './components/Aurora/index.js';
|
|
39
43
|
export { BarChart, LineChart, DonutChart, Sparkline, ChartLegend, niceMax, niceDomain } from './components/Chart/index.js';
|
|
40
44
|
export type { BarChartProps, LineChartProps, DonutChartProps, SparklineProps, ChartLegendProps, ChartSeries, ChartColor } from './components/Chart/index.js';
|
|
41
45
|
export type { AmountProps } from './components/Amount/index.js';
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,8 @@ import { Textarea, textareaVariants } from "./components/Textarea/index.js";
|
|
|
21
21
|
import { NumberInput } from "./components/NumberInput/index.js";
|
|
22
22
|
import { MoneyInput } from "./components/MoneyInput/index.js";
|
|
23
23
|
import { Amount } from "./components/Amount/index.js";
|
|
24
|
+
import { Celebrate } from "./components/Celebrate/index.js";
|
|
25
|
+
import { Aurora } from "./components/Aurora/index.js";
|
|
24
26
|
import { BarChart, LineChart, DonutChart, Sparkline, ChartLegend, niceMax, niceDomain } from "./components/Chart/index.js";
|
|
25
27
|
import { NumberTicker } from "./components/NumberTicker/index.js";
|
|
26
28
|
import { SearchInput } from "./components/SearchInput/index.js";
|
|
@@ -118,6 +120,7 @@ export {
|
|
|
118
120
|
Amount,
|
|
119
121
|
AppShell,
|
|
120
122
|
AspectRatio,
|
|
123
|
+
Aurora,
|
|
121
124
|
Autocomplete,
|
|
122
125
|
Avatar,
|
|
123
126
|
AvatarGroup,
|
|
@@ -129,6 +132,7 @@ export {
|
|
|
129
132
|
ButtonGroup,
|
|
130
133
|
Card,
|
|
131
134
|
CardLink,
|
|
135
|
+
Celebrate,
|
|
132
136
|
ChartLegend,
|
|
133
137
|
CheckList,
|
|
134
138
|
CheckListItem,
|