@waveso/ui 0.15.0 → 0.16.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.
Files changed (129) hide show
  1. package/README.md +25 -22
  2. package/dist/accordion.d.ts +4 -20
  3. package/dist/accordion.js +2 -2
  4. package/dist/action-bar.d.ts +1 -10
  5. package/dist/action-bar.js +6 -5
  6. package/dist/alert-dialog.d.ts +12 -52
  7. package/dist/alert-dialog.js +5 -5
  8. package/dist/alert.d.ts +13 -22
  9. package/dist/alert.js +13 -4
  10. package/dist/animate.d.ts +6 -49
  11. package/dist/animate.js +8 -13
  12. package/dist/aspect-ratio.d.ts +3 -8
  13. package/dist/autocomplete.d.ts +21 -88
  14. package/dist/autocomplete.js +3 -3
  15. package/dist/avatar.d.ts +7 -28
  16. package/dist/avatar.js +4 -4
  17. package/dist/badge.d.ts +3 -11
  18. package/dist/badge.js +6 -6
  19. package/dist/breadcrumb.d.ts +7 -31
  20. package/dist/button-group.d.ts +7 -20
  21. package/dist/button-group.js +5 -4
  22. package/dist/button.d.ts +4 -12
  23. package/dist/button.js +6 -6
  24. package/dist/card.d.ts +16 -33
  25. package/dist/card.js +27 -14
  26. package/dist/checkbox.d.ts +1 -6
  27. package/dist/checkbox.js +2 -2
  28. package/dist/collapsible.d.ts +3 -12
  29. package/dist/combobox.d.ts +18 -81
  30. package/dist/combobox.js +4 -4
  31. package/dist/context-menu.d.ts +17 -68
  32. package/dist/context-menu.js +14 -14
  33. package/dist/count.d.ts +1 -15
  34. package/dist/count.js +3 -2
  35. package/dist/dialog.d.ts +10 -41
  36. package/dist/dialog.js +5 -5
  37. package/dist/direction.d.ts +0 -1
  38. package/dist/drawer.d.ts +11 -44
  39. package/dist/drawer.js +1 -1
  40. package/dist/encrypted-text.d.ts +15 -14
  41. package/dist/encrypted-text.js +205 -66
  42. package/dist/field.d.ts +27 -30
  43. package/dist/field.js +36 -8
  44. package/dist/fieldset.d.ts +14 -0
  45. package/dist/fieldset.js +26 -0
  46. package/dist/film-grain-shader.d.ts +3 -4
  47. package/dist/film-grain-webgl.d.ts +2 -9
  48. package/dist/film-grain-webgl.js +4 -1
  49. package/dist/film-grain.d.ts +1 -11
  50. package/dist/form.d.ts +23 -42
  51. package/dist/form.js +7 -4
  52. package/dist/glyph-matrix.d.ts +25 -0
  53. package/dist/glyph-matrix.js +266 -0
  54. package/dist/gradient-reveal-text.d.ts +4 -17
  55. package/dist/gradient-reveal-text.js +8 -8
  56. package/dist/hooks/use-mobile.d.ts +2 -3
  57. package/dist/infinite-scroll.d.ts +1 -16
  58. package/dist/input-group.d.ts +11 -37
  59. package/dist/input-group.js +1 -1
  60. package/dist/input-otp.d.ts +4 -20
  61. package/dist/input-otp.js +2 -2
  62. package/dist/input.d.ts +3 -11
  63. package/dist/input.js +1 -1
  64. package/dist/item.d.ts +14 -51
  65. package/dist/item.js +17 -11
  66. package/dist/kbd.d.ts +3 -11
  67. package/dist/kbd.js +2 -2
  68. package/dist/label.d.ts +1 -6
  69. package/dist/label.js +1 -1
  70. package/dist/lib/focus.d.ts +3 -5
  71. package/dist/lib/internal-icons.d.ts +19 -22
  72. package/dist/lib/merge-refs.d.ts +9 -0
  73. package/dist/lib/merge-refs.js +16 -0
  74. package/dist/lib/utils.d.ts +3 -5
  75. package/dist/lib/utils.js +9 -1
  76. package/dist/masonry.d.ts +2 -16
  77. package/dist/masonry.js +5 -3
  78. package/dist/menu.d.ts +17 -65
  79. package/dist/menu.js +7 -7
  80. package/dist/menubar.d.ts +16 -55
  81. package/dist/menubar.js +1 -1
  82. package/dist/pagination.d.ts +9 -33
  83. package/dist/pagination.js +1 -1
  84. package/dist/popover.d.ts +9 -43
  85. package/dist/popover.js +1 -1
  86. package/dist/preview-card.d.ts +5 -25
  87. package/dist/preview-card.js +1 -1
  88. package/dist/progress.d.ts +5 -24
  89. package/dist/progress.js +2 -2
  90. package/dist/radio-group.d.ts +2 -9
  91. package/dist/radio-group.js +1 -1
  92. package/dist/radio.d.ts +2 -10
  93. package/dist/radio.js +2 -2
  94. package/dist/resizable.d.ts +43 -0
  95. package/dist/resizable.js +53 -0
  96. package/dist/scroll-area.d.ts +14 -13
  97. package/dist/scroll-area.js +26 -7
  98. package/dist/select.d.ts +15 -64
  99. package/dist/select.js +4 -4
  100. package/dist/separator.d.ts +1 -7
  101. package/dist/separator.js +1 -1
  102. package/dist/sidebar.d.ts +29 -126
  103. package/dist/sidebar.js +14 -14
  104. package/dist/skeleton.d.ts +1 -6
  105. package/dist/slider.d.ts +1 -14
  106. package/dist/slider.js +5 -5
  107. package/dist/spinner.d.ts +8 -6
  108. package/dist/spinner.js +24 -6
  109. package/dist/styles.css +575 -182
  110. package/dist/switch.d.ts +2 -9
  111. package/dist/switch.js +6 -6
  112. package/dist/table.d.ts +14 -34
  113. package/dist/table.js +40 -9
  114. package/dist/tabs.d.ts +5 -22
  115. package/dist/tabs.js +3 -3
  116. package/dist/textarea.d.ts +3 -12
  117. package/dist/textarea.js +1 -1
  118. package/dist/toast.d.ts +13 -39
  119. package/dist/toast.js +4 -4
  120. package/dist/toggle-group.d.ts +3 -19
  121. package/dist/toggle-group.js +16 -10
  122. package/dist/toggle.d.ts +3 -11
  123. package/dist/toggle.js +11 -6
  124. package/dist/tooltip.d.ts +6 -24
  125. package/dist/tooltip.js +10 -6
  126. package/dist/typewriter.d.ts +1 -14
  127. package/dist/video-text.d.ts +25 -0
  128. package/dist/video-text.js +147 -0
  129. package/package.json +57 -51
