@dev-dga/react 0.1.1 → 0.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/dist/index.d.ts CHANGED
@@ -2,7 +2,9 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as class_variance_authority_types from 'class-variance-authority/types';
3
3
  import { ReactNode } from 'react';
4
4
  import { VariantProps } from 'class-variance-authority';
5
- import { Checkbox as Checkbox$1 } from 'radix-ui';
5
+ import { Checkbox as Checkbox$1, RadioGroup as RadioGroup$1, Switch as Switch$1, Select as Select$1 } from 'radix-ui';
6
+ import { DgaTheme } from '@dev-dga/tokens';
7
+ export { DgaTheme, PaletteName, ThemeColor } from '@dev-dga/tokens';
6
8
  import { ClassValue } from 'clsx';
7
9
 
8
10
  declare const buttonVariants: (props?: ({
@@ -16,8 +18,24 @@ interface ButtonProps extends React.ComponentProps<'button'>, VariantProps<typeo
16
18
  endIcon?: ReactNode;
17
19
  /** Flip start/end icons horizontally in RTL (for chevrons, arrows, etc.) */
18
20
  iconFlip?: boolean;
21
+ /**
22
+ * Render as the single child element instead of a `<button>`. Lets consumers
23
+ * compose Button with router links (`<Button asChild><Link href="…">…</Link></Button>`)
24
+ * without `<button><a>` invalid nesting.
25
+ *
26
+ * The `type` and native `disabled` attributes are dropped in this mode
27
+ * (they're meaningless on non-button elements) , the disabled visual + a11y
28
+ * state still works via `aria-disabled` + `tabIndex={-1}`. button.css
29
+ * matches on `[aria-disabled='true']` alongside `:disabled` so the styling
30
+ * applies on any element.
31
+ *
32
+ * Consumer remains responsible for preventing the underlying action when
33
+ * disabled (e.g., calling `e.preventDefault()` in the Link's onClick),
34
+ * since native `disabled` doesn't gate clicks on non-form-controls.
35
+ */
36
+ asChild?: boolean;
19
37
  }
20
- declare function Button({ variant, size, fullWidth, loading, disabled, startIcon, endIcon, iconFlip, className, children, type, ...props }: ButtonProps): react_jsx_runtime.JSX.Element;
38
+ declare function Button({ variant, size, fullWidth, loading, disabled, startIcon, endIcon, iconFlip, asChild, className, children, type, ...props }: ButtonProps): react_jsx_runtime.JSX.Element;
21
39
 
22
40
  declare const inputVariants: (props?: ({
23
41
  size?: "sm" | "md" | "lg" | null | undefined;
@@ -34,14 +52,14 @@ interface InputProps extends Omit<React.ComponentProps<'input'>, 'size'>, Varian
34
52
  error?: boolean;
35
53
  /**
36
54
  * Content rendered inside the field, before the input (icon or short text,
37
- * e.g. a search glyph or `https://`). May be interactive it is NOT
55
+ * e.g. a search glyph or `https://`). May be interactive , it is NOT
38
56
  * `aria-hidden`. Mark purely-decorative icons `aria-hidden` yourself.
39
57
  */
40
58
  startAdornment?: ReactNode;
41
59
  /**
42
60
  * Content rendered inside the field, after the input. Compose a clear
43
61
  * button or password-reveal toggle here with `<Button size="icon-sm">`
44
- * the 28px in-field icon size that fits the field without overflow.
62
+ * , the 28px in-field icon size that fits the field without overflow.
45
63
  */
46
64
  endAdornment?: ReactNode;
47
65
  }
@@ -80,26 +98,165 @@ interface CheckboxProps extends Omit<React.ComponentProps<typeof Checkbox$1.Root
80
98
  }
81
99
  declare function Checkbox({ id: externalId, label, helperText, errorMessage, error, size, required, className, ...props }: CheckboxProps): react_jsx_runtime.JSX.Element;
82
100
 
101
+ declare const radioGroupVariants: (props?: ({
102
+ size?: "sm" | "md" | null | undefined;
103
+ orientation?: "horizontal" | "vertical" | null | undefined;
104
+ error?: boolean | null | undefined;
105
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
106
+ declare const radioVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
107
+ interface RadioGroupProps extends Omit<React.ComponentProps<typeof RadioGroup$1.Root>, 'children' | 'orientation'>, Pick<VariantProps<typeof radioGroupVariants>, 'size' | 'orientation'> {
108
+ /** Group label, sits above the rows. Associated to the group via aria-labelledby. */
109
+ label?: ReactNode;
110
+ /** Hint shown below the group. Hidden while an error message is showing. */
111
+ helperText?: ReactNode;
112
+ /** Message shown below the group when `error` is true (or when only `errorMessage` is set). */
113
+ errorMessage?: ReactNode;
114
+ /** Marks the group invalid: sets aria-invalid and applies error styling. */
115
+ error?: boolean;
116
+ /** `<Radio>` children. */
117
+ children: ReactNode;
118
+ }
119
+ interface RadioProps extends Omit<React.ComponentProps<typeof RadioGroup$1.Item>, 'children'> {
120
+ /** Visible label for this radio, sits beside the circle, associated via htmlFor/id. */
121
+ label?: ReactNode;
122
+ }
123
+ declare function RadioGroup({ id: externalId, label, helperText, errorMessage, error, size, orientation, required, className, children, ...props }: RadioGroupProps): react_jsx_runtime.JSX.Element;
124
+ declare function Radio({ id: externalId, label, className, ...props }: RadioProps): react_jsx_runtime.JSX.Element;
125
+
126
+ declare const switchVariants: (props?: ({
127
+ size?: "sm" | "md" | null | undefined;
128
+ error?: boolean | null | undefined;
129
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
130
+ interface SwitchProps extends Omit<React.ComponentProps<typeof Switch$1.Root>, 'children'>, VariantProps<typeof switchVariants> {
131
+ /** Visible label, sits beside the track, associated via `htmlFor`/`id`. */
132
+ label?: ReactNode;
133
+ /** Hint shown below the row. Hidden while an error message is showing. */
134
+ helperText?: ReactNode;
135
+ /** Message shown below the row when `error` is true. */
136
+ errorMessage?: ReactNode;
137
+ /** Marks the field invalid: sets `aria-invalid` and error styling. */
138
+ error?: boolean;
139
+ }
140
+ declare function Switch({ id: externalId, label, helperText, errorMessage, error, size, required, className, ...props }: SwitchProps): react_jsx_runtime.JSX.Element;
141
+
142
+ declare const selectTriggerVariants: (props?: ({
143
+ size?: "sm" | "md" | null | undefined;
144
+ error?: boolean | null | undefined;
145
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
146
+ interface SelectProps extends Omit<React.ComponentProps<typeof Select$1.Root>, 'children' | 'dir'>, VariantProps<typeof selectTriggerVariants> {
147
+ /** Visible label above the trigger, associated via `htmlFor`/`id`. */
148
+ label?: ReactNode;
149
+ /** Hint shown below the trigger. Hidden while an error message is showing. */
150
+ helperText?: ReactNode;
151
+ /** Message shown below the trigger when `error` is true. */
152
+ errorMessage?: ReactNode;
153
+ /** Marks the field invalid: sets `aria-invalid` and error styling. */
154
+ error?: boolean;
155
+ /** Placeholder shown in the trigger when no value is selected. */
156
+ placeholder?: ReactNode;
157
+ /** `<SelectItem>` children, rendered inside the dropdown panel. */
158
+ children: ReactNode;
159
+ /** Caller-supplied id for the trigger; falls back to a generated one. */
160
+ id?: string;
161
+ /** Forwarded to the trigger (the focusable control). */
162
+ className?: string;
163
+ 'aria-label'?: string;
164
+ 'aria-labelledby'?: string;
165
+ }
166
+ interface SelectItemProps extends React.ComponentProps<typeof Select$1.Item> {
167
+ /** The visible label for this item. */
168
+ children: ReactNode;
169
+ }
170
+ declare function Select({ id: externalId, label, helperText, errorMessage, error, size, required, placeholder, className, children, ...rootProps }: SelectProps): react_jsx_runtime.JSX.Element;
171
+ declare function SelectItem({ className, children, ...props }: SelectItemProps): react_jsx_runtime.JSX.Element;
172
+
83
173
  type DgaRootElement = 'div' | 'main' | 'nav' | 'section' | 'article' | 'aside' | 'header' | 'footer';
84
174
  interface DgaProviderProps {
85
175
  dir?: 'ltr' | 'rtl';
86
176
  locale?: string;
87
177
  mode?: 'light' | 'dark';
178
+ /**
179
+ * Brand theme. `theme.primary` accepts a palette name (`'lavender'`),
180
+ * any CSS color string (`'#7C3AED'` , hover/active auto-derived via
181
+ * `color-mix()`), or an explicit `{ base, hover, active, foreground? }`
182
+ * triplet. The override-object pattern (`style={{ '--ddga-color-primary':
183
+ * '...' }}`) still works , `style` wins over `theme`.
184
+ */
185
+ theme?: DgaTheme;
88
186
  as?: DgaRootElement;
89
187
  className?: string;
90
188
  style?: React.CSSProperties;
91
189
  children: React.ReactNode;
92
190
  }
93
- declare function DgaProvider({ dir, locale, mode, as: Component, className, style: consumerStyle, children, }: DgaProviderProps): react_jsx_runtime.JSX.Element;
191
+ declare function DgaProvider({ dir, locale, mode, theme, as: Component, className, style: consumerStyle, children, }: DgaProviderProps): react_jsx_runtime.JSX.Element;
94
192
 
95
193
  interface DgaContextValue {
96
194
  dir: 'ltr' | 'rtl';
97
195
  locale: string;
98
196
  mode: 'light' | 'dark';
99
- rootRef: React.RefObject<HTMLElement | null>;
197
+ /**
198
+ * The DgaProvider root element. Portal-rendering components (Select, and
199
+ * future Tooltip / Modal / Toast / Popover / DropdownMenu) MUST pass this
200
+ * as their Radix `Portal container={…}` so that `data-theme`, custom
201
+ * theme vars, and `.ddga-theme-*` classes set on the root inherit into
202
+ * the portaled content. Without it, portals mount under <body> and
203
+ * silently miss dark mode + custom themes.
204
+ *
205
+ * Exposed as state (not a ref) so consumers re-render once the element
206
+ * mounts , a useRef wouldn't fire that update and the portal would
207
+ * race to <body> on the first commit.
208
+ */
209
+ rootEl: HTMLElement | null;
100
210
  }
101
211
  declare function useDga(): DgaContextValue;
102
212
 
213
+ /**
214
+ * Returns the current writing direction from the nearest `<DgaProvider>`.
215
+ *
216
+ * Prefer this over `useDga().dir` when a component only needs direction
217
+ * (clearer intent, smaller dependency footprint at the call site).
218
+ *
219
+ * Throws if called outside a `<DgaProvider>` (matches `useDga`).
220
+ */
221
+ declare function useDir(): 'ltr' | 'rtl';
222
+
223
+ interface UseFieldA11yOptions {
224
+ /** Component name used in the dev warning, e.g. `'Input'`. */
225
+ name: string;
226
+ /** Caller-supplied id; falls back to a stable generated one. */
227
+ id?: string;
228
+ label?: ReactNode;
229
+ error?: boolean;
230
+ errorMessage?: ReactNode;
231
+ helperText?: ReactNode;
232
+ /** From the consumer's props , used to suppress the no-label warning. */
233
+ 'aria-label'?: string;
234
+ 'aria-labelledby'?: string;
235
+ }
236
+ interface FieldA11y {
237
+ fieldId: string;
238
+ helperId: string;
239
+ errorId: string;
240
+ hasError: boolean;
241
+ hasErrorMessage: boolean;
242
+ hasHelper: boolean;
243
+ /** Spread onto the control element (input / textarea / Radix root). */
244
+ controlProps: {
245
+ id: string;
246
+ 'aria-invalid': true | undefined;
247
+ 'aria-describedby': string | undefined;
248
+ };
249
+ }
250
+ declare function useFieldA11y(options: UseFieldA11yOptions): FieldA11y;
251
+
252
+ interface FieldMessageProps {
253
+ id: string;
254
+ /** `error` announces politely; `helper` is static. */
255
+ variant: 'error' | 'helper';
256
+ children: ReactNode;
257
+ }
258
+ declare function FieldMessage({ id, variant, children }: FieldMessageProps): react_jsx_runtime.JSX.Element;
259
+
103
260
  declare function cn(...inputs: ClassValue[]): string;
104
261
 
105
- export { Button, type ButtonProps, Checkbox, type CheckboxProps, DgaProvider, type DgaProviderProps, Input, type InputProps, Textarea, type TextareaProps, buttonVariants, checkboxVariants, cn, inputVariants, textareaVariants, useDga };
262
+ export { Button, type ButtonProps, Checkbox, type CheckboxProps, DgaProvider, type DgaProviderProps, type FieldA11y, FieldMessage, type FieldMessageProps, Input, type InputProps, Radio, RadioGroup, type RadioGroupProps, type RadioProps, Select, SelectItem, type SelectItemProps, type SelectProps, Switch, type SwitchProps, Textarea, type TextareaProps, type UseFieldA11yOptions, buttonVariants, checkboxVariants, cn, inputVariants, radioGroupVariants, radioVariants, selectTriggerVariants, switchVariants, textareaVariants, useDga, useDir, useFieldA11y };
package/dist/index.js CHANGED
@@ -65,6 +65,24 @@ function Minus(props) {
65
65
  }
66
66
  );
67
67
  }
68
+ function ChevronDown(props) {
69
+ return /* @__PURE__ */ jsx(
70
+ "svg",
71
+ {
72
+ xmlns: "http://www.w3.org/2000/svg",
73
+ width: "1em",
74
+ height: "1em",
75
+ viewBox: "0 0 24 24",
76
+ fill: "none",
77
+ stroke: "currentColor",
78
+ strokeWidth: "2",
79
+ strokeLinecap: "round",
80
+ strokeLinejoin: "round",
81
+ ...props,
82
+ children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
83
+ }
84
+ );
85
+ }
68
86
 
69
87
  // src/components/Button/Button.tsx
70
88
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
@@ -143,7 +161,7 @@ function Button({
143
161
  // src/components/Input/Input.tsx
144
162
  import { cva as cva2 } from "class-variance-authority";
145
163
 
146
- // src/internal/field/use-field-a11y.ts
164
+ // src/field/use-field-a11y.ts
147
165
  import { useId } from "react";
148
166
  function isPresent(value) {
149
167
  return value != null && value !== "";
@@ -153,7 +171,7 @@ function useFieldA11y(options) {
153
171
  const fieldId = options.id ?? generatedId;
154
172
  const helperId = `${fieldId}-helper`;
155
173
  const errorId = `${fieldId}-error`;
156
- const hasError = !!options.error;
174
+ const hasError = !!options.error || isPresent(options.errorMessage);
157
175
  const hasErrorMessage = hasError && isPresent(options.errorMessage);
158
176
  const hasHelper = !hasErrorMessage && isPresent(options.helperText);
159
177
  if (process.env.NODE_ENV === "development" && !options.label) {
@@ -178,7 +196,7 @@ function useFieldA11y(options) {
178
196
  };
179
197
  }
180
198
 
181
- // src/internal/field/FieldMessage.tsx
199
+ // src/field/FieldMessage.tsx
182
200
  import { jsx as jsx3 } from "react/jsx-runtime";
183
201
  function FieldMessage({ id, variant, children }) {
184
202
  return /* @__PURE__ */ jsx3(
@@ -292,7 +310,7 @@ var textareaVariants = cva3("ddga-textarea", {
292
310
  true: "ddga-textarea--error"
293
311
  },
294
312
  // Horizontal/both resize breaks form layout (same reason it's not the
295
- // default) only vertical or locked are offered.
313
+ // default) , only vertical or locked are offered.
296
314
  resize: {
297
315
  vertical: "ddga-textarea--resize-vertical",
298
316
  none: "ddga-textarea--resize-none"
@@ -419,9 +437,169 @@ function Checkbox({
419
437
  ] });
420
438
  }
421
439
 
422
- // src/providers/DgaProvider.tsx
423
- import { useRef, useMemo, useContext as useContext2 } from "react";
424
- import { Tooltip as TooltipPrimitive } from "radix-ui";
440
+ // src/components/Radio/Radio.tsx
441
+ import { useId as useId2 } from "react";
442
+ import { RadioGroup as RadioGroupPrimitive } from "radix-ui";
443
+ import { cva as cva5 } from "class-variance-authority";
444
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
445
+ var radioGroupVariants = cva5("ddga-radio-group", {
446
+ variants: {
447
+ size: {
448
+ sm: "ddga-radio-group--sm",
449
+ md: "ddga-radio-group--md"
450
+ },
451
+ orientation: {
452
+ vertical: "ddga-radio-group--vertical",
453
+ horizontal: "ddga-radio-group--horizontal"
454
+ },
455
+ error: {
456
+ true: "ddga-radio-group--error"
457
+ }
458
+ },
459
+ defaultVariants: {
460
+ size: "md",
461
+ orientation: "vertical"
462
+ }
463
+ });
464
+ var radioVariants = cva5("ddga-radio");
465
+ function RadioGroup({
466
+ id: externalId,
467
+ label,
468
+ helperText,
469
+ errorMessage,
470
+ error,
471
+ size,
472
+ orientation,
473
+ required,
474
+ className,
475
+ children,
476
+ ...props
477
+ }) {
478
+ const { errorId, helperId, hasError, hasErrorMessage, hasHelper, controlProps, fieldId } = useFieldA11y({
479
+ name: "RadioGroup",
480
+ id: externalId,
481
+ label,
482
+ error,
483
+ errorMessage,
484
+ helperText,
485
+ "aria-label": props["aria-label"],
486
+ "aria-labelledby": props["aria-labelledby"]
487
+ });
488
+ const labelId = `${fieldId}-label`;
489
+ return /* @__PURE__ */ jsxs5("div", { "data-slot": "radio-group-field", className: "ddga-field", children: [
490
+ label && /* @__PURE__ */ jsxs5("span", { id: labelId, className: "ddga-radio-group__label", children: [
491
+ label,
492
+ required && /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", className: "ddga-radio-group__required", children: "*" })
493
+ ] }),
494
+ /* @__PURE__ */ jsx7(
495
+ RadioGroupPrimitive.Root,
496
+ {
497
+ ...props,
498
+ "aria-invalid": controlProps["aria-invalid"],
499
+ "aria-describedby": controlProps["aria-describedby"],
500
+ "aria-labelledby": label ? labelId : props["aria-labelledby"],
501
+ orientation: orientation === "horizontal" ? "horizontal" : "vertical",
502
+ required,
503
+ "data-slot": "radio-group",
504
+ className: cn(radioGroupVariants({ size, orientation, error: hasError }), className),
505
+ children
506
+ }
507
+ ),
508
+ hasErrorMessage && /* @__PURE__ */ jsx7(FieldMessage, { id: errorId, variant: "error", children: errorMessage }),
509
+ hasHelper && /* @__PURE__ */ jsx7(FieldMessage, { id: helperId, variant: "helper", children: helperText })
510
+ ] });
511
+ }
512
+ function Radio({ id: externalId, label, className, ...props }) {
513
+ const generatedId = useId2();
514
+ const itemId = externalId ?? generatedId;
515
+ return /* @__PURE__ */ jsxs5("div", { className: "ddga-radio-row", children: [
516
+ /* @__PURE__ */ jsx7(
517
+ RadioGroupPrimitive.Item,
518
+ {
519
+ ...props,
520
+ id: itemId,
521
+ "data-slot": "radio",
522
+ className: cn(radioVariants(), className),
523
+ children: /* @__PURE__ */ jsx7(
524
+ RadioGroupPrimitive.Indicator,
525
+ {
526
+ "data-slot": "radio-indicator",
527
+ className: "ddga-radio__indicator",
528
+ children: /* @__PURE__ */ jsx7("span", { className: "ddga-radio__dot", "aria-hidden": "true" })
529
+ }
530
+ )
531
+ }
532
+ ),
533
+ label && /* @__PURE__ */ jsx7("label", { htmlFor: itemId, className: "ddga-radio__label", children: label })
534
+ ] });
535
+ }
536
+
537
+ // src/components/Switch/Switch.tsx
538
+ import { Switch as SwitchPrimitive } from "radix-ui";
539
+ import { cva as cva6 } from "class-variance-authority";
540
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
541
+ var switchVariants = cva6("ddga-switch", {
542
+ variants: {
543
+ size: {
544
+ sm: "ddga-switch--sm",
545
+ md: "ddga-switch--md"
546
+ },
547
+ error: {
548
+ true: "ddga-switch--error"
549
+ }
550
+ },
551
+ defaultVariants: {
552
+ size: "md"
553
+ }
554
+ });
555
+ function Switch({
556
+ id: externalId,
557
+ label,
558
+ helperText,
559
+ errorMessage,
560
+ error,
561
+ size,
562
+ required,
563
+ className,
564
+ ...props
565
+ }) {
566
+ const { fieldId, errorId, helperId, hasError, hasErrorMessage, hasHelper, controlProps } = useFieldA11y({
567
+ name: "Switch",
568
+ id: externalId,
569
+ label,
570
+ error,
571
+ errorMessage,
572
+ helperText,
573
+ "aria-label": props["aria-label"],
574
+ "aria-labelledby": props["aria-labelledby"]
575
+ });
576
+ return /* @__PURE__ */ jsxs6("div", { "data-slot": "switch-field", className: "ddga-field", children: [
577
+ /* @__PURE__ */ jsxs6("div", { className: "ddga-switch-row", children: [
578
+ /* @__PURE__ */ jsx8(
579
+ SwitchPrimitive.Root,
580
+ {
581
+ ...props,
582
+ ...controlProps,
583
+ "data-slot": "switch",
584
+ required,
585
+ className: cn(switchVariants({ size, error: hasError }), className),
586
+ children: /* @__PURE__ */ jsx8(SwitchPrimitive.Thumb, { "data-slot": "switch-thumb", className: "ddga-switch__thumb" })
587
+ }
588
+ ),
589
+ label && /* @__PURE__ */ jsxs6("label", { htmlFor: fieldId, className: "ddga-switch__label", children: [
590
+ label,
591
+ required && /* @__PURE__ */ jsx8("span", { "aria-hidden": "true", className: "ddga-switch__required", children: "*" })
592
+ ] })
593
+ ] }),
594
+ hasErrorMessage && /* @__PURE__ */ jsx8(FieldMessage, { id: errorId, variant: "error", children: errorMessage }),
595
+ hasHelper && /* @__PURE__ */ jsx8(FieldMessage, { id: helperId, variant: "helper", children: helperText })
596
+ ] });
597
+ }
598
+
599
+ // src/components/Select/Select.tsx
600
+ import { useContext as useContext2 } from "react";
601
+ import { Select as SelectPrimitive } from "radix-ui";
602
+ import { cva as cva7 } from "class-variance-authority";
425
603
 
426
604
  // src/providers/DgaContext.ts
427
605
  import { createContext, useContext } from "react";
@@ -434,50 +612,162 @@ function useDga() {
434
612
  return ctx;
435
613
  }
436
614
 
615
+ // src/components/Select/Select.tsx
616
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
617
+ var selectTriggerVariants = cva7("ddga-select-trigger", {
618
+ variants: {
619
+ size: {
620
+ sm: "ddga-select-trigger--sm",
621
+ md: "ddga-select-trigger--md"
622
+ },
623
+ error: {
624
+ true: "ddga-select-trigger--error"
625
+ }
626
+ },
627
+ defaultVariants: {
628
+ size: "md"
629
+ }
630
+ });
631
+ function Select({
632
+ id: externalId,
633
+ label,
634
+ helperText,
635
+ errorMessage,
636
+ error,
637
+ size,
638
+ required,
639
+ placeholder,
640
+ className,
641
+ children,
642
+ ...rootProps
643
+ }) {
644
+ const { fieldId, errorId, helperId, hasError, hasErrorMessage, hasHelper, controlProps } = useFieldA11y({
645
+ name: "Select",
646
+ id: externalId,
647
+ label,
648
+ error,
649
+ errorMessage,
650
+ helperText,
651
+ "aria-label": rootProps["aria-label"],
652
+ "aria-labelledby": rootProps["aria-labelledby"]
653
+ });
654
+ const ctx = useContext2(DgaContext);
655
+ const portalContainer = ctx?.rootEl ?? void 0;
656
+ return /* @__PURE__ */ jsxs7("div", { "data-slot": "select-field", className: "ddga-field", children: [
657
+ label && /* @__PURE__ */ jsxs7("label", { htmlFor: fieldId, className: "ddga-select__label", children: [
658
+ label,
659
+ required && /* @__PURE__ */ jsx9("span", { "aria-hidden": "true", className: "ddga-select__required", children: "*" })
660
+ ] }),
661
+ /* @__PURE__ */ jsxs7(SelectPrimitive.Root, { required, ...rootProps, children: [
662
+ /* @__PURE__ */ jsxs7(
663
+ SelectPrimitive.Trigger,
664
+ {
665
+ ...controlProps,
666
+ "data-slot": "select-trigger",
667
+ className: cn(selectTriggerVariants({ size, error: hasError }), className),
668
+ children: [
669
+ /* @__PURE__ */ jsx9(SelectPrimitive.Value, { placeholder }),
670
+ /* @__PURE__ */ jsx9(SelectPrimitive.Icon, { asChild: true, className: "ddga-select__icon", children: /* @__PURE__ */ jsx9(ChevronDown, { "aria-hidden": "true" }) })
671
+ ]
672
+ }
673
+ ),
674
+ /* @__PURE__ */ jsx9(SelectPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx9(
675
+ SelectPrimitive.Content,
676
+ {
677
+ "data-slot": "select-content",
678
+ className: "ddga-select-content",
679
+ position: "popper",
680
+ sideOffset: 4,
681
+ children: /* @__PURE__ */ jsx9(SelectPrimitive.Viewport, { className: "ddga-select-viewport", children })
682
+ }
683
+ ) })
684
+ ] }),
685
+ hasErrorMessage && /* @__PURE__ */ jsx9(FieldMessage, { id: errorId, variant: "error", children: errorMessage }),
686
+ hasHelper && /* @__PURE__ */ jsx9(FieldMessage, { id: helperId, variant: "helper", children: helperText })
687
+ ] });
688
+ }
689
+ function SelectItem({ className, children, ...props }) {
690
+ return /* @__PURE__ */ jsxs7(
691
+ SelectPrimitive.Item,
692
+ {
693
+ ...props,
694
+ "data-slot": "select-item",
695
+ className: cn("ddga-select-item", className),
696
+ children: [
697
+ /* @__PURE__ */ jsx9(SelectPrimitive.ItemText, { children }),
698
+ /* @__PURE__ */ jsx9(SelectPrimitive.ItemIndicator, { className: "ddga-select-item__indicator", children: /* @__PURE__ */ jsx9(Check, { className: "ddga-select-item__check", "aria-hidden": "true" }) })
699
+ ]
700
+ }
701
+ );
702
+ }
703
+
437
704
  // src/providers/DgaProvider.tsx
438
- import { jsx as jsx7 } from "react/jsx-runtime";
705
+ import { useState, useMemo, useContext as useContext3 } from "react";
706
+ import { Direction as DirectionPrimitive, Tooltip as TooltipPrimitive } from "radix-ui";
707
+ import { buildTheme } from "@dev-dga/tokens";
708
+ import { jsx as jsx10 } from "react/jsx-runtime";
439
709
  function DgaProvider({
440
710
  dir = "ltr",
441
711
  locale,
442
712
  mode = "light",
713
+ theme,
443
714
  as: Component = "div",
444
715
  className,
445
716
  style: consumerStyle,
446
717
  children
447
718
  }) {
448
- const parentCtx = useContext2(DgaContext);
719
+ const parentCtx = useContext3(DgaContext);
449
720
  const isNested = parentCtx !== null;
450
- const rootRef = useRef(null);
721
+ const [rootEl, setRootEl] = useState(null);
451
722
  const resolvedLocale = locale ?? (dir === "rtl" ? "ar" : "en");
452
723
  const ctxValue = useMemo(
453
- () => ({ dir, locale: resolvedLocale, mode, rootRef }),
454
- [dir, resolvedLocale, mode]
724
+ () => ({ dir, locale: resolvedLocale, mode, rootEl }),
725
+ [dir, resolvedLocale, mode, rootEl]
455
726
  );
456
- return /* @__PURE__ */ jsx7(DgaContext.Provider, { value: ctxValue, children: /* @__PURE__ */ jsx7(
727
+ const themeVars = useMemo(() => theme ? buildTheme(theme) : null, [theme]);
728
+ const inner = /* @__PURE__ */ jsx10(DirectionPrimitive.Provider, { dir, children });
729
+ return /* @__PURE__ */ jsx10(DgaContext.Provider, { value: ctxValue, children: /* @__PURE__ */ jsx10(
457
730
  Component,
458
731
  {
459
- ref: rootRef,
732
+ ref: setRootEl,
460
733
  dir,
461
734
  lang: resolvedLocale,
462
735
  "data-slot": "dga-root",
463
736
  "data-theme": mode,
464
737
  className,
465
- style: { colorScheme: mode, ...consumerStyle },
466
- children: isNested ? children : /* @__PURE__ */ jsx7(TooltipPrimitive.Provider, { delayDuration: 300, skipDelayDuration: 100, children })
738
+ style: { colorScheme: mode, ...themeVars ?? {}, ...consumerStyle },
739
+ children: isNested ? inner : /* @__PURE__ */ jsx10(TooltipPrimitive.Provider, { delayDuration: 300, skipDelayDuration: 100, children: inner })
467
740
  }
468
741
  ) });
469
742
  }
743
+
744
+ // src/hooks/useDir.ts
745
+ function useDir() {
746
+ return useDga().dir;
747
+ }
470
748
  export {
471
749
  Button,
472
750
  Checkbox,
473
751
  DgaProvider,
752
+ FieldMessage,
474
753
  Input,
754
+ Radio,
755
+ RadioGroup,
756
+ Select,
757
+ SelectItem,
758
+ Switch,
475
759
  Textarea,
476
760
  buttonVariants,
477
761
  checkboxVariants,
478
762
  cn,
479
763
  inputVariants,
764
+ radioGroupVariants,
765
+ radioVariants,
766
+ selectTriggerVariants,
767
+ switchVariants,
480
768
  textareaVariants,
481
- useDga
769
+ useDga,
770
+ useDir,
771
+ useFieldA11y
482
772
  };
483
773
  //# sourceMappingURL=index.js.map