@viraui/react 0.0.20 → 0.0.22

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 (58) hide show
  1. package/dist/catalog.json +13 -1
  2. package/dist/components/avatar/avatar.js +1 -1
  3. package/dist/components/avatar-group/avatar-group.js +3 -2
  4. package/dist/components/basic-input/basic-input.js +1 -1
  5. package/dist/components/basic-input/field-label.js +1 -1
  6. package/dist/components/button/button.js +1 -1
  7. package/dist/components/checkbox/checkbox.js +1 -1
  8. package/dist/components/chip/chip.js +1 -1
  9. package/dist/components/clamp-text/clamp-text.js +1 -1
  10. package/dist/components/icon/icon.js +1 -1
  11. package/dist/components/index.d.ts +2 -0
  12. package/dist/components/linear-progress/linear-progress.js +1 -1
  13. package/dist/components/masonry/masonry-item.js +1 -1
  14. package/dist/components/masonry/masonry.js +1 -1
  15. package/dist/components/progressive-blur/index.d.ts +2 -0
  16. package/dist/components/progressive-blur/progressive-blur.css +1 -0
  17. package/dist/components/progressive-blur/progressive-blur.d.ts +38 -0
  18. package/dist/components/progressive-blur/progressive-blur.guide.json +25 -0
  19. package/dist/components/progressive-blur/progressive-blur.js +39 -0
  20. package/dist/components/progressive-blur/progressive-blur.module.js +6 -0
  21. package/dist/components/progressive-blur/progressive-blur.utils.d.ts +14 -0
  22. package/dist/components/progressive-blur/progressive-blur.utils.js +40 -0
  23. package/dist/components/radio/radio.js +1 -1
  24. package/dist/components/select/select-group.js +1 -1
  25. package/dist/components/select/select-option.d.ts +7 -1
  26. package/dist/components/select/select-option.js +19 -7
  27. package/dist/components/select/select-separator.js +1 -1
  28. package/dist/components/select/select.css +1 -1
  29. package/dist/components/select/select.d.ts +7 -1
  30. package/dist/components/select/select.guide.json +1 -0
  31. package/dist/components/select/select.js +3 -3
  32. package/dist/components/select/select.module.js +1 -0
  33. package/dist/components/skeleton/skeleton.js +2 -2
  34. package/dist/components/slider/slider.js +1 -1
  35. package/dist/components/spinner/spinner.js +2 -2
  36. package/dist/components/stack/stack.js +1 -1
  37. package/dist/components/static-noise/index.d.ts +2 -0
  38. package/dist/components/static-noise/static-noise.css +1 -0
  39. package/dist/components/static-noise/static-noise.d.ts +37 -0
  40. package/dist/components/static-noise/static-noise.guide.json +25 -0
  41. package/dist/components/static-noise/static-noise.js +45 -0
  42. package/dist/components/static-noise/static-noise.module.js +6 -0
  43. package/dist/components/surface/surface-radius-context.d.ts +37 -0
  44. package/dist/components/surface/surface-radius-context.js +70 -0
  45. package/dist/components/surface/surface.css +1 -1
  46. package/dist/components/surface/surface.d.ts +5 -5
  47. package/dist/components/surface/surface.guide.json +10 -4
  48. package/dist/components/surface/surface.js +23 -4
  49. package/dist/components/switch/switch.js +1 -1
  50. package/dist/components/text/text.js +1 -1
  51. package/dist/components/textarea/textarea.js +1 -1
  52. package/dist/components/textfield/textfield.js +1 -1
  53. package/dist/components/title/title.js +1 -1
  54. package/dist/core/clsx.d.ts +1 -0
  55. package/dist/core/clsx.js +36 -0
  56. package/dist/index.js +3 -1
  57. package/dist/preflight.css +1 -1
  58. package/package.json +4 -7
package/dist/catalog.json CHANGED
@@ -119,7 +119,7 @@
119
119
  {
120
120
  "id": "surface",
121
121
  "name": "Surface",
122
- "summary": "Presentational container with token background, optional border, radius, and padding.",
122
+ "summary": "Presentational container with token background, optional border, radius, and padding; nested surfaces use radius=\"auto\" for concentric corners.",
123
123
  "guidePath": "./components/surface/surface.guide.json"
124
124
  },
125
125
  {
@@ -128,6 +128,18 @@
128
128
  "summary": "Decorative SVG pulsing loading indicator used inside interactive components.",
129
129
  "guidePath": "./components/spinner/spinner.guide.json"
130
130
  },