package/dist/form.d.ts CHANGED
@@ -1,36 +1,12 @@
1
1
  import { Field } from "./field.js";
2
- import * as _$react_jsx_runtime0 from "react/jsx-runtime";
3
2
  import * as React from "react";
4
- import * as _$react_hook_form0 from "react-hook-form";
5
3
  import { ControllerFieldState, ControllerRenderProps, FieldPath, FieldValues, RegisterOptions, SubmitHandler, UseFormReturn, useForm, useWatch } from "react-hook-form";
6
-
7
4
  //#region src/form.d.ts
8
5
  type FormProps<TFieldValues extends FieldValues> = {
9
6
  form: UseFormReturn<TFieldValues>;
10
7
  onSubmit: SubmitHandler<TFieldValues>;
11
8
  } & Omit<React.ComponentProps<"form">, "onSubmit">;
12
9
  type FormRootProps = React.ComponentProps<"form">;
13
- type FormErrorProps = React.ComponentProps<"p">;
14
- type FormActionsProps = React.ComponentProps<"div">;
15
- type FormMessageProps = React.ComponentProps<"p">;
16
- declare function Form<TFieldValues extends FieldValues>({
17
- form,
18
- onSubmit,
19
- ...props
20
- }: FormProps<TFieldValues>): _$react_jsx_runtime0.JSX.Element;
21
- /**
22
- * Plain `<form>` element with RHF integration.
23
- *
24
- * Uses a native `<form>` instead of `@base-ui/react/form` because Base UI
25
- * Form's internal submit/validation handling conflicts with React Hook Form
26
- * and blocks button click events inside modal dialogs. Since RHF already
27
- * provides validation, error handling, and submit management, the Base UI
28
- * Form wrapper adds no value at the moment.
29
- */
30
- declare function FormRoot({
31
- className,
32
- ...props
33
- }: FormRootProps): _$react_jsx_runtime0.JSX.Element;
34
10
  type FormFieldRenderArgs<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>> = {
35
11
  id: string;
36
12
  field: ControllerRenderProps<TFieldValues, TName>;
@@ -53,25 +29,30 @@ type FormFieldProps<TFieldValues extends FieldValues, TName extends FieldPath<TF
53
29
  */
54
30
  render: (args: FormFieldRenderArgs<TFieldValues, TName>) => React.ReactNode;
55
31
  } & Omit<React.ComponentProps<typeof Field>, "children" | "name" | "invalid" | "touched" | "dirty" | "render">;
32
+ type FormErrorProps = React.ComponentProps<"p">;
33
+ type FormActionsProps = React.ComponentProps<"div">;
34
+ type FormMessageProps = React.ComponentProps<"p">;
35
+ declare function Form<TFieldValues extends FieldValues>({ form, onSubmit, ...props }: FormProps<TFieldValues>): React.JSX.Element;
36
+ /**
37
+ * Plain `<form>` element with RHF integration.
38
+ *
39
+ * Uses a native `<form>` instead of `@base-ui/react/form` because Base UI
40
+ * Form's internal submit/validation handling conflicts with React Hook Form
41
+ * and blocks button click events inside modal dialogs. Since RHF already
42
+ * provides validation, error handling, and submit management, the Base UI
43
+ * Form wrapper adds no value at the moment.
44
+ */
45
+ declare function FormRoot({ className, ...props }: FormRootProps): React.JSX.Element;
56
46
  /**
57
47
  * Base UI + React Hook Form field helper.
58
48
  *
59
49
  * It maps RHF Controller state onto Base UI's <Field> state so styling can
60
50
  * rely on `data-[invalid]`, `data-[touched]`, `data-[dirty]`, etc.
61
51
  */
