@dev-dga/react 0.2.0 → 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/CHANGELOG.md +48 -0
- package/README.md +54 -6
- package/dist/index.cjs +315 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +152 -5
- package/dist/index.d.ts +152 -5
- package/dist/index.js +300 -17
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
# @dev-dga/react
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Breaking Changes
|
|
6
|
+
|
|
7
|
+
- **`DgaContextValue.rootRef` (RefObject) → `rootEl` (`HTMLElement | null`).** The `useDga()` return shape changed: `rootRef.current` is now `rootEl` directly. Callers reading `useDga().rootRef` will see a TypeScript error. Reason: the previous `useRef`-based exposure had a race — `useRef` doesn't trigger re-renders when the element mounts, so portal-rendering components reading `rootRef.current` raced to `<body>` on the first commit. The new state-backed callback ref triggers a re-render once the element is available. Pre-1.0 release; almost certainly no external consumers existed.
|
|
8
|
+
|
|
9
|
+
### Minor Changes
|
|
10
|
+
|
|
11
|
+
- **Theming API — `theme` prop on `<DgaProvider>`.** Accepts a `DgaTheme` (from `@dev-dga/tokens`'s new `buildTheme()`); memoizes the resulting CSS vars and merges them into the root element's `style`. Three input shapes supported: palette name (`'lavender'`), single CSS color (hover/active derived via `color-mix()` — requires Safari 16.4+), or explicit `{ base, hover, active, foreground? }` triplet. Consumer's manual `style` override still wins (escape hatch preserved):
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
// palette name
|
|
15
|
+
<DgaProvider theme={{ primary: 'lavender' }}>{…}</DgaProvider>
|
|
16
|
+
|
|
17
|
+
// single hex (derives hover + active)
|
|
18
|
+
<DgaProvider theme={{ primary: '#7C3AED' }}>{…}</DgaProvider>
|
|
19
|
+
|
|
20
|
+
// explicit triplet
|
|
21
|
+
<DgaProvider theme={{ primary: { base: '#A', hover: '#B', active: '#C', foreground: '#D' } }}>
|
|
22
|
+
{…}
|
|
23
|
+
</DgaProvider>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Theme types re-exported from `@dev-dga/react`: `DgaTheme`, `PaletteName`, `ThemeColor`.
|
|
27
|
+
|
|
28
|
+
- **Public field primitive — `useFieldA11y` + `FieldMessage`.** Promoted from `internal/` to the public surface. The same primitive every shipped form control uses; lets consumers build custom fields (date picker, file upload, combobox) with the library's id generation, helper/error precedence, ARIA wiring, and dev-time accessible-name warning. Exports: `useFieldA11y`, `FieldMessage`, `UseFieldA11yOptions`, `FieldA11y`, `FieldMessageProps`.
|
|
29
|
+
|
|
30
|
+
- **Three new components on the field primitive.** Each ships with tests, an autodocs story (EN + RTL/AR copy), and per-component CSS in `@dev-dga/css`:
|
|
31
|
+
- **`RadioGroup` + `Radio`** — Radix RadioGroup. Compound shape with `label`/`helperText`/`error`/`errorMessage`/`size`/`orientation` on the group; size + error cascade from group to items via CSS. Group label associated via `aria-labelledby`.
|
|
32
|
+
- **`Switch`** — single boolean. Same `useFieldA11y` wiring as Checkbox.
|
|
33
|
+
- **`Select` + `SelectItem`** — Radix Select. Closed shape — Trigger + Portal + Content + Viewport rendered internally; consumers compose with `<SelectItem>` children. Trigger height matches `Input` (32/36) so triggers + text inputs align in form rows. Content panel width matches trigger via `--radix-select-trigger-width`.
|
|
34
|
+
|
|
35
|
+
- **`asChild` composition on Button (Radix Slot).** New `asChild?: boolean` prop. When true, renders via `SlotPrimitive.Slot` with `Slottable` wrapping `children` so icons land as siblings inside the consumer's element. Unblocks router-link composition without invalid `<button><a>` nesting:
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
<Button asChild>
|
|
39
|
+
<Link href="/about">About</Link>
|
|
40
|
+
</Button>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
In Slot mode the `type` and native `disabled` attributes are dropped (no effect on non-form-controls); the disabled state still applies via `aria-disabled` + `tabIndex={-1}`. `@dev-dga/css` matches `[aria-disabled='true']` alongside `:disabled` so the visual disabled state works on any rendered element. Convention set for future visual components (Card, Badge, Avatar, Alert, …); form-control components that already wrap Radix primitives skip `asChild` — the primitive handles Slot internally.
|
|
44
|
+
|
|
45
|
+
- **Select dropdown anchored to the DgaProvider root for theme + dark-mode inheritance.** Radix Portal defaults to `<body>`, which lives above the `DgaProvider` root in the DOM tree — `data-theme`, custom theme vars set via the new `theme` prop, and `.ddga-theme-*` classes set on the root never reached the dropdown. Select now re-anchors via `<Select.Portal container={ctx.rootEl}>`. Same pattern documented in `DgaContext.ts` for future portal-using components (Tooltip / Modal / Toast / Popover / DropdownMenu).
|
|
46
|
+
|
|
47
|
+
### Patch Changes
|
|
48
|
+
|
|
49
|
+
- **`errorMessage` alone now sets `aria-invalid` and renders the message.** Previously, `useFieldA11y` (and the form components that use it) gated rendering on `error: true`, so passing `errorMessage="…"` without `error` was a silent no-op — a footgun. `hasError` is now derived as `error || isPresent(errorMessage)`. The `error` boolean is still useful for the message-less invalid case (form-level validation marking the field invalid without per-field copy). Backward-compatible for callers passing both `error` + `errorMessage`.
|
|
50
|
+
|
|
3
51
|
## 0.2.0
|
|
4
52
|
|
|
5
53
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
React 19 components for the **DGA (Digital Government Authority)** design system , Saudi Arabia's national reference for government digital platforms.
|
|
4
4
|
|
|
5
|
-
Accessible (WCAG 2.2 AA), RTL-native, dark-mode ready. **Ships no CSS** , pair with `@dev-dga/css`.
|
|
5
|
+
Accessible (WCAG 2.2 AA), RTL-native, dark-mode ready, themable. **Ships no CSS** , pair with `@dev-dga/css`.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -16,29 +16,77 @@ Requires `react@^19` and `react-dom@^19` (peer dependencies).
|
|
|
16
16
|
|
|
17
17
|
```tsx
|
|
18
18
|
import '@dev-dga/css'; // required , components ship no styles
|
|
19
|
-
import { DgaProvider, Button, Input,
|
|
19
|
+
import { DgaProvider, Button, Input, Select, SelectItem, Switch } from '@dev-dga/react';
|
|
20
20
|
|
|
21
21
|
export default function App() {
|
|
22
22
|
return (
|
|
23
23
|
<DgaProvider>
|
|
24
|
-
<Button>Hello</Button>
|
|
25
24
|
<Input label="Email" type="email" helperText="We'll never share it." />
|
|
25
|
+
<Select label="Country" placeholder="Choose…">
|
|
26
|
+
<SelectItem value="sa">Saudi Arabia</SelectItem>
|
|
27
|
+
<SelectItem value="ae">United Arab Emirates</SelectItem>
|
|
28
|
+
</Select>
|
|
29
|
+
<Switch label="Subscribe to the newsletter" />
|
|
30
|
+
<Button>Submit</Button>
|
|
26
31
|
</DgaProvider>
|
|
27
32
|
);
|
|
28
33
|
}
|
|
29
34
|
```
|
|
30
35
|
|
|
31
|
-
For RTL
|
|
36
|
+
For RTL, dark mode, or a brand color, configure the provider:
|
|
32
37
|
|
|
33
38
|
```tsx
|
|
34
|
-
<DgaProvider dir="rtl" mode="dark">
|
|
39
|
+
<DgaProvider dir="rtl" mode="dark" theme={{ primary: 'lavender' }}>
|
|
35
40
|
{/* … */}
|
|
36
41
|
</DgaProvider>
|
|
37
42
|
```
|
|
38
43
|
|
|
44
|
+
## Compose with router links (`asChild`)
|
|
45
|
+
|
|
46
|
+
Visual components support `asChild` so you can render them as your router's `Link` (Next.js, React Router, TanStack Router, …) without invalid `<button><a>` nesting:
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
<Button asChild>
|
|
50
|
+
<Link href="/about">About</Link>
|
|
51
|
+
</Button>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Build your own field
|
|
55
|
+
|
|
56
|
+
`useFieldA11y` + `FieldMessage` are public , the same primitives every shipped form control uses. Build a custom field (date picker, file upload, combobox) with the library's a11y wiring, helper/error precedence, and dev-time warnings:
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { useFieldA11y, FieldMessage } from '@dev-dga/react';
|
|
60
|
+
|
|
61
|
+
function MyField({ label, helperText, error, errorMessage, ...rest }) {
|
|
62
|
+
const { fieldId, errorId, helperId, hasError, hasErrorMessage, hasHelper, controlProps } =
|
|
63
|
+
useFieldA11y({ name: 'MyField', label, error, errorMessage, helperText });
|
|
64
|
+
return (
|
|
65
|
+
<div className="ddga-field">
|
|
66
|
+
{label && <label htmlFor={fieldId}>{label}</label>}
|
|
67
|
+
<input {...controlProps} {...rest} />
|
|
68
|
+
{hasErrorMessage && (
|
|
69
|
+
<FieldMessage id={errorId} variant="error">
|
|
70
|
+
{errorMessage}
|
|
71
|
+
</FieldMessage>
|
|
72
|
+
)}
|
|
73
|
+
{hasHelper && (
|
|
74
|
+
<FieldMessage id={helperId} variant="helper">
|
|
75
|
+
{helperText}
|
|
76
|
+
</FieldMessage>
|
|
77
|
+
)}
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
39
83
|
## Components
|
|
40
84
|
|
|
41
|
-
`Button` · `Input` · `Textarea` · `Checkbox` · `
|
|
85
|
+
**Form:** `Button` · `Input` · `Textarea` · `Checkbox` · `RadioGroup` + `Radio` · `Switch` · `Select` + `SelectItem`
|
|
86
|
+
|
|
87
|
+
**Primitives:** `DgaProvider` · `useDga` · `useDir` · `useFieldA11y` · `FieldMessage` · `cn`
|
|
88
|
+
|
|
89
|
+
**Theming types:** `DgaTheme` · `PaletteName` · `ThemeColor`
|
|
42
90
|
|
|
43
91
|
## Docs
|
|
44
92
|
|
package/dist/index.cjs
CHANGED
|
@@ -23,15 +23,26 @@ __export(src_exports, {
|
|
|
23
23
|
Button: () => Button,
|
|
24
24
|
Checkbox: () => Checkbox,
|
|
25
25
|
DgaProvider: () => DgaProvider,
|
|
26
|
+
FieldMessage: () => FieldMessage,
|
|
26
27
|
Input: () => Input,
|
|
28
|
+
Radio: () => Radio,
|
|
29
|
+
RadioGroup: () => RadioGroup,
|
|
30
|
+
Select: () => Select,
|
|
31
|
+
SelectItem: () => SelectItem,
|
|
32
|
+
Switch: () => Switch,
|
|
27
33
|
Textarea: () => Textarea,
|
|
28
34
|
buttonVariants: () => buttonVariants,
|
|
29
35
|
checkboxVariants: () => checkboxVariants,
|
|
30
36
|
cn: () => cn,
|
|
31
37
|
inputVariants: () => inputVariants,
|
|
38
|
+
radioGroupVariants: () => radioGroupVariants,
|
|
39
|
+
radioVariants: () => radioVariants,
|
|
40
|
+
selectTriggerVariants: () => selectTriggerVariants,
|
|
41
|
+
switchVariants: () => switchVariants,
|
|
32
42
|
textareaVariants: () => textareaVariants,
|
|
33
43
|
useDga: () => useDga,
|
|
34
|
-
useDir: () => useDir
|
|
44
|
+
useDir: () => useDir,
|
|
45
|
+
useFieldA11y: () => useFieldA11y
|
|
35
46
|
});
|
|
36
47
|
module.exports = __toCommonJS(src_exports);
|
|
37
48
|
|
|
@@ -102,6 +113,24 @@ function Minus(props) {
|
|
|
102
113
|
}
|
|
103
114
|
);
|
|
104
115
|
}
|
|
116
|
+
function ChevronDown(props) {
|
|
117
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
118
|
+
"svg",
|
|
119
|
+
{
|
|
120
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
121
|
+
width: "1em",
|
|
122
|
+
height: "1em",
|
|
123
|
+
viewBox: "0 0 24 24",
|
|
124
|
+
fill: "none",
|
|
125
|
+
stroke: "currentColor",
|
|
126
|
+
strokeWidth: "2",
|
|
127
|
+
strokeLinecap: "round",
|
|
128
|
+
strokeLinejoin: "round",
|
|
129
|
+
...props,
|
|
130
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m6 9 6 6 6-6" })
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
}
|
|
105
134
|
|
|
106
135
|
// src/components/Button/Button.tsx
|
|
107
136
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
@@ -180,7 +209,7 @@ function Button({
|
|
|
180
209
|
// src/components/Input/Input.tsx
|
|
181
210
|
var import_class_variance_authority2 = require("class-variance-authority");
|
|
182
211
|
|
|
183
|
-
// src/
|
|
212
|
+
// src/field/use-field-a11y.ts
|
|
184
213
|
var import_react2 = require("react");
|
|
185
214
|
function isPresent(value) {
|
|
186
215
|
return value != null && value !== "";
|
|
@@ -190,7 +219,7 @@ function useFieldA11y(options) {
|
|
|
190
219
|
const fieldId = options.id ?? generatedId;
|
|
191
220
|
const helperId = `${fieldId}-helper`;
|
|
192
221
|
const errorId = `${fieldId}-error`;
|
|
193
|
-
const hasError = !!options.error;
|
|
222
|
+
const hasError = !!options.error || isPresent(options.errorMessage);
|
|
194
223
|
const hasErrorMessage = hasError && isPresent(options.errorMessage);
|
|
195
224
|
const hasHelper = !hasErrorMessage && isPresent(options.helperText);
|
|
196
225
|
if (process.env.NODE_ENV === "development" && !options.label) {
|
|
@@ -215,7 +244,7 @@ function useFieldA11y(options) {
|
|
|
215
244
|
};
|
|
216
245
|
}
|
|
217
246
|
|
|
218
|
-
// src/
|
|
247
|
+
// src/field/FieldMessage.tsx
|
|
219
248
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
220
249
|
function FieldMessage({ id, variant, children }) {
|
|
221
250
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -456,52 +485,306 @@ function Checkbox({
|
|
|
456
485
|
] });
|
|
457
486
|
}
|
|
458
487
|
|
|
459
|
-
// src/
|
|
460
|
-
var
|
|
488
|
+
// src/components/Radio/Radio.tsx
|
|
489
|
+
var import_react3 = require("react");
|
|
461
490
|
var import_radix_ui2 = require("radix-ui");
|
|
491
|
+
var import_class_variance_authority5 = require("class-variance-authority");
|
|
492
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
493
|
+
var radioGroupVariants = (0, import_class_variance_authority5.cva)("ddga-radio-group", {
|
|
494
|
+
variants: {
|
|
495
|
+
size: {
|
|
496
|
+
sm: "ddga-radio-group--sm",
|
|
497
|
+
md: "ddga-radio-group--md"
|
|
498
|
+
},
|
|
499
|
+
orientation: {
|
|
500
|
+
vertical: "ddga-radio-group--vertical",
|
|
501
|
+
horizontal: "ddga-radio-group--horizontal"
|
|
502
|
+
},
|
|
503
|
+
error: {
|
|
504
|
+
true: "ddga-radio-group--error"
|
|
505
|
+
}
|
|
506
|
+
},
|
|
507
|
+
defaultVariants: {
|
|
508
|
+
size: "md",
|
|
509
|
+
orientation: "vertical"
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
var radioVariants = (0, import_class_variance_authority5.cva)("ddga-radio");
|
|
513
|
+
function RadioGroup({
|
|
514
|
+
id: externalId,
|
|
515
|
+
label,
|
|
516
|
+
helperText,
|
|
517
|
+
errorMessage,
|
|
518
|
+
error,
|
|
519
|
+
size,
|
|
520
|
+
orientation,
|
|
521
|
+
required,
|
|
522
|
+
className,
|
|
523
|
+
children,
|
|
524
|
+
...props
|
|
525
|
+
}) {
|
|
526
|
+
const { errorId, helperId, hasError, hasErrorMessage, hasHelper, controlProps, fieldId } = useFieldA11y({
|
|
527
|
+
name: "RadioGroup",
|
|
528
|
+
id: externalId,
|
|
529
|
+
label,
|
|
530
|
+
error,
|
|
531
|
+
errorMessage,
|
|
532
|
+
helperText,
|
|
533
|
+
"aria-label": props["aria-label"],
|
|
534
|
+
"aria-labelledby": props["aria-labelledby"]
|
|
535
|
+
});
|
|
536
|
+
const labelId = `${fieldId}-label`;
|
|
537
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { "data-slot": "radio-group-field", className: "ddga-field", children: [
|
|
538
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { id: labelId, className: "ddga-radio-group__label", children: [
|
|
539
|
+
label,
|
|
540
|
+
required && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": "true", className: "ddga-radio-group__required", children: "*" })
|
|
541
|
+
] }),
|
|
542
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
543
|
+
import_radix_ui2.RadioGroup.Root,
|
|
544
|
+
{
|
|
545
|
+
...props,
|
|
546
|
+
"aria-invalid": controlProps["aria-invalid"],
|
|
547
|
+
"aria-describedby": controlProps["aria-describedby"],
|
|
548
|
+
"aria-labelledby": label ? labelId : props["aria-labelledby"],
|
|
549
|
+
orientation: orientation === "horizontal" ? "horizontal" : "vertical",
|
|
550
|
+
required,
|
|
551
|
+
"data-slot": "radio-group",
|
|
552
|
+
className: cn(radioGroupVariants({ size, orientation, error: hasError }), className),
|
|
553
|
+
children
|
|
554
|
+
}
|
|
555
|
+
),
|
|
556
|
+
hasErrorMessage && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FieldMessage, { id: errorId, variant: "error", children: errorMessage }),
|
|
557
|
+
hasHelper && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FieldMessage, { id: helperId, variant: "helper", children: helperText })
|
|
558
|
+
] });
|
|
559
|
+
}
|
|
560
|
+
function Radio({ id: externalId, label, className, ...props }) {
|
|
561
|
+
const generatedId = (0, import_react3.useId)();
|
|
562
|
+
const itemId = externalId ?? generatedId;
|
|
563
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ddga-radio-row", children: [
|
|
564
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
565
|
+
import_radix_ui2.RadioGroup.Item,
|
|
566
|
+
{
|
|
567
|
+
...props,
|
|
568
|
+
id: itemId,
|
|
569
|
+
"data-slot": "radio",
|
|
570
|
+
className: cn(radioVariants(), className),
|
|
571
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
572
|
+
import_radix_ui2.RadioGroup.Indicator,
|
|
573
|
+
{
|
|
574
|
+
"data-slot": "radio-indicator",
|
|
575
|
+
className: "ddga-radio__indicator",
|
|
576
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ddga-radio__dot", "aria-hidden": "true" })
|
|
577
|
+
}
|
|
578
|
+
)
|
|
579
|
+
}
|
|
580
|
+
),
|
|
581
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { htmlFor: itemId, className: "ddga-radio__label", children: label })
|
|
582
|
+
] });
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// src/components/Switch/Switch.tsx
|
|
586
|
+
var import_radix_ui3 = require("radix-ui");
|
|
587
|
+
var import_class_variance_authority6 = require("class-variance-authority");
|
|
588
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
589
|
+
var switchVariants = (0, import_class_variance_authority6.cva)("ddga-switch", {
|
|
590
|
+
variants: {
|
|
591
|
+
size: {
|
|
592
|
+
sm: "ddga-switch--sm",
|
|
593
|
+
md: "ddga-switch--md"
|
|
594
|
+
},
|
|
595
|
+
error: {
|
|
596
|
+
true: "ddga-switch--error"
|
|
597
|
+
}
|
|
598
|
+
},
|
|
599
|
+
defaultVariants: {
|
|
600
|
+
size: "md"
|
|
601
|
+
}
|
|
602
|
+
});
|
|
603
|
+
function Switch({
|
|
604
|
+
id: externalId,
|
|
605
|
+
label,
|
|
606
|
+
helperText,
|
|
607
|
+
errorMessage,
|
|
608
|
+
error,
|
|
609
|
+
size,
|
|
610
|
+
required,
|
|
611
|
+
className,
|
|
612
|
+
...props
|
|
613
|
+
}) {
|
|
614
|
+
const { fieldId, errorId, helperId, hasError, hasErrorMessage, hasHelper, controlProps } = useFieldA11y({
|
|
615
|
+
name: "Switch",
|
|
616
|
+
id: externalId,
|
|
617
|
+
label,
|
|
618
|
+
error,
|
|
619
|
+
errorMessage,
|
|
620
|
+
helperText,
|
|
621
|
+
"aria-label": props["aria-label"],
|
|
622
|
+
"aria-labelledby": props["aria-labelledby"]
|
|
623
|
+
});
|
|
624
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { "data-slot": "switch-field", className: "ddga-field", children: [
|
|
625
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "ddga-switch-row", children: [
|
|
626
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
627
|
+
import_radix_ui3.Switch.Root,
|
|
628
|
+
{
|
|
629
|
+
...props,
|
|
630
|
+
...controlProps,
|
|
631
|
+
"data-slot": "switch",
|
|
632
|
+
required,
|
|
633
|
+
className: cn(switchVariants({ size, error: hasError }), className),
|
|
634
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_radix_ui3.Switch.Thumb, { "data-slot": "switch-thumb", className: "ddga-switch__thumb" })
|
|
635
|
+
}
|
|
636
|
+
),
|
|
637
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { htmlFor: fieldId, className: "ddga-switch__label", children: [
|
|
638
|
+
label,
|
|
639
|
+
required && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "aria-hidden": "true", className: "ddga-switch__required", children: "*" })
|
|
640
|
+
] })
|
|
641
|
+
] }),
|
|
642
|
+
hasErrorMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FieldMessage, { id: errorId, variant: "error", children: errorMessage }),
|
|
643
|
+
hasHelper && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FieldMessage, { id: helperId, variant: "helper", children: helperText })
|
|
644
|
+
] });
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
// src/components/Select/Select.tsx
|
|
648
|
+
var import_react5 = require("react");
|
|
649
|
+
var import_radix_ui4 = require("radix-ui");
|
|
650
|
+
var import_class_variance_authority7 = require("class-variance-authority");
|
|
462
651
|
|
|
463
652
|
// src/providers/DgaContext.ts
|
|
464
|
-
var
|
|
465
|
-
var DgaContext = (0,
|
|
653
|
+
var import_react4 = require("react");
|
|
654
|
+
var DgaContext = (0, import_react4.createContext)(null);
|
|
466
655
|
function useDga() {
|
|
467
|
-
const ctx = (0,
|
|
656
|
+
const ctx = (0, import_react4.useContext)(DgaContext);
|
|
468
657
|
if (!ctx) {
|
|
469
658
|
throw new Error("useDga must be used within a <DgaProvider>");
|
|
470
659
|
}
|
|
471
660
|
return ctx;
|
|
472
661
|
}
|
|
473
662
|
|
|
663
|
+
// src/components/Select/Select.tsx
|
|
664
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
665
|
+
var selectTriggerVariants = (0, import_class_variance_authority7.cva)("ddga-select-trigger", {
|
|
666
|
+
variants: {
|
|
667
|
+
size: {
|
|
668
|
+
sm: "ddga-select-trigger--sm",
|
|
669
|
+
md: "ddga-select-trigger--md"
|
|
670
|
+
},
|
|
671
|
+
error: {
|
|
672
|
+
true: "ddga-select-trigger--error"
|
|
673
|
+
}
|
|
674
|
+
},
|
|
675
|
+
defaultVariants: {
|
|
676
|
+
size: "md"
|
|
677
|
+
}
|
|
678
|
+
});
|
|
679
|
+
function Select({
|
|
680
|
+
id: externalId,
|
|
681
|
+
label,
|
|
682
|
+
helperText,
|
|
683
|
+
errorMessage,
|
|
684
|
+
error,
|
|
685
|
+
size,
|
|
686
|
+
required,
|
|
687
|
+
placeholder,
|
|
688
|
+
className,
|
|
689
|
+
children,
|
|
690
|
+
...rootProps
|
|
691
|
+
}) {
|
|
692
|
+
const { fieldId, errorId, helperId, hasError, hasErrorMessage, hasHelper, controlProps } = useFieldA11y({
|
|
693
|
+
name: "Select",
|
|
694
|
+
id: externalId,
|
|
695
|
+
label,
|
|
696
|
+
error,
|
|
697
|
+
errorMessage,
|
|
698
|
+
helperText,
|
|
699
|
+
"aria-label": rootProps["aria-label"],
|
|
700
|
+
"aria-labelledby": rootProps["aria-labelledby"]
|
|
701
|
+
});
|
|
702
|
+
const ctx = (0, import_react5.useContext)(DgaContext);
|
|
703
|
+
const portalContainer = ctx?.rootEl ?? void 0;
|
|
704
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { "data-slot": "select-field", className: "ddga-field", children: [
|
|
705
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { htmlFor: fieldId, className: "ddga-select__label", children: [
|
|
706
|
+
label,
|
|
707
|
+
required && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "aria-hidden": "true", className: "ddga-select__required", children: "*" })
|
|
708
|
+
] }),
|
|
709
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_radix_ui4.Select.Root, { required, ...rootProps, children: [
|
|
710
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
711
|
+
import_radix_ui4.Select.Trigger,
|
|
712
|
+
{
|
|
713
|
+
...controlProps,
|
|
714
|
+
"data-slot": "select-trigger",
|
|
715
|
+
className: cn(selectTriggerVariants({ size, error: hasError }), className),
|
|
716
|
+
children: [
|
|
717
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_radix_ui4.Select.Value, { placeholder }),
|
|
718
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_radix_ui4.Select.Icon, { asChild: true, className: "ddga-select__icon", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ChevronDown, { "aria-hidden": "true" }) })
|
|
719
|
+
]
|
|
720
|
+
}
|
|
721
|
+
),
|
|
722
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_radix_ui4.Select.Portal, { container: portalContainer, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
723
|
+
import_radix_ui4.Select.Content,
|
|
724
|
+
{
|
|
725
|
+
"data-slot": "select-content",
|
|
726
|
+
className: "ddga-select-content",
|
|
727
|
+
position: "popper",
|
|
728
|
+
sideOffset: 4,
|
|
729
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_radix_ui4.Select.Viewport, { className: "ddga-select-viewport", children })
|
|
730
|
+
}
|
|
731
|
+
) })
|
|
732
|
+
] }),
|
|
733
|
+
hasErrorMessage && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(FieldMessage, { id: errorId, variant: "error", children: errorMessage }),
|
|
734
|
+
hasHelper && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(FieldMessage, { id: helperId, variant: "helper", children: helperText })
|
|
735
|
+
] });
|
|
736
|
+
}
|
|
737
|
+
function SelectItem({ className, children, ...props }) {
|
|
738
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
739
|
+
import_radix_ui4.Select.Item,
|
|
740
|
+
{
|
|
741
|
+
...props,
|
|
742
|
+
"data-slot": "select-item",
|
|
743
|
+
className: cn("ddga-select-item", className),
|
|
744
|
+
children: [
|
|
745
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_radix_ui4.Select.ItemText, { children }),
|
|
746
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_radix_ui4.Select.ItemIndicator, { className: "ddga-select-item__indicator", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Check, { className: "ddga-select-item__check", "aria-hidden": "true" }) })
|
|
747
|
+
]
|
|
748
|
+
}
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
|
|
474
752
|
// src/providers/DgaProvider.tsx
|
|
475
|
-
var
|
|
753
|
+
var import_react6 = require("react");
|
|
754
|
+
var import_radix_ui5 = require("radix-ui");
|
|
755
|
+
var import_tokens = require("@dev-dga/tokens");
|
|
756
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
476
757
|
function DgaProvider({
|
|
477
758
|
dir = "ltr",
|
|
478
759
|
locale,
|
|
479
760
|
mode = "light",
|
|
761
|
+
theme,
|
|
480
762
|
as: Component = "div",
|
|
481
763
|
className,
|
|
482
764
|
style: consumerStyle,
|
|
483
765
|
children
|
|
484
766
|
}) {
|
|
485
|
-
const parentCtx = (0,
|
|
767
|
+
const parentCtx = (0, import_react6.useContext)(DgaContext);
|
|
486
768
|
const isNested = parentCtx !== null;
|
|
487
|
-
const
|
|
769
|
+
const [rootEl, setRootEl] = (0, import_react6.useState)(null);
|
|
488
770
|
const resolvedLocale = locale ?? (dir === "rtl" ? "ar" : "en");
|
|
489
|
-
const ctxValue = (0,
|
|
490
|
-
() => ({ dir, locale: resolvedLocale, mode,
|
|
491
|
-
[dir, resolvedLocale, mode]
|
|
771
|
+
const ctxValue = (0, import_react6.useMemo)(
|
|
772
|
+
() => ({ dir, locale: resolvedLocale, mode, rootEl }),
|
|
773
|
+
[dir, resolvedLocale, mode, rootEl]
|
|
492
774
|
);
|
|
493
|
-
const
|
|
494
|
-
|
|
775
|
+
const themeVars = (0, import_react6.useMemo)(() => theme ? (0, import_tokens.buildTheme)(theme) : null, [theme]);
|
|
776
|
+
const inner = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_radix_ui5.Direction.Provider, { dir, children });
|
|
777
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DgaContext.Provider, { value: ctxValue, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
495
778
|
Component,
|
|
496
779
|
{
|
|
497
|
-
ref:
|
|
780
|
+
ref: setRootEl,
|
|
498
781
|
dir,
|
|
499
782
|
lang: resolvedLocale,
|
|
500
783
|
"data-slot": "dga-root",
|
|
501
784
|
"data-theme": mode,
|
|
502
785
|
className,
|
|
503
|
-
style: { colorScheme: mode, ...consumerStyle },
|
|
504
|
-
children: isNested ? inner : /* @__PURE__ */ (0,
|
|
786
|
+
style: { colorScheme: mode, ...themeVars ?? {}, ...consumerStyle },
|
|
787
|
+
children: isNested ? inner : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_radix_ui5.Tooltip.Provider, { delayDuration: 300, skipDelayDuration: 100, children: inner })
|
|
505
788
|
}
|
|
506
789
|
) });
|
|
507
790
|
}
|
|
@@ -515,14 +798,25 @@ function useDir() {
|
|
|
515
798
|
Button,
|
|
516
799
|
Checkbox,
|
|
517
800
|
DgaProvider,
|
|
801
|
+
FieldMessage,
|
|
518
802
|
Input,
|
|
803
|
+
Radio,
|
|
804
|
+
RadioGroup,
|
|
805
|
+
Select,
|
|
806
|
+
SelectItem,
|
|
807
|
+
Switch,
|
|
519
808
|
Textarea,
|
|
520
809
|
buttonVariants,
|
|
521
810
|
checkboxVariants,
|
|
522
811
|
cn,
|
|
523
812
|
inputVariants,
|
|
813
|
+
radioGroupVariants,
|
|
814
|
+
radioVariants,
|
|
815
|
+
selectTriggerVariants,
|
|
816
|
+
switchVariants,
|
|
524
817
|
textareaVariants,
|
|
525
818
|
useDga,
|
|
526
|
-
useDir
|
|
819
|
+
useDir,
|
|
820
|
+
useFieldA11y
|
|
527
821
|
});
|
|
528
822
|
//# sourceMappingURL=index.cjs.map
|