131
+ {
132
+ "id": "static-noise",
133
+ "name": "StaticNoise",
134
+ "summary": "Decorative SVG turbulence noise overlay for textured surfaces and hero sections.",
135
+ "guidePath": "./components/static-noise/static-noise.guide.json"
136
+ },
137
+ {
138
+ "id": "progressive-blur",
139
+ "name": "ProgressiveBlur",
140
+ "summary": "Decorative stacked backdrop-filter overlay that ramps blur from one edge toward the opposite edge.",
141
+ "guidePath": "./components/progressive-blur/progressive-blur.guide.json"
142
+ },
131
143
  {
132
144
  "id": "text",
133
145
  "name": "Text",
@@ -1,10 +1,10 @@
1
1
  import './avatar.css';
2
+ import { clsx } from "../../core/clsx.js";
2
3
  import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
3
4
  import avatar_module_default from "./avatar.module.js";
4
5
  import { Text } from "../text/text.js";
5
6
  import { Skeleton } from "../skeleton/skeleton.js";
6
7
  import { Avatar } from "@base-ui/react/avatar";
7
- import { clsx } from "clsx";
8
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
9
  //#region src/components/avatar/avatar.tsx
10
10
  var fallbackTextSizeByAvatarSize = {
@@ -1,4 +1,5 @@
1
1
  import './avatar-group.css';
2
+ import { clsx } from "../../core/clsx.js";
2
3
  import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
3
4
  import { Avatar } from "../avatar/avatar.js";
4
5
  import { resolveThemeValue } from "../../core/theme/resolve-theme-value.js";
@@ -6,11 +7,10 @@ import avatar_group_module_default from "./avatar-group.module.js";
6
7
  import { Stack } from "../stack/stack.js";
7
8
  import { Text } from "../text/text.js";
8
9
  import { Surface } from "../surface/surface.js";
9
- import { clsx } from "clsx";
10
10
  import { jsx, jsxs } from "react/jsx-runtime";
11
11
  //#region src/components/avatar-group/avatar-group.tsx
12
12
  var getAvatarKey = (avatar, index) => `${avatar.src ?? "fallback"}-${typeof avatar.fallback === "string" ? avatar.fallback : "node"}-${index}`;
13
- var AvatarGroup = ({ avatars, className, direction = "horizontal", gap = "x-small", maxVisible, overflowText, size = "small", style, ...otherProps }) => {
13
+ var AvatarGroup = ({ avatars, className, direction = "horizontal", gap = "x-small", maxVisible, overflowText, ref, size = "small", style, ...otherProps }) => {
14
14
  const { componentProps, intrinsicAttributes } = extractIntrinsicViraProps(otherProps);
15
15
  const isOverflowing = typeof maxVisible === "number" && maxVisible > 0 && avatars.length > maxVisible;
16
16
  const hasOverflow = isOverflowing && overflowText !== void 0 && overflowText !== null;
@@ -22,6 +22,7 @@ var AvatarGroup = ({ avatars, className, direction = "horizontal", gap = "x-smal
22
22
  return /* @__PURE__ */ jsxs("div", {
23
23
  ...componentProps,
24
24
  ...intrinsicAttributes,
25
+ ref,
25
26
  className: clsx(avatar_group_module_default.AvatarGroup, className),
26
27
  "data-direction": direction,
27
28
  "data-gap": gap,
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import './basic-input.css';
3
+ import { clsx } from "../../core/clsx.js";
3
4
  import basic_input_module_default from "./basic-input.module.js";
4
- import { clsx } from "clsx";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  import * as React from "react";
7
7
  import { Field } from "@base-ui/react/field";
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import './field-label.css';
3
+ import { clsx } from "../../core/clsx.js";
3
4
  import { Text } from "../text/text.js";
4
5
  import field_label_module_default from "./field-label.module.js";
5
- import { clsx } from "clsx";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  //#region src/components/basic-input/field-label.tsx
8
8
  /**
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  import './button.css';
3
+ import { clsx } from "../../core/clsx.js";
3
4
  import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
4
5
  import { Spinner } from "../spinner/spinner.js";
5
6
  import button_module_default from "./button.module.js";
6
- import { clsx } from "clsx";
7
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
8
  import { useRender } from "@base-ui/react/use-render";
9
9
  import * as React from "react";
@@ -1,12 +1,12 @@
1
1
  "use client";
2
2
  import './checkbox.css';
3
+ import { clsx } from "../../core/clsx.js";
3
4
  import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
4
5
  import { Stack } from "../stack/stack.js";
5
6
  import { FieldHelperCopy } from "../basic-input/field-helper-copy.js";
6
7
  import { FieldLabel } from "../basic-input/field-label.js";
7
8
  import checkbox_module_default from "./checkbox.module.js";
8
9
  import { Icon } from "../icon/icon.js";
9
- import { clsx } from "clsx";
10
10
  import { jsx, jsxs } from "react/jsx-runtime";
11
11
  import { Checkbox, Field } from "@base-ui/react";
12
12
  //#region src/components/checkbox/checkbox.tsx
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  import './chip.css';
3
+ import { clsx } from "../../core/clsx.js";
3
4
  import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
4
5
  import { Stack } from "../stack/stack.js";
5
6
  import chip_module_default from "./chip.module.js";
6
- import { clsx } from "clsx";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
8
  import { useRender } from "@base-ui/react/use-render";
9
9
  import "react";
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import './clamp-text.css';
3
+ import { clsx } from "../../core/clsx.js";
3
4
  import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
4
5
  import clamp_text_module_default from "./clamp-text.module.js";
5
- import { clsx } from "clsx";
6
6
  import { useRender } from "@base-ui/react/use-render";
7
7
  import { useMemo } from "react";
8
8
  //#region src/components/clamp-text/clamp-text.tsx
@@ -1,7 +1,7 @@
1
1
  import './icon.css';
2
+ import { clsx } from "../../core/clsx.js";
2
3
  import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
3
4
  import icon_module_default from "./icon.module.js";
4
- import { clsx } from "clsx";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  import { generatedDefaultIconVariant, generatedIconRegistry } from "#internal-icons/icon-registry";
7
7
  //#region src/components/icon/icon.tsx
@@ -19,5 +19,7 @@ export * from './skeleton';
19
19
  export * from './stack';
20
20
  export * from './surface';
21
21
  export * from './spinner';
22
+ export * from './static-noise';
23
+ export * from './progressive-blur';
22
24
  export * from './text';
23
25
  export * from './title';
@@ -1,11 +1,11 @@
1
1
  "use client";
2
2
  import './linear-progress.css';
3
+ import { clsx } from "../../core/clsx.js";
3
4
  import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
4
5
  import { Stack } from "../stack/stack.js";
5
6
  import { Text } from "../text/text.js";
6
7
  import { FieldLabel } from "../basic-input/field-label.js";
7
8
  import linear_progress_module_default from "./linear-progress.module.js";
8
- import { clsx } from "clsx";
9
9
  import { jsx, jsxs } from "react/jsx-runtime";
10
10
  import { Progress } from "@base-ui/react/progress";
11
11
  //#region src/components/linear-progress/linear-progress.tsx
@@ -1,7 +1,7 @@
1
1
  "use client";
2
+ import { clsx } from "../../core/clsx.js";
2
3
  import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
3
4
  import masonry_module_default from "./masonry.module.js";
4
- import { clsx } from "clsx";
5
5
  import { useRender } from "@base-ui/react/use-render";
6
6
  //#region src/components/masonry/masonry-item.tsx
7
7
  var MasonryItem = ({ className, ref, render, spanAll = false, ...otherProps }) => {
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import './masonry.css';
3
+ import { clsx } from "../../core/clsx.js";
3
4
  import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
4
5
  import { resolveThemeValue } from "../../core/theme/resolve-theme-value.js";
5
6
  import masonry_module_default from "./masonry.module.js";
6
7
  import { MasonryItem } from "./masonry-item.js";
7
- import { clsx } from "clsx";
8
8
  import { useRender } from "@base-ui/react/use-render";
9
9
  //#region src/components/masonry/masonry.tsx
10
10
  var MasonryRoot = ({ children, className, columnCount = 4, columnFill = "balance", columnRuleStyle, columnRuleWidth, columnWidth, gap = "large", ref, render, style, ...otherProps }) => {
@@ -0,0 +1,2 @@
1
+ export { ProgressiveBlur } from './progressive-blur';
2
+ export type { ProgressiveBlurProps } from './progressive-blur';
@@ -0,0 +1 @@
1
+ .progressive-blur-module_ProgressiveBlur_eIxTK{--progressive-blur:16px;pointer-events:none}.progressive-blur-module_Layer_zbzMS{position:absolute;inset:0;backdrop-filter:blur(calc(var(--progressive-blur) * var(--progressive-blur-factor)));mask-image:var(--progressive-blur-mask-image);.progressive-blur-module_ProgressiveBlur_eIxTK[data-direction=top] &{--progressive-blur-mask-image:linear-gradient(to top,var(--progressive-blur-mask-gradient))}.progressive-blur-module_ProgressiveBlur_eIxTK[data-direction=right] &{--progressive-blur-mask-image:linear-gradient(to right,var(--progressive-blur-mask-gradient))}.progressive-blur-module_ProgressiveBlur_eIxTK[data-direction=bottom] &{--progressive-blur-mask-image:linear-gradient(to bottom,var(--progressive-blur-mask-gradient))}.progressive-blur-module_ProgressiveBlur_eIxTK[data-direction=left] &{--progressive-blur-mask-image:linear-gradient(to left,var(--progressive-blur-mask-gradient))}}
@@ -0,0 +1,38 @@
1
+ import { IntrinsicViraProps } from '../../core/props/intrinsic-vira-props';
2
+ import { ProgressiveBlurDirection, ProgressiveBlurEasing } from './progressive-blur.utils';
3
+ import type * as React from 'react';
4
+ /**
5
+ * Public ProgressiveBlur props.
6
+ *
7
+ * Includes standard `div` attributes such as `id`, `className`, and event handlers,
8
+ * plus Vira-owned progressive backdrop blur controls.
9
+ *
10
+ * @default Native div pass-through props keep React defaults.
11
+ */
12
+ export type ProgressiveBlurProps = React.ComponentPropsWithRef<'div'> & IntrinsicViraProps & {
13
+ /**
14
+ * Sets the maximum blur radius applied to the first layer at the selected edge.
15
+ *
16
+ * @default '16px'
17
+ */
18
+ blur?: string;
19
+ /**
20
+ * Selects the edge where maximum blur starts and fades toward the opposite edge.
21
+ *
22
+ * @default 'bottom'
23
+ */
24
+ direction?: ProgressiveBlurDirection;
25
+ /**
26
+ * Selects the easing curve used to distribute blur factors across internal layers.
27
+ *
28
+ * @default 'exponential'
29
+ */
30
+ easing?: ProgressiveBlurEasing;
31
+ /**
32
+ * Sets the number of internal blur layers. Values are clamped to `2..16`.
33
+ *
34
+ * @default Varies by easing: linear `6`, ease-in/out `8`, ease-in-out `10`, exponential `8`.
35
+ */
36
+ steps?: number;
37
+ };
38
+ export declare const ProgressiveBlur: React.FC<ProgressiveBlurProps>;
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "ProgressiveBlur",
3
+ "summary": "Decorative stacked backdrop-filter overlay that ramps blur from one edge toward the opposite edge.",
4
+ "whenToUse": [
5
+ "Edge scrims on cards, sheets, heroes, or scroll regions where content should fade into blur",
6
+ "Glass or vibrant surfaces that need directional legibility without a hard blur cutoff",
7
+ "Decorative atmosphere where the parent owns semantics and layout positioning"
8
+ ],
9
+ "whenNotToUse": [
10
+ "Standalone loading or status feedback without a labeled parent region",
11
+ "Large full-viewport stacks with many simultaneous high-radius blur layers",
12
+ "Cases where a single uniform backdrop blur is sufficient"
13
+ ],
14
+ "accessibility": [
15
+ "ProgressiveBlur is decorative — the root renders with aria-hidden by default",
16
+ "Parent surface or region must expose any meaningful label or busy state",
17
+ "Consumer owns position, inset, z-index, and sizing for the overlay placement"
18
+ ],
19
+ "antiPatterns": [
20
+ "Stacking many full-viewport ProgressiveBlur instances on one screen",
21
+ "Driving layout size or scroll behavior from inside the overlay component",
22
+ "Embedding layout positioning rules inside the component stylesheet"
23
+ ],
24
+ "related": ["Surface", "StaticNoise"]
25
+ }
@@ -0,0 +1,39 @@
1
+ import './progressive-blur.css';
2
+ import { clsx } from "../../core/clsx.js";
3
+ import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
4
+ import progressive_blur_module_default from "./progressive-blur.module.js";
5
+ import { formatProgressiveBlurMaskGradient, getProgressiveBlurFactor, getProgressiveBlurMaskStops, resolveProgressiveBlurSteps } from "./progressive-blur.utils.js";
6
+ import { jsx } from "react/jsx-runtime";
7
+ //#region src/components/progressive-blur/progressive-blur.tsx
8
+ var ProgressiveBlur = ({ blur = "16px", className, direction = "bottom", easing = "exponential", ref, steps, style, ...otherProps }) => {
9
+ const { componentProps, intrinsicAttributes } = extractIntrinsicViraProps(otherProps);
10
+ const resolvedSteps = resolveProgressiveBlurSteps(steps, easing);
11
+ const dynamicStyle = {
12
+ "--progressive-blur": blur,
13
+ ...style
14
+ };
15
+ const layers = Array.from({ length: resolvedSteps }, (_, layerIndex) => {
16
+ const factor = getProgressiveBlurFactor(easing, layerIndex, resolvedSteps);
17
+ const maskGradient = formatProgressiveBlurMaskGradient(getProgressiveBlurMaskStops(layerIndex, resolvedSteps));
18
+ return /* @__PURE__ */ jsx("span", {
19
+ "aria-hidden": "true",
20
+ className: progressive_blur_module_default.Layer,
21
+ style: {
22
+ "--progressive-blur-factor": factor,
23
+ "--progressive-blur-mask-gradient": maskGradient
24
+ }
25
+ }, layerIndex);
26
+ });
27
+ return /* @__PURE__ */ jsx("div", {
28
+ ...componentProps,
29
+ ...intrinsicAttributes,
30
+ ref,
31
+ "aria-hidden": "true",
32
+ className: clsx(progressive_blur_module_default.ProgressiveBlur, className),
33
+ "data-direction": direction,
34
+ style: dynamicStyle,
35
+ children: layers
36
+ });
37
+ };
38
+ //#endregion
39
+ export { ProgressiveBlur };
@@ -0,0 +1,6 @@
1
+ var progressive_blur_module_default = {
2
+ ProgressiveBlur: "progressive-blur-module_ProgressiveBlur_eIxTK",
3
+ Layer: "progressive-blur-module_Layer_zbzMS"
4
+ };
5
+ //#endregion
6
+ export { progressive_blur_module_default as default };
@@ -0,0 +1,14 @@
1
+ export type ProgressiveBlurDirection = 'top' | 'right' | 'bottom' | 'left';
2
+ export type ProgressiveBlurEasing = 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'exponential';
3
+ export declare const PROGRESSIVE_BLUR_MIN_STEPS = 2;
4
+ export declare const PROGRESSIVE_BLUR_MAX_STEPS = 16;
5
+ export declare const resolveProgressiveBlurSteps: (steps: number | undefined, easing: ProgressiveBlurEasing) => number;
6
+ export declare const getProgressiveBlurFactor: (easing: ProgressiveBlurEasing, layerIndex: number, totalSteps: number) => number;
7
+ export type ProgressiveBlurMaskStops = {
8
+ p1: number;
9
+ p2: number;
10
+ p3: number;
11
+ p4: number;
12
+ };
13
+ export declare const getProgressiveBlurMaskStops: (layerIndex: number, totalSteps: number) => ProgressiveBlurMaskStops;
14
+ export declare const formatProgressiveBlurMaskGradient: (stops: ProgressiveBlurMaskStops) => string;
@@ -0,0 +1,40 @@
1
+ var DEFAULT_STEPS_BY_EASING = {
2
+ linear: 6,
3
+ "ease-in": 8,
4
+ "ease-out": 8,
5
+ "ease-in-out": 10,
6
+ exponential: 8
7
+ };
8
+ var resolveProgressiveBlurSteps = (steps, easing) => {
9
+ const resolved = steps ?? DEFAULT_STEPS_BY_EASING[easing];
10
+ return Math.min(16, Math.max(2, resolved));
11
+ };
12
+ var getProgressiveBlurFactor = (easing, layerIndex, totalSteps) => {
13
+ if (easing === "exponential") return .5 ** layerIndex;
14
+ const progress = layerIndex / (totalSteps - 1);
15
+ switch (easing) {
16
+ case "linear": return 1 - progress;
17
+ case "ease-in": return 1 - progress * progress;
18
+ case "ease-out": return 1 - (1 - (1 - progress) ** 2);
19
+ case "ease-in-out": return 1 - (progress < .5 ? 2 * progress * progress : 1 - (-2 * progress + 2) ** 2 / 2);
20
+ default: return 1 - progress;
21
+ }
22
+ };
23
+ var getProgressiveBlurMaskStops = (layerIndex, totalSteps) => {
24
+ const increment = 100 / totalSteps;
25
+ const maskIndex = totalSteps - layerIndex;
26
+ return {
27
+ p1: Math.round((increment * maskIndex - increment) * 10) / 10,
28
+ p2: Math.round(increment * maskIndex * 10) / 10,
29
+ p3: Math.round((increment * maskIndex + increment) * 10) / 10,
30
+ p4: Math.round((increment * maskIndex + increment * 2) * 10) / 10
31
+ };
32
+ };
33
+ var formatProgressiveBlurMaskGradient = (stops) => {
34
+ let gradient = `transparent ${stops.p1}%, black ${stops.p2}%`;
35
+ if (stops.p3 <= 100) gradient += `, black ${stops.p3}%`;
36
+ if (stops.p4 <= 100) gradient += `, transparent ${stops.p4}%`;
37
+ return gradient;
38
+ };
39
+ //#endregion
40
+ export { formatProgressiveBlurMaskGradient, getProgressiveBlurFactor, getProgressiveBlurMaskStops, resolveProgressiveBlurSteps };
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import './radio.css';
3
+ import { clsx } from "../../core/clsx.js";
3
4
  import { Stack } from "../stack/stack.js";
4
5
  import { FieldHelperCopy } from "../basic-input/field-helper-copy.js";
5
6
  import { FieldLabel } from "../basic-input/field-label.js";
6
7
  import radio_module_default from "./radio.module.js";
7
- import { clsx } from "clsx";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
9
  import { Field } from "@base-ui/react/field";
10
10
  import { Radio } from "@base-ui/react/radio";
@@ -1,9 +1,9 @@
1
1
  "use client";
2
+ import { clsx } from "../../core/clsx.js";
2
3
  import { Stack } from "../stack/stack.js";
3
4
  import { Text } from "../text/text.js";
4
5
  import select_module_default from "./select.module.js";
5
6
  import { SelectIndicatorSlot } from "./select-indicator-slot.js";
6
- import { clsx } from "clsx";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
8
  import { Select } from "@base-ui/react/select";
9
9
  //#region src/components/select/select-group.tsx
@@ -6,6 +6,12 @@ import type * as React from 'react';
6
6
  * @default Base UI pass-through props keep upstream defaults.
7
7
  */
8
8
  export type SelectOptionProps = SelectItem.Props & {
9
+ /**
10
+ * Decorative leading node rendered before the option label.
11
+ *
12
+ * @default No addon is rendered.
13
+ */
14
+ addon?: React.ReactNode;
9
15
  /**
10
16
  * Custom indicator node rendered when the option is selected.
11
17
  *
@@ -13,4 +19,4 @@ export type SelectOptionProps = SelectItem.Props & {
13
19
  */
14
20
  indicator?: React.ReactNode;
15
21
  };
16
- export declare function SelectOption({ children, className, disabled, indicator, label, value, ...itemProps }: SelectOptionProps): React.JSX.Element;
22
+ export declare function SelectOption({ addon, children, className, disabled, indicator, label, value, ...itemProps }: SelectOptionProps): React.JSX.Element;
@@ -1,14 +1,14 @@
1
1
  "use client";
2
+ import { clsx } from "../../core/clsx.js";
2
3
  import { Stack } from "../stack/stack.js";
3
4
  import { Text } from "../text/text.js";
4
5
  import select_module_default from "./select.module.js";
5
6
  import { SelectIndicatorSlot } from "./select-indicator-slot.js";
6
7
  import { Icon } from "../icon/icon.js";
7
- import { clsx } from "clsx";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
9
  import { Select } from "@base-ui/react/select";
10
10
  //#region src/components/select/select-option.tsx
11
- function SelectOption({ children, className, disabled, indicator, label, value, ...itemProps }) {
11
+ function SelectOption({ addon, children, className, disabled, indicator, label, value, ...itemProps }) {
12
12
  return /* @__PURE__ */ jsxs(Select.Item, {
13
13
  ...itemProps,
14
14
  "aria-label": label,
@@ -23,11 +23,23 @@ function SelectOption({ children, className, disabled, indicator, label, value,
23
23
  vAlign: "center"
24
24
  }),
25
25
  value,
26
- children: [/* @__PURE__ */ jsx(Text, {
27
- lineHeight: "small",
28
- render: /* @__PURE__ */ jsx(Select.ItemText, {}),
29
- size: "small",
30
- children
26
+ children: [/* @__PURE__ */ jsxs(Stack, {
27
+ direction: "row",
28
+ columnGap: "small",
29
+ vAlign: "start",
30
+ children: [addon && /* @__PURE__ */ jsx(Stack, {
31
+ vPadding: "2x-small",
32
+ "aria-hidden": "true",
33
+ grow: false,
34
+ shrink: false,
35
+ children: addon
36
+ }), /* @__PURE__ */ jsx(Text, {
37
+ className: select_module_default.OptionText,
38
+ lineHeight: "small",
39
+ render: /* @__PURE__ */ jsx(Select.ItemText, {}),
40
+ size: "small",
41
+ children
42
+ })]
31
43
  }), /* @__PURE__ */ jsx(SelectIndicatorSlot, {
32
44
  interactive: true,
33
45
  children: indicator ?? /* @__PURE__ */ jsx(Icon, {
@@ -1,6 +1,6 @@
1
1
  "use client";
2
+ import { clsx } from "../../core/clsx.js";
2
3
  import select_module_default from "./select.module.js";
3
- import { clsx } from "clsx";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  import { Select } from "@base-ui/react/select";
6
6
  //#region src/components/select/select-separator.tsx
@@ -1 +1 @@
1
- .select-module_Select_eXv4Y{--input-height:var(--space-x-large);--control-group-background:var(--base-1);--control-group-color:var(--global-foreground);--control-group-border-color:var(--global-contrast);--control-group-border-radius:var(--radius-small);--select-trigger-padding-inline-start:var(--space-small);--select-trigger-padding-inline-end:var(--space-x-small);--field-label-padding-inline:calc((var(--control-group-border-radius) + 0px) / 2);z-index:0;&:has([required]) [data-field-label]:after{content:" *";color:var(--highlight-red)}&[data-invalid]>.select-module_Trigger_-wBsg:not(:disabled):not([data-disabled]){--control-group-border-color:var(--highlight-red);box-shadow:none;outline-color:oklab(from var(--highlight-red) l a b/.5)}}.select-module_Trigger_-wBsg{box-sizing:border-box;inline-size:100%;min-inline-size:0;block-size:var(--input-height);padding-inline:calc(var(--select-trigger-padding-inline-start) + ((var(--control-group-border-radius) + 0px) / 4)) var(--select-trigger-padding-inline-end);border:1px solid var(--control-group-border-color);border-radius:var(--control-group-border-radius);background:var(--control-group-background);color:var(--control-group-color);font:inherit;text-align:start;cursor:pointer;&:focus-visible{outline:2px solid var(--global-foreground);outline-offset:2px}&[data-popup-open]{outline:none}&:disabled,&[data-disabled]{--control-group-background:var(--global-disabled-background);--control-group-border-color:transparent;--control-group-color:var(--global-disabled-foreground);box-shadow:none;cursor:not-allowed}}.select-module_Value_uWHPX{--text-fluid-factor:0;--text-font-size:var(--font-scale-body-small);flex:1 1 auto;min-inline-size:0;overflow:hidden;display:block;text-overflow:ellipsis;&[data-placeholder]{color:var(--global-disabled-foreground)}}.select-module_Icon_EOwki{font-size:var(--font-scale-body-small);pointer-events:none}.select-module_Description_OmwmV{padding-inline:calc((var(--control-group-border-radius) + 0px) / 2)}.select-module_SelectPopup_UzGXL{--select-list-border-radius:var(--radius-medium);--select-list-padding:var(--space-x-small);box-sizing:border-box;min-inline-size:var(--anchor-width);overflow:visible;color:var(--global-foreground);outline:none;position:relative}.select-module_ScrollArrow_kHlEi{--scroll-arrow-background:var(--is-vibrancy-active) oklab(from var(--base-1) l a b/80%);position:absolute;inset-inline:0;z-index:1;inline-size:100%;block-size:var(--space-large);cursor:default;background:var(--scroll-arrow-background,var(--base-1));backdrop-filter:var(--vibrancy-filter,none);border:1px solid var(--global-contrast)}.select-module_ScrollButton_sHBOa{pointer-events:none}.select-module_ScrollArrowUp_DGXS-{inset-block-start:0;border-radius:var(--select-list-border-radius) var(--select-list-border-radius) 0 0}.select-module_ScrollArrowDown_vhJy0{inset-block-end:0;border-radius:0 0 var(--select-list-border-radius) var(--select-list-border-radius)}.select-module_List_jdUWx{box-sizing:border-box;inline-size:100%;max-block-size:var(--available-height);overflow-y:auto;scroll-padding-block:var(--select-list-padding);list-style:none;overscroll-behavior:contain;&:focus,&:focus-visible{outline:none}}.select-module_Option_KgYqz{border-radius:calc((var(--select-list-border-radius) + 0px) - var(--select-list-padding));cursor:pointer;&:focus{outline:none}&:focus-visible{outline:2px solid var(--global-foreground);outline-offset:0}&:not([data-disabled]):hover,&:not([data-disabled])[data-highlighted]{--option-hover-background:var(--is-vibrancy-active) oklab(from var(--global-contrast) l a b/14%);background:var(--option-hover-background,var(--global-contrast))}&[data-disabled]{color:var(--global-disabled-foreground);cursor:not-allowed}}.select-module_Indicator_YNUuz{inline-size:var(--space-medium);color:var(--global-primary);opacity:0;transition:opacity var(--duration-fast) var(--easing-standard),transform var(--duration-fast) var(--easing-standard);&[data-selected]{opacity:1}}.select-module_Group_xzkuA+.select-module_Group_xzkuA{margin-block-start:var(--space-medium)}.select-module_Separator_Q-ri9{block-size:1px;margin-block:var(--space-small);margin-inline:var(--space-small);background:var(--base-3)}
1
+ .select-module_Select_eXv4Y{--input-height:var(--space-x-large);--control-group-background:var(--base-1);--control-group-color:var(--global-foreground);--control-group-border-color:var(--global-contrast);--control-group-border-radius:var(--radius-small);--select-trigger-padding-inline-start:var(--space-small);--select-trigger-padding-inline-end:var(--space-x-small);--field-label-padding-inline:calc((var(--control-group-border-radius) + 0px) / 2);z-index:0;&:has([required]) [data-field-label]:after{content:" *";color:var(--highlight-red)}&[data-invalid]>.select-module_Trigger_-wBsg:not(:disabled):not([data-disabled]){--control-group-border-color:var(--highlight-red);box-shadow:none;outline-color:oklab(from var(--highlight-red) l a b/.5)}}.select-module_Trigger_-wBsg{box-sizing:border-box;inline-size:100%;min-inline-size:0;block-size:var(--input-height);padding-inline:calc(var(--select-trigger-padding-inline-start) + ((var(--control-group-border-radius) + 0px) / 4)) var(--select-trigger-padding-inline-end);border:1px solid var(--control-group-border-color);border-radius:var(--control-group-border-radius);background:var(--control-group-background);color:var(--control-group-color);font:inherit;text-align:start;cursor:pointer;&:focus-visible{outline:2px solid var(--global-foreground);outline-offset:2px}&[data-popup-open]{outline:none}&:disabled,&[data-disabled]{--control-group-background:var(--global-disabled-background);--control-group-border-color:transparent;--control-group-color:var(--global-disabled-foreground);box-shadow:none;cursor:not-allowed}}.select-module_Value_uWHPX{--text-fluid-factor:0;--text-font-size:var(--font-scale-body-small);flex:1 1 auto;min-inline-size:0;overflow:hidden;display:block;text-overflow:ellipsis;&[data-placeholder]{color:var(--global-disabled-foreground)}}.select-module_Icon_EOwki{font-size:var(--font-scale-body-small);pointer-events:none}.select-module_Description_OmwmV{padding-inline:calc((var(--control-group-border-radius) + 0px) / 2)}.select-module_SelectPopup_UzGXL{--select-list-border-radius:var(--radius-medium);--select-list-padding:var(--space-x-small);box-sizing:border-box;min-inline-size:var(--anchor-width);overflow:visible;color:var(--global-foreground);outline:none;position:relative}.select-module_ScrollArrow_kHlEi{--scroll-arrow-background:var(--is-vibrancy-active) oklab(from var(--base-1) l a b/80%);position:absolute;inset-inline:0;z-index:1;inline-size:100%;block-size:var(--space-large);cursor:default;background:var(--scroll-arrow-background,var(--base-1));backdrop-filter:var(--vibrancy-filter,none);border:1px solid var(--global-contrast)}.select-module_ScrollButton_sHBOa{pointer-events:none}.select-module_ScrollArrowUp_DGXS-{inset-block-start:0;border-radius:var(--select-list-border-radius) var(--select-list-border-radius) 0 0}.select-module_ScrollArrowDown_vhJy0{inset-block-end:0;border-radius:0 0 var(--select-list-border-radius) var(--select-list-border-radius)}.select-module_List_jdUWx{box-sizing:border-box;inline-size:100%;max-block-size:var(--available-height);overflow-y:auto;scroll-padding-block:var(--select-list-padding);list-style:none;overscroll-behavior:contain;&:focus,&:focus-visible{outline:none}}.select-module_OptionText_UynBD{flex:1 1 auto;min-inline-size:0}.select-module_Option_KgYqz{border-radius:calc((var(--select-list-border-radius) + 0px) - var(--select-list-padding));cursor:pointer;&:focus{outline:none}&:focus-visible{outline:2px solid var(--global-foreground);outline-offset:0}&:not([data-disabled]):hover,&:not([data-disabled])[data-highlighted]{--option-hover-background:var(--is-vibrancy-active) oklab(from var(--global-contrast) l a b/14%);background:var(--option-hover-background,var(--global-contrast))}&[data-disabled]{color:var(--global-disabled-foreground);cursor:not-allowed}}.select-module_Indicator_YNUuz{inline-size:var(--space-medium);color:var(--global-primary);opacity:0;transition:opacity var(--duration-fast) var(--easing-standard),transform var(--duration-fast) var(--easing-standard);&[data-selected]{opacity:1}}.select-module_Group_xzkuA+.select-module_Group_xzkuA{margin-block-start:var(--space-medium)}.select-module_Separator_Q-ri9{block-size:1px;margin-block:var(--space-small);margin-inline:var(--space-small);background:var(--base-3)}
@@ -53,8 +53,14 @@ export type SelectProps = SelectRoot.Props<string> & Omit<FieldRoot.Props, 'ref'
53
53
  * @default No ref is attached.
54
54
  */
55
55
  ref?: React.Ref<HTMLButtonElement>;
56
+ /**
57
+ * When `true`, aligns the list popup width with the trigger via Base UI `alignItemWithTrigger`.
58
+ *
59
+ * @default false
60
+ */
61
+ alignListWithTrigger?: boolean;
56
62
  };
57
- declare function SelectRootComponent({ children, className, description, dirty, disabled, error, icon, invalid, label, name, placeholder, ref, touched, validate, validationDebounceTime, validationMode, ...selectRootProps }: SelectProps): React.JSX.Element;
63
+ declare function SelectRootComponent({ alignListWithTrigger, children, className, description, dirty, disabled, error, icon, invalid, label, name, placeholder, ref, touched, validate, validationDebounceTime, validationMode, ...selectRootProps }: SelectProps): React.JSX.Element;
58
64
  export declare const Select: typeof SelectRootComponent & {
59
65
  Option: typeof SelectOption;
60
66
  Group: typeof SelectGroup;
@@ -4,6 +4,7 @@
4
4
  "whenToUse": [
5
5
  "Choose one value from a predefined list with label and helper copy",
6
6
  "Grouped or separated option lists",
7
+ "Rich option rows with a leading decorative addon and multi-line label content",
7
8
  "Trigger chrome aligned with Textfield control shell"
8
9
  ],
9
10
  "whenNotToUse": ["Multiple selection", "Combobox, filterable search, or custom anchor positioning"],
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import './select.css';
3
+ import { clsx } from "../../core/clsx.js";
3
4
  import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
4
5
  import { Stack } from "../stack/stack.js";
5
6
  import { Elevator } from "../elevator/elevator.js";
@@ -13,13 +14,12 @@ import { SelectOption } from "./select-option.js";
13
14
  import { SelectSeparator } from "./select-separator.js";
14
15
  import { Icon } from "../icon/icon.js";
15
16
  import { Surface } from "../surface/surface.js";
16
- import { clsx } from "clsx";
17
17
  import { jsx, jsxs } from "react/jsx-runtime";
18
18
  import { useId } from "react";
19
19
  import { Field } from "@base-ui/react/field";
20
20
  import { Select } from "@base-ui/react/select";
21
21
  //#region src/components/select/select.tsx
22
- function SelectRootComponent({ children, className, description, dirty, disabled, error, icon = /* @__PURE__ */ jsx(Icon, {
22
+ function SelectRootComponent({ alignListWithTrigger = false, children, className, description, dirty, disabled, error, icon = /* @__PURE__ */ jsx(Icon, {
23
23
  name: "ChevronExpandY",
24
24
  size: 16
25
25
  }), invalid, label, name, placeholder, ref, touched, validate, validationDebounceTime, validationMode, ...selectRootProps }) {
@@ -87,7 +87,7 @@ function SelectRootComponent({ children, className, description, dirty, disabled
87
87
  children: icon
88
88
  })]
89
89
  }), /* @__PURE__ */ jsx(Select.Portal, { children: /* @__PURE__ */ jsx(Select.Positioner, {
90
- alignItemWithTrigger: true,
90
+ alignItemWithTrigger: alignListWithTrigger,
91
91
  children: /* @__PURE__ */ jsxs(Select.Popup, {
92
92
  className: select_module_default.SelectPopup,
93
93
  children: [
@@ -10,6 +10,7 @@ var select_module_default = {
10
10
  ScrollArrowUp: "select-module_ScrollArrowUp_DGXS-",
11
11
  ScrollArrowDown: "select-module_ScrollArrowDown_vhJy0",
12
12
  List: "select-module_List_jdUWx",
13
+ OptionText: "select-module_OptionText_UynBD",
13
14
  Option: "select-module_Option_KgYqz",
14
15
  Indicator: "select-module_Indicator_YNUuz",
15
16
  Group: "select-module_Group_xzkuA",
@@ -1,8 +1,8 @@
1
1
  import './skeleton.css';
2
+ import { clsx } from "../../core/clsx.js";
2
3
  import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
3
4
  import { resolveThemeValue } from "../../core/theme/resolve-theme-value.js";
4
5
  import skeleton_module_default from "./skeleton.module.js";
5
- import clsx$1 from "clsx";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  //#region src/components/skeleton/skeleton.tsx
8
8
  var Skeleton = ({ className, height, minHeight, minWidth, radius, ref, style, width, ...otherProps }) => {
@@ -20,7 +20,7 @@ var Skeleton = ({ className, height, minHeight, minWidth, radius, ref, style, wi
20
20
  ...intrinsicAttributes,
21
21
  ref,
22
22
  "aria-hidden": "true",
23
- className: clsx$1(skeleton_module_default.Skeleton, className),
23
+ className: clsx(skeleton_module_default.Skeleton, className),
24
24
  style: dynamicStyle
25
25
  });
26
26
  };
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import './slider.css';
3
+ import { clsx } from "../../core/clsx.js";
3
4
  import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
4
5
  import { Stack } from "../stack/stack.js";
5
6
  import { Text } from "../text/text.js";
@@ -8,7 +9,6 @@ import { FieldLabel } from "../basic-input/field-label.js";
8
9
  import slider_module_default from "./slider.module.js";
9
10
  import { SliderControl } from "./slider-control.js";
10
11
  import { isRangeSlider } from "./slider-utils.js";
11
- import { clsx } from "clsx";
12
12
  import { jsx, jsxs } from "react/jsx-runtime";
13
13
  import { Field } from "@base-ui/react/field";
14
14
  import { Slider } from "@base-ui/react/slider";
@@ -1,7 +1,7 @@
1
1
  import './spinner.css';
2
+ import { clsx } from "../../core/clsx.js";
2
3
  import { extractIntrinsicViraProps } from "../../core/props/intrinsic-vira-props.js";
3
4
  import spinner_module_default from "./spinner.module.js";
4
- import clsx$1 from "clsx";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/components/spinner/spinner.tsx
7
7
  var Spinner = ({ className, color, size = "big", ref, style, ...otherProps }) => {
@@ -10,7 +10,7 @@ var Spinner = ({ className, color, size = "big", ref, style, ...otherProps }) =>
10
10
  ...componentProps,
11
11
  ...intrinsicAttributes,
12
12
  ref,
13
- className: clsx$1(spinner_module_default.Spinner, className),
13
+ className: clsx(spinner_module_default.Spinner, className),
14
14
  "data-dimension": size,
15
15
  viewBox: "0 0 16 16",
16
16
  xmlns: "http://www.w3.org/2000/svg",