62
- declare function FormField<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>(props: FormFieldProps<TFieldValues, TName>): _$react_jsx_runtime0.JSX.Element;
63
- declare function FormError({
64
- className,
65
- ...props
66
- }: FormErrorProps): _$react_jsx_runtime0.JSX.Element | null;
67
- declare function FormActions({
68
- className,
69
- ...props
70
- }: FormActionsProps): _$react_jsx_runtime0.JSX.Element;
71
- declare function FormMessage({
72
- className,
73
- ...props
74
- }: FormMessageProps): _$react_jsx_runtime0.JSX.Element;
52
+ declare function FormField<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>(props: FormFieldProps<TFieldValues, TName>): React.JSX.Element;
53
+ declare function FormError({ className, ...props }: FormErrorProps): React.JSX.Element | null;
54
+ declare function FormActions({ className, ...props }: FormActionsProps): React.JSX.Element;
55
+ declare function FormMessage({ className, ...props }: FormMessageProps): React.JSX.Element;
75
56
  /**
76
57
  * Convenience helper for mapping RHF field props onto either:
77
58
  * - Base UI controls (use `onValueChange`)
@@ -83,15 +64,15 @@ declare function fieldControlProps<TFieldValues extends FieldValues, TName exten
83
64
  invalid?: boolean;
84
65
  native?: boolean;
85
66
  }): {
86
- "aria-describedby": string | undefined;
87
- "aria-invalid": boolean | undefined;
88
- onValueChange?: ((...event: any[]) => void) | undefined;
89
67
  id: string | undefined;
90
68
  name: TName;
91
- ref: _$react_hook_form0.RefCallBack;
69
+ ref: import("react-hook-form").RefCallBack;
92
70
  value: string;
93
- onBlur: _$react_hook_form0.Noop;
71
+ onBlur: import("react-hook-form").Noop;
94
72
  onChange: (...event: any[]) => void;
73
+ onValueChange?: ((...event: any[]) => void) | undefined;
74
+ "aria-describedby": string | undefined;
75
+ "aria-invalid": boolean | undefined;
95
76
  };
96
77
  //#endregion
97
78
  export { Form, FormActions, type FormActionsProps, FormError, type FormErrorProps, FormField, type FormFieldProps, type FormFieldRenderArgs, FormMessage, type FormMessageProps, type FormProps, FormRoot, type FormRootProps, fieldControlProps, useForm, useWatch };
package/dist/form.js CHANGED
@@ -65,16 +65,19 @@ function FormField(props) {
65
65
  children: [
66
66
  label ? /* @__PURE__ */ jsxs(FieldLabel, { children: [label, isRequired ? /* @__PURE__ */ jsx("span", {
67
67
  "aria-hidden": "true",
68
- className: "text-destructive ml-1",
68
+ className: "text-danger ms-1",
69
69
  children: "*"
70
70
  }) : null] }) : null,
71
- description ? /* @__PURE__ */ jsx(FieldDescription, { children: description }) : null,
72
71
  render({
73
72
  id: controlId,
74
73
  field,
75
74
  fieldState
76
75
  }),
77
- fieldState.error ? /* @__PURE__ */ jsx(FieldError, { children: fieldState.error.message }) : null
76
+ fieldState.error ? /* @__PURE__ */ jsx(FieldError, {
77
+ match: true,
78
+ children: fieldState.error.message
79
+ }) : null,
80
+ description ? /* @__PURE__ */ jsx(FieldDescription, { children: description }) : null
78
81
  ]
79
82
  })
80
83
  });
