@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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.1.0",
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,3 @@
1
+ import * as React from 'react';
2
+ export type AuroraProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>;
3
+ export declare const Aurora: React.ForwardRefExoticComponent<AuroraProps & React.RefAttributes<HTMLDivElement>>;
@@ -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
+ };
@@ -0,0 +1,2 @@
1
+ export { Aurora } from './Aurora.js';
2
+ export type { AuroraProps } from './Aurora.js';
@@ -0,0 +1,4 @@
1
+ import { Aurora } from "./Aurora.js";
2
+ export {
3
+ Aurora
4
+ };
@@ -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 (opt-in; off for touch and reduced motion). */
12
- effect?: 'none' | 'sheen';
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
+ };
@@ -0,0 +1,2 @@
1
+ export { Celebrate } from './Celebrate.js';
2
+ export type { CelebrateProps } from './Celebrate.js';
@@ -0,0 +1,4 @@
1
+ import { Celebrate } from "./Celebrate.js";
2
+ export {
3
+ Celebrate
4
+ };
@@ -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,