@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/CHANGELOG.md +67 -0
- package/README.md +54 -6
- package/dist/index.cjs +323 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +164 -7
- package/dist/index.d.ts +164 -7
- package/dist/index.js +307 -17
- package/dist/index.js.map +1 -1
- package/package.json +8 -7
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# @dev-dga/react
|
|
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
|
+
|
|
51
|
+
## 0.2.0
|
|
52
|
+
|
|
53
|
+
### Minor Changes
|
|
54
|
+
|
|
55
|
+
- Add `useDir()` hook and wire Radix's `Direction.Provider` into `DgaProvider`.
|
|
56
|
+
- **`useDir(): 'ltr' | 'rtl'`** — public hook returning direction from the nearest `<DgaProvider>`. Throws when used outside a provider. Use this in custom components instead of `useDga().dir` when only direction is needed.
|
|
57
|
+
- **Auto-propagation to Radix portals** — `DgaProvider` now wraps its children in `<Direction.Provider value={dir}>`. Radix primitives that render in portals (Tooltip, Select, Toast, Modal, …) inherit direction from the provider tree instead of falling back to `document.body`'s dir. Future portal-based components will respect the configured direction with no per-component plumbing. **No effect on the four components shipped in this release** (`Button`, `Input`, `Textarea`, `Checkbox`) — none render portals — so this is forward-looking infrastructure, not a behavior change for current consumers. The one edge case: code rendering `radix-ui` portal primitives directly inside a `DgaProvider` will now see them pick up the provider direction (a fix, not a regression).
|
|
58
|
+
|
|
59
|
+
For LTR-locked content inside an RTL page (Saudi phone numbers, IBANs, National IDs), use the native `dir="ltr"` attribute plus the appropriate `inputMode` on `<Input>` directly — no new component required. See the `Foundations/RTL` Storybook page for examples.
|
|
60
|
+
|
|
61
|
+
## 0.1.1
|
|
62
|
+
|
|
63
|
+
- Per-package README and metadata polish.
|
|
64
|
+
|
|
65
|
+
## 0.1.0
|
|
66
|
+
|
|
67
|
+
- Initial release: `Button`, `Input`, `Textarea`, `Checkbox`, `DgaProvider`, `useDga`, `cn`. React 19, ref-as-prop, `cva` variants, BEM `ddga-*` classes resolving `var(--ddga-*)`.
|
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,14 +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
|
-
useDga: () => useDga
|
|
43
|
+
useDga: () => useDga,
|
|
44
|
+
useDir: () => useDir,
|
|
45
|
+
useFieldA11y: () => useFieldA11y
|
|
34
46
|
});
|
|
35
47
|
module.exports = __toCommonJS(src_exports);
|
|
36
48
|
|
|
@@ -101,6 +113,24 @@ function Minus(props) {
|
|
|
101
113
|
}
|
|
102
114
|
);
|
|
103
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
|
+
}
|
|
104
134
|
|
|
105
135
|
// src/components/Button/Button.tsx
|
|
106
136
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
@@ -179,7 +209,7 @@ function Button({
|
|
|
179
209
|
// src/components/Input/Input.tsx
|
|
180
210
|
var import_class_variance_authority2 = require("class-variance-authority");
|
|
181
211
|
|
|
182
|
-
// src/
|
|
212
|
+
// src/field/use-field-a11y.ts
|
|
183
213
|
var import_react2 = require("react");
|
|
184
214
|
function isPresent(value) {
|
|
185
215
|
return value != null && value !== "";
|
|
@@ -189,7 +219,7 @@ function useFieldA11y(options) {
|
|
|
189
219
|
const fieldId = options.id ?? generatedId;
|
|
190
220
|
const helperId = `${fieldId}-helper`;
|
|
191
221
|
const errorId = `${fieldId}-error`;
|
|
192
|
-
const hasError = !!options.error;
|
|
222
|
+
const hasError = !!options.error || isPresent(options.errorMessage);
|
|
193
223
|
const hasErrorMessage = hasError && isPresent(options.errorMessage);
|
|
194
224
|
const hasHelper = !hasErrorMessage && isPresent(options.helperText);
|
|
195
225
|
if (process.env.NODE_ENV === "development" && !options.label) {
|
|
@@ -214,7 +244,7 @@ function useFieldA11y(options) {
|
|
|
214
244
|
};
|
|
215
245
|
}
|
|
216
246
|
|
|
217
|
-
// src/
|
|
247
|
+
// src/field/FieldMessage.tsx
|
|
218
248
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
219
249
|
function FieldMessage({ id, variant, children }) {
|
|
220
250
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -328,7 +358,7 @@ var textareaVariants = (0, import_class_variance_authority3.cva)("ddga-textarea"
|
|
|
328
358
|
true: "ddga-textarea--error"
|
|
329
359
|
},
|
|
330
360
|
// Horizontal/both resize breaks form layout (same reason it's not the
|
|
331
|
-
// default)
|
|
361
|
+
// default) , only vertical or locked are offered.
|
|
332
362
|
resize: {
|
|
333
363
|
vertical: "ddga-textarea--resize-vertical",
|
|
334
364
|
none: "ddga-textarea--resize-none"
|
|
@@ -455,66 +485,338 @@ function Checkbox({
|
|
|
455
485
|
] });
|
|
456
486
|
}
|
|
457
487
|
|
|
458
|
-
// src/
|
|
459
|
-
var
|
|
488
|
+
// src/components/Radio/Radio.tsx
|
|
489
|
+
var import_react3 = require("react");
|
|
460
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");
|
|
461
651
|
|
|
462
652
|
// src/providers/DgaContext.ts
|
|
463
|
-
var
|
|
464
|
-
var DgaContext = (0,
|
|
653
|
+
var import_react4 = require("react");
|
|
654
|
+
var DgaContext = (0, import_react4.createContext)(null);
|
|
465
655
|
function useDga() {
|
|
466
|
-
const ctx = (0,
|
|
656
|
+
const ctx = (0, import_react4.useContext)(DgaContext);
|
|
467
657
|
if (!ctx) {
|
|
468
658
|
throw new Error("useDga must be used within a <DgaProvider>");
|
|
469
659
|
}
|
|
470
660
|
return ctx;
|
|
471
661
|
}
|
|
472
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
|
+
|
|
473
752
|
// src/providers/DgaProvider.tsx
|
|
474
|
-
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");
|
|
475
757
|
function DgaProvider({
|
|
476
758
|
dir = "ltr",
|
|
477
759
|
locale,
|
|
478
760
|
mode = "light",
|
|
761
|
+
theme,
|
|
479
762
|
as: Component = "div",
|
|
480
763
|
className,
|
|
481
764
|
style: consumerStyle,
|
|
482
765
|
children
|
|
483
766
|
}) {
|
|
484
|
-
const parentCtx = (0,
|
|
767
|
+
const parentCtx = (0, import_react6.useContext)(DgaContext);
|
|
485
768
|
const isNested = parentCtx !== null;
|
|
486
|
-
const
|
|
769
|
+
const [rootEl, setRootEl] = (0, import_react6.useState)(null);
|
|
487
770
|
const resolvedLocale = locale ?? (dir === "rtl" ? "ar" : "en");
|
|
488
|
-
const ctxValue = (0,
|
|
489
|
-
() => ({ dir, locale: resolvedLocale, mode,
|
|
490
|
-
[dir, resolvedLocale, mode]
|
|
771
|
+
const ctxValue = (0, import_react6.useMemo)(
|
|
772
|
+
() => ({ dir, locale: resolvedLocale, mode, rootEl }),
|
|
773
|
+
[dir, resolvedLocale, mode, rootEl]
|
|
491
774
|
);
|
|
492
|
-
|
|
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)(
|
|
493
778
|
Component,
|
|
494
779
|
{
|
|
495
|
-
ref:
|
|
780
|
+
ref: setRootEl,
|
|
496
781
|
dir,
|
|
497
782
|
lang: resolvedLocale,
|
|
498
783
|
"data-slot": "dga-root",
|
|
499
784
|
"data-theme": mode,
|
|
500
785
|
className,
|
|
501
|
-
style: { colorScheme: mode, ...consumerStyle },
|
|
502
|
-
children: isNested ?
|
|
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 })
|
|
503
788
|
}
|
|
504
789
|
) });
|
|
505
790
|
}
|
|
791
|
+
|
|
792
|
+
// src/hooks/useDir.ts
|
|
793
|
+
function useDir() {
|
|
794
|
+
return useDga().dir;
|
|
795
|
+
}
|
|
506
796
|
// Annotate the CommonJS export names for ESM import in node:
|
|
507
797
|
0 && (module.exports = {
|
|
508
798
|
Button,
|
|
509
799
|
Checkbox,
|
|
510
800
|
DgaProvider,
|
|
801
|
+
FieldMessage,
|
|
511
802
|
Input,
|
|
803
|
+
Radio,
|
|
804
|
+
RadioGroup,
|
|
805
|
+
Select,
|
|
806
|
+
SelectItem,
|
|
807
|
+
Switch,
|
|
512
808
|
Textarea,
|
|
513
809
|
buttonVariants,
|
|
514
810
|
checkboxVariants,
|
|
515
811
|
cn,
|
|
516
812
|
inputVariants,
|
|
813
|
+
radioGroupVariants,
|
|
814
|
+
radioVariants,
|
|
815
|
+
selectTriggerVariants,
|
|
816
|
+
switchVariants,
|
|
517
817
|
textareaVariants,
|
|
518
|
-
useDga
|
|
818
|
+
useDga,
|
|
819
|
+
useDir,
|
|
820
|
+
useFieldA11y
|
|
519
821
|
});
|
|
520
822
|
//# sourceMappingURL=index.cjs.map
|