@@ -86,7 +89,7 @@ function FormError({ className, ...props }) {
86
89
  return /* @__PURE__ */ jsx("p", {
87
90
  "data-slot": "form-error",
88
91
  role: "alert",
89
- className: cn("text-destructive rounded-lg border border-destructive/30 bg-destructive/5 p-4 text-sm", className),
92
+ className: cn("text-danger rounded-lg border border-danger/30 bg-danger/5 p-4 text-sm", className),
90
93
  ...props,
91
94
  children: message
92
95
  });
@@ -0,0 +1,25 @@
1
+ import * as React from "react";
2
+ //#region src/glyph-matrix.d.ts
3
+ interface GlyphMatrixProps extends React.ComponentProps<"canvas"> {
4
+ /** Characters picked from at random. */
5
+ glyphs?: string;
6
+ /** Multiplies how fast the field changes. 0 holds it still. */
7
+ speed?: number;
8
+ /**
9
+ * Bright flashes, some typing short runs along a row. Off leaves a calm
10
+ * shimmer: glyphs swapping quietly at their resting brightness.
11
+ */
12
+ glitch?: boolean;
13
+ }
14
+ /**
15
+ * A field of glitching glyphs, for decorative backgrounds (`glitch={false}`
16
+ * for a calm shimmer behind busy content). Styled with
17
+ * classes: `text-*` sets the glyphs' color and size, `font-*` their typeface,
18
+ * and `accent-*` the color of the flares, which alternate with the text color
19
+ * at full strength. A theme switch re-tints the field. `opacity-*` makes it
20
+ * fainter, and `mask-*` fades it toward an edge (`mask-b-from-40%`) or around
21
+ * content on top (`mask-radial-from-transparent mask-radial-to-black`).
22
+ */
23
+ declare function GlyphMatrix({ glyphs, speed, glitch, className, ref, ...props }: GlyphMatrixProps): React.JSX.Element;
24
+ //#endregion
25
+ export { GlyphMatrix, type GlyphMatrixProps };
@@ -0,0 +1,266 @@
1
+ "use client";
2
+ import { cn } from "./lib/utils.js";
3
+ import { mergeRefs } from "./lib/merge-refs.js";
4
+ import { jsx } from "react/jsx-runtime";
5
+ import * as React from "react";
6
+ //#region src/glyph-matrix.tsx
7
+ const DEFAULT_GLYPHS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$&*()-_+=/[]{};:<>.,0123456789";
8
+ /** Space beside each glyph and the row height, in ems. */
9
+ const CELL_GAP = .6;
10
+ const ROW_HEIGHT = 1.55;
11
+ /** Share of cells left blank. */
12
+ const BLANK_SHARE = .1;
13
+ /** Resting opacity range of the other cells. */
14
+ const REST_MIN = .12;
15
+ const REST_RANGE = .38;
16
+ /** Share of the field that quietly swaps its glyph each second. */
17
+ const SWAP_RATE = .2;
18
+ /** Share of the field that flares each second. */
19
+ const FLARE_RATE = .035;
20
+ /** Chance a flare starts a streak: a run that types along its row. */
21
+ const STREAK_CHANCE = .24;
22
+ /** Share of streaks that run long (10–24 cells instead of 2–8). */
23
+ const LONG_STREAK_CHANCE = 1 / 16;
24
+ /** Seconds between a streak's cells. */
25
+ const STREAK_PACE = .028;
26
+ /** Faint background glyphs gain nothing from more than 2 device pixels per px. */
27
+ const MAX_PIXEL_RATIO = 2;
28
+ /** How often the canvas's color and font are re-read, in seconds. */
29
+ const STYLE_CHECK = .25;
30
+ function randomGlyph(pool) {
31
+ return pool[Math.floor(Math.random() * pool.length)] ?? " ";
32
+ }
33
+ function randomRest() {
34
+ return Math.random() < BLANK_SHARE ? 0 : REST_MIN + Math.random() * REST_RANGE;
35
+ }
36
+ function randomFlare() {
37
+ return {
38
+ peak: .45 + Math.random() * .55,
39
+ hold: .04 + Math.random() * .26,
40
+ fade: .45 + Math.random() * .6,
41
+ accent: Math.random() < .5
42
+ };
43
+ }
44
+ /** Cells a streak adds after its first one. */
45
+ function streakLength() {
46
+ return Math.random() < LONG_STREAK_CHANCE ? 9 + Math.floor(Math.random() * 15) : 1 + Math.floor(Math.random() * 7);
47
+ }
48
+ /**
49
+ * A field of glitching glyphs, for decorative backgrounds (`glitch={false}`
50
+ * for a calm shimmer behind busy content). Styled with
51
+ * classes: `text-*` sets the glyphs' color and size, `font-*` their typeface,
52
+ * and `accent-*` the color of the flares, which alternate with the text color
53
+ * at full strength. A theme switch re-tints the field. `opacity-*` makes it
54
+ * fainter, and `mask-*` fades it toward an edge (`mask-b-from-40%`) or around
55
+ * content on top (`mask-radial-from-transparent mask-radial-to-black`).
56
+ */
57
+ function GlyphMatrix({ glyphs = DEFAULT_GLYPHS, speed = 1, glitch = true, className, ref, ...props }) {
58
+ const canvasRef = React.useRef(null);
59
+ const mergedRef = React.useMemo(() => mergeRefs(canvasRef, ref), [ref]);
60
+ React.useEffect(() => {
61
+ const canvas = canvasRef.current;
62
+ const context = canvas?.getContext("2d");
63
+ if (!canvas || !context) return;
64
+ const pool = Array.from(glyphs.length > 0 ? glyphs : DEFAULT_GLYPHS);
65
+ const pace = Number.isFinite(speed) ? Math.max(0, speed) : 1;
66
+ const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
67
+ let color = "";
68
+ let accent = "";
69
+ let font = "";
70
+ let cellWidth = 0;
71
+ let cellHeight = 0;
72
+ let cols = 0;
73
+ let total = 0;
74
+ let cells = [];
75
+ let rests = /* @__PURE__ */ new Float32Array(0);
76
+ let heats = /* @__PURE__ */ new Float32Array(0);
77
+ let flares = [];
78
+ const active = /* @__PURE__ */ new Set();
79
+ const dirty = /* @__PURE__ */ new Set();
80
+ const streaks = [];
81
+ let swapCarry = 0;
82
+ let flareCarry = 0;
83
+ let styleCheck = STYLE_CHECK;
84
+ let visible = true;
85
+ let disposed = false;
86
+ let frame = 0;
87
+ let last = 0;
88
+ const drawCell = (index) => {
89
+ const x = index % cols * cellWidth;
90
+ const y = Math.floor(index / cols) * cellHeight;
91
+ const glyph = cells[index] ?? " ";
92
+ const rest = rests[index] ?? 0;
93
+ const heat = heats[index] ?? 0;
94
+ context.clearRect(x, y, cellWidth, cellHeight);
95
+ if (rest * (1 - heat) > .004) {
96
+ context.fillStyle = color;
97
+ context.globalAlpha = rest * (1 - heat);
98
+ context.fillText(glyph, x + cellWidth / 2, y + cellHeight / 2);
99
+ }
100
+ if (heat > .004) {
101
+ context.fillStyle = flares[index]?.accent ? accent : color;
102
+ context.globalAlpha = heat;
103
+ context.fillText(glyph, x + cellWidth / 2, y + cellHeight / 2);
104
+ }
105
+ };
106
+ const paintAll = () => {
107
+ context.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
108
+ context.font = font;
109
+ context.textAlign = "center";
110
+ context.textBaseline = "middle";
111
+ for (let index = 0; index < total; index++) drawCell(index);
112
+ dirty.clear();
113
+ };
114
+ const build = () => {
115
+ const ratio = Math.min(window.devicePixelRatio || 1, MAX_PIXEL_RATIO);
116
+ const { clientWidth: width, clientHeight: height } = canvas;
117
+ canvas.width = Math.round(width * ratio);
118
+ canvas.height = Math.round(height * ratio);
119
+ context.setTransform(ratio, 0, 0, ratio, 0, 0);
120
+ context.font = font;
121
+ const size = parseFloat(getComputedStyle(canvas).fontSize) || 14;
122
+ let advance = 1;
123
+ for (const glyph of new Set(pool)) advance = Math.max(advance, context.measureText(glyph).width);
124
+ cellWidth = Math.ceil(advance + size * CELL_GAP);
125
+ cellHeight = Math.ceil(size * ROW_HEIGHT);
126
+ cols = Math.ceil(width / cellWidth);
127
+ total = cols * Math.ceil(height / cellHeight);
128
+ cells = Array.from({ length: total }, () => randomGlyph(pool));
129
+ rests = Float32Array.from({ length: total }, randomRest);
130
+ heats = new Float32Array(total);
131
+ flares = [];
132
+ active.clear();
133
+ dirty.clear();
134
+ streaks.length = 0;
135
+ paintAll();
136
+ };
137
+ const syncStyle = () => {
138
+ const computed = getComputedStyle(canvas);
139
+ const nextAccent = computed.accentColor === "auto" ? computed.color : computed.accentColor;
140
+ const nextFont = `${computed.fontWeight} ${computed.fontSize} ${computed.fontFamily}`;
141
+ const colorChanged = computed.color !== color || nextAccent !== accent;
142
+ color = computed.color;
143
+ accent = nextAccent;
144
+ if (nextFont !== font) {
145
+ font = nextFont;
146
+ build();
147
+ if (!document.fonts.check(nextFont)) document.fonts.load(nextFont).then(() => {
148
+ if (!disposed && font === nextFont) build();
149
+ }, () => {});
150
+ } else if (colorChanged) paintAll();
151
+ };
152
+ const ignite = (index, flare) => {
153
+ flares[index] = { ...flare };
154
+ heats[index] = flare.peak;
155
+ active.add(index);
156
+ dirty.add(index);
157
+ };
158
+ const update = (dt) => {
159
+ swapCarry += total * SWAP_RATE * pace * dt;
160
+ for (; swapCarry >= 1; swapCarry--) {
161
+ const index = Math.floor(Math.random() * total);
162
+ if (active.has(index)) continue;
163
+ cells[index] = randomGlyph(pool);
164
+ dirty.add(index);
165
+ }
166
+ if (glitch) flareCarry += total * FLARE_RATE * pace * dt;
167
+ for (; flareCarry >= 1; flareCarry--) {
168
+ const index = Math.floor(Math.random() * total);
169
+ const flare = randomFlare();
170
+ ignite(index, flare);
171
+ if (Math.random() < STREAK_CHANCE) streaks.push({
172
+ index,
173
+ left: streakLength(),
174
+ carry: 0,
175
+ flare
176
+ });
177
+ }
178
+ for (let s = streaks.length - 1; s >= 0; s--) {
179
+ const streak = streaks[s];
180
+ if (!streak) continue;
181
+ streak.carry += dt * pace / STREAK_PACE;
182
+ while (streak.carry >= 1 && streak.left > 0) {
183
+ streak.carry -= 1;
184
+ streak.left -= 1;
185
+ streak.index += 1;
186
+ if (streak.index % cols === 0 || streak.index >= total) {
187
+ streak.left = 0;
188
+ break;
189
+ }
190
+ ignite(streak.index, streak.flare);
191
+ }
192
+ if (streak.left <= 0) streaks.splice(s, 1);
193
+ }
194
+ for (const index of active) {
195
+ const flare = flares[index];
196
+ if (!flare) {
197
+ active.delete(index);
198
+ continue;
199
+ }
200
+ if (flare.hold > 0) flare.hold -= dt;
201
+ else heats[index] = (heats[index] ?? 0) * Math.exp(-dt * 4 / flare.fade);
202
+ const heat = heats[index] ?? 0;
203
+ if (heat < .012 && flare.hold <= 0) {
204
+ heats[index] = 0;
205
+ active.delete(index);
206
+ } else if (Math.random() < heat * dt * 12) cells[index] = randomGlyph(pool);
207
+ dirty.add(index);
208
+ }
209
+ for (const index of dirty) drawCell(index);
210
+ dirty.clear();
211
+ };
212
+ const settle = () => {
213
+ for (const index of active) {
214
+ heats[index] = 0;
215
+ drawCell(index);
216
+ }
217
+ active.clear();
218
+ streaks.length = 0;
219
+ };
220
+ const tick = (time) => {
221
+ frame = requestAnimationFrame(tick);
222
+ const dt = last ? Math.min(.05, (time - last) / 1e3) : 0;
223
+ last = time;
224
+ if (!visible || dt === 0) return;
225
+ styleCheck -= dt;
226
+ if (styleCheck <= 0) {
227
+ styleCheck = STYLE_CHECK;
228
+ syncStyle();
229
+ }
230
+ if (reducedMotion.matches) {
231
+ if (active.size > 0) settle();
232
+ return;
233
+ }
234
+ update(dt);
235
+ };
236
+ const resizeObserver = new ResizeObserver(() => {
237
+ if (font) build();
238
+ else syncStyle();
239
+ });
240
+ resizeObserver.observe(canvas);
241
+ const intersectionObserver = new IntersectionObserver(([entry]) => {
242
+ if (entry) visible = entry.isIntersecting;
243
+ });
244
+ intersectionObserver.observe(canvas);
245
+ frame = requestAnimationFrame(tick);
246
+ return () => {
247
+ disposed = true;
248
+ cancelAnimationFrame(frame);
249
+ resizeObserver.disconnect();
250
+ intersectionObserver.disconnect();
251
+ };
252
+ }, [
253
+ glyphs,
254
+ speed,
255
+ glitch
256
+ ]);
257
+ return /* @__PURE__ */ jsx("canvas", {
258
+ ref: mergedRef,
259
+ "data-slot": "glyph-matrix",
260
+ "aria-hidden": "true",
261
+ className: cn("text-contrast accent-accent font-mono text-sm pointer-events-none block size-full", className),
262
+ ...props
263
+ });
264
+ }
265
+ //#endregion
266
+ export { GlyphMatrix };
@@ -1,12 +1,10 @@
1
- import * as _$react_jsx_runtime0 from "react/jsx-runtime";
2
-
3
1
  //#region src/gradient-reveal-text.d.ts
4
2
  interface GradientRevealTextProps {
5
3
  /** The text to display */
6
4
  text: string;
7
5
  /** Spotlight follow speed in seconds. Default: 0 (instant) */
8
6
  duration?: number;
9
- /** Gradient colors for the reveal effect. Default: rainbow */
7
+ /** Gradient colors for the reveal effect, any CSS color (`var(--wave-teal-400)` too). Default: rainbow */
10
8
  colors?: string[];
11
9
  /** Base stroke opacity when not hovered. Default: 0.3 */
12
10
  baseOpacity?: number;
@@ -18,7 +16,7 @@ interface GradientRevealTextProps {
18
16
  spotlightSize?: number;
19
17
  /** Stroke width in px. Default: auto (1.5% of text height) */
20
18
  strokeWidth?: number;
21
- /** Base stroke color. Default: neutral-200 (light) / neutral-800 (dark) via Tailwind */
19
+ /** Base stroke color. Default: the `contour` token, so it follows the theme */
22
20
  baseColor?: string;
23
21
  className?: string;
24
22
  }
@@ -32,20 +30,9 @@ interface GradientRevealTextProps {
32
30
  * @example
33
31
  * ```tsx
34
32
  * <GradientRevealText text="HELLO" />
35
- * <GradientRevealText text="BRAND" colors={["#ff0000", "#00ff00"]} />
33
+ * <GradientRevealText text="BRAND" colors={["var(--wave-red-400)", "var(--wave-green-400)"]} />
36
34
  * ```
37
35
  */
38
- declare function GradientRevealText({
39
- text,
40
- duration,
41
- colors,
42
- baseOpacity,
43
- hoverOpacity,
44
- fontFamily,
45
- spotlightSize,
46
- strokeWidth: strokeWidthPx,
47
- baseColor,
48
- className
49
- }: GradientRevealTextProps): _$react_jsx_runtime0.JSX.Element;
36
+ declare function GradientRevealText({ text, duration, colors, baseOpacity, hoverOpacity, fontFamily, spotlightSize, strokeWidth: strokeWidthPx, baseColor, className }: GradientRevealTextProps): import("react").JSX.Element;
50
37
  //#endregion
51
38
  export { GradientRevealText, type GradientRevealTextProps };
@@ -4,11 +4,11 @@ import { jsx, jsxs } from "react/jsx-runtime";
4
4
  import { useCallback, useEffect, useId, useRef, useState } from "react";
5
5
  //#region src/gradient-reveal-text.tsx
6
6
  const DEFAULT_COLORS = [
7
- "#eab308",
8
- "#ef4444",
9
- "#3b82f6",
10
- "#06b6d4",
11
- "#8b5cf6"
7
+ "var(--wave-yellow-400)",
8
+ "var(--wave-red-400)",
9
+ "var(--wave-blue-400)",
10
+ "var(--wave-teal-400)",
11
+ "var(--wave-purple-400)"
12
12
  ];
13
13
  /**
14
14
  * Large decorative text with a gradient spotlight that follows the cursor.
@@ -20,7 +20,7 @@ const DEFAULT_COLORS = [
20
20
  * @example
21
21
  * ```tsx
22
22
  * <GradientRevealText text="HELLO" />
23
- * <GradientRevealText text="BRAND" colors={["#ff0000", "#00ff00"]} />
23
+ * <GradientRevealText text="BRAND" colors={["var(--wave-red-400)", "var(--wave-green-400)"]} />
24
24
  * ```
25
25
  */
26
26
  function GradientRevealText({ text, duration = 0, colors = DEFAULT_COLORS, baseOpacity = .3, hoverOpacity = .7, fontFamily = "Helvetica Neue, Helvetica, Arial, sans-serif", spotlightSize = .6, strokeWidth: strokeWidthPx, baseColor, className }) {
@@ -188,7 +188,7 @@ function GradientRevealText({ text, duration = 0, colors = DEFAULT_COLORS, baseO
188
188
  y2: "0%",
189
189
  children: hovered && stops.map((s) => /* @__PURE__ */ jsx("stop", {
190
190
  offset: s.offset,
191
- stopColor: s.color
191
+ style: { stopColor: s.color }
192
192
  }, s.offset))
193
193
  }),
194
194
  /* @__PURE__ */ jsxs("radialGradient", {
@@ -236,7 +236,7 @@ function GradientRevealText({ text, duration = 0, colors = DEFAULT_COLORS, baseO
236
236
  y: "50%",
237
237
  textAnchor: "middle",
238
238
  dominantBaseline: "central",
239
- className: baseColor ? "font-bold" : "font-bold stroke-neutral-200 dark:stroke-neutral-800",
239
+ className: baseColor ? "font-bold" : "font-bold stroke-contour",
240
240
  style: {
241
241
  ...textStyle,
242
242
  ...baseColor ? { stroke: baseColor } : {},
@@ -4,6 +4,5 @@
4
4
  *
5
5
  * @param breakpoint - Width in pixels. Defaults to 768.
6
6
  */
7
- declare function useIsMobile(breakpoint?: number): boolean;
8
- //#endregion
9
- export { useIsMobile };
7
+ export declare function useIsMobile(breakpoint?: number): boolean;
8
+ //#endregion
@@ -1,6 +1,4 @@
1
- import * as _$react_jsx_runtime0 from "react/jsx-runtime";
2
1
  import * as React from "react";
3
-
4
2
  //#region src/infinite-scroll.d.ts
5
3
  type InfiniteScrollProps = React.ComponentProps<"div"> & {
6
4
  onLoadMore: () => void;
@@ -13,19 +11,6 @@ type InfiniteScrollProps = React.ComponentProps<"div"> & {
13
11
  loader?: React.ReactNode;
14
12
  endMessage?: React.ReactNode;
15
13
  };
16
- declare function InfiniteScroll({
17
- onLoadMore,
18
- hasMore,
19
- isLoading,
20
- direction,
21
- root,
22
- rootMargin,
23
- threshold,
24
- loader,
25
- endMessage,
26
- className,
27
- children,
28
- ...props
29
- }: InfiniteScrollProps): _$react_jsx_runtime0.JSX.Element;
14
+ declare function InfiniteScroll({ onLoadMore, hasMore, isLoading, direction, root, rootMargin, threshold, loader, endMessage, className, children, ...props }: InfiniteScrollProps): React.JSX.Element;
30
15
  //#endregion
31
16
  export { InfiniteScroll, type InfiniteScrollProps };
@@ -1,14 +1,11 @@
1
1
  import { Button } from "./button.js";
2
2
  import { Input } from "./input.js";
3
- import * as _$react_jsx_runtime0 from "react/jsx-runtime";
4
3
  import * as React from "react";
5
4
  import { VariantProps } from "class-variance-authority";
6
- import * as _$class_variance_authority_types0 from "class-variance-authority/types";
7
-
8
5
  //#region src/input-group.d.ts
9
6
  declare const inputGroupVariants: (props?: ({
10
- size?: "default" | "sm" | "xs" | "lg" | null | undefined;
11
- } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
7
+ size?: "default" | "lg" | "sm" | "xs" | null | undefined;
8
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
12
9
  type InputGroupProps = React.ComponentProps<"div"> & VariantProps<typeof inputGroupVariants>;
13
10
  type InputGroupAddonProps = React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>;
14
11
  type InputGroupButtonProps = Omit<React.ComponentProps<typeof Button>, "size" | "type"> & VariantProps<typeof inputGroupButtonVariants> & {
@@ -17,40 +14,17 @@ type InputGroupButtonProps = Omit<React.ComponentProps<typeof Button>, "size" |
17
14
  type InputGroupTextProps = React.ComponentProps<"span">;
18
15
  type InputGroupInputProps = React.ComponentProps<typeof Input>;
19
16
  type InputGroupTextareaProps = React.ComponentProps<"textarea">;
20
- declare function InputGroup({
21
- className,
22
- size,
23
- ...props
24
- }: InputGroupProps): _$react_jsx_runtime0.JSX.Element;
17
+ declare function InputGroup({ className, size, ...props }: InputGroupProps): React.JSX.Element;
25
18
  declare const inputGroupAddonVariants: (props?: ({
26
- align?: "inline-start" | "inline-end" | "block-start" | "block-end" | null | undefined;
27
- } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
28
- declare function InputGroupAddon({
29
- className,
30
- align,
31
- ...props
32
- }: InputGroupAddonProps): _$react_jsx_runtime0.JSX.Element;
19
+ align?: "block-end" | "block-start" | "inline-end" | "inline-start" | null | undefined;
20
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
21
+ declare function InputGroupAddon({ className, align, ...props }: InputGroupAddonProps): React.JSX.Element;
33
22
  declare const inputGroupButtonVariants: (props?: ({
34
23
  size?: "default" | "icon" | null | undefined;
35
- } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
36
- declare function InputGroupButton({
37
- className,
38
- type,
39
- variant,
40
- size,
41
- ...props
42
- }: InputGroupButtonProps): _$react_jsx_runtime0.JSX.Element;
43
- declare function InputGroupText({
44
- className,
45
- ...props
46
- }: InputGroupTextProps): _$react_jsx_runtime0.JSX.Element;
47
- declare function InputGroupInput({
48
- className,
49
- ...props
50
- }: InputGroupInputProps): _$react_jsx_runtime0.JSX.Element;
51
- declare function InputGroupTextarea({
52
- className,
53
- ...props
54
- }: InputGroupTextareaProps): _$react_jsx_runtime0.JSX.Element;
24
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
25
+ declare function InputGroupButton({ className, type, variant, size, ...props }: InputGroupButtonProps): React.JSX.Element;
26
+ declare function InputGroupText({ className, ...props }: InputGroupTextProps): React.JSX.Element;
27
+ declare function InputGroupInput({ className, ...props }: InputGroupInputProps): React.JSX.Element;
28
+ declare function InputGroupTextarea({ className, ...props }: InputGroupTextareaProps): React.JSX.Element;
55
29
  //#endregion
56
30
  export { InputGroup, InputGroupAddon, type InputGroupAddonProps, InputGroupButton, type InputGroupButtonProps, InputGroupInput, type InputGroupInputProps, type InputGroupProps, InputGroupText, type InputGroupTextProps, InputGroupTextarea, type InputGroupTextareaProps, inputGroupAddonVariants, inputGroupButtonVariants, inputGroupVariants };
@@ -6,7 +6,7 @@ import { Textarea } from "./textarea.js";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  import { cva } from "class-variance-authority";
8
8
  //#region src/input-group.tsx
9
- const inputGroupVariants = cva("bg-edge hover:border-focus has-[[data-slot=input-group-control]:focus-visible]:border-focus has-[[data-slot=input-group-control]:focus-visible]:ring-focus/50 has-[[data-slot][aria-invalid=true]]:ring-destructive/30 has-[[data-slot][aria-invalid=true]]:border-destructive group/input-group relative flex w-full min-w-0 items-center rounded-md border border-transparent motion-color outline-hidden in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:pointer-events-none has-disabled:opacity-30 not-has-disabled:has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-3 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 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3", {
9
+ const inputGroupVariants = cva("bg-shade hover:border-focus has-[[data-slot=input-group-control]:focus-visible]:border-focus has-[[data-slot=input-group-control]:focus-visible]:ring-focus/50 has-[[data-slot][aria-invalid=true]]:ring-danger/30 has-[[data-slot][aria-invalid=true]]:border-danger group/input-group relative flex w-full min-w-0 items-center rounded-md border border-transparent motion-color outline-hidden in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:pointer-events-none has-disabled:opacity-30 not-has-disabled:has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-3 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 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3", {
10
10
  variants: { size: {
11
11
  xs: "h-6 rounded-sm",
12
12
  sm: "h-8",
@@ -1,33 +1,17 @@
1
- import * as _$react_jsx_runtime0 from "react/jsx-runtime";
2
1
  import * as React from "react";
3
2
  import { OTPInput } from "input-otp";
4
-
5
3
  //#region src/input-otp.d.ts
6
4
  type InputOTPProps = React.ComponentProps<typeof OTPInput> & {
7
5
  containerClassName?: string;
8
6
  };
9
- declare function InputOTP({
10
- className,
11
- containerClassName,
12
- ...props
13
- }: InputOTPProps): _$react_jsx_runtime0.JSX.Element;
14
7
  type InputOTPGroupProps = React.ComponentProps<"div">;
15
- declare function InputOTPGroup({
16
- className,
17
- ...props
18
- }: InputOTPGroupProps): _$react_jsx_runtime0.JSX.Element;
19
8
  type InputOTPSlotProps = React.ComponentProps<"div"> & {
20
9
  index: number;
21
10
  };
22
- declare function InputOTPSlot({
23
- index,
24
- className,
25
- ...props
26
- }: InputOTPSlotProps): _$react_jsx_runtime0.JSX.Element;
27
11
  type InputOTPSeparatorProps = React.ComponentProps<"div">;
28
- declare function InputOTPSeparator({
29
- className,
30
- ...props
31
- }: InputOTPSeparatorProps): _$react_jsx_runtime0.JSX.Element;
12
+ declare function InputOTP({ className, containerClassName, ...props }: InputOTPProps): React.JSX.Element;
13
+ declare function InputOTPGroup({ className, ...props }: InputOTPGroupProps): React.JSX.Element;
14
+ declare function InputOTPSlot({ index, className, ...props }: InputOTPSlotProps): React.JSX.Element;
15
+ declare function InputOTPSeparator({ className, ...props }: InputOTPSeparatorProps): React.JSX.Element;
32
16
  //#endregion
33
17
  export { InputOTP, InputOTPGroup, type InputOTPGroupProps, type InputOTPProps, InputOTPSeparator, type InputOTPSeparatorProps, InputOTPSlot, type InputOTPSlotProps };