@edux-design/forms 0.0.8 → 0.0.9

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.mts CHANGED
@@ -1,4 +1,3 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
1
  import * as react from 'react';
3
2
 
4
3
  declare function Label({ children, hint, description, ...props }: {
@@ -57,7 +56,29 @@ type InputProps = React.InputHTMLAttributes<HTMLInputElement> & {
57
56
  }) => void;
58
57
  };
59
58
 
60
- declare function Radio(): react_jsx_runtime.JSX.Element;
59
+ /**
60
+ * Minimal radio control wired to the surrounding Field context.
61
+ *
62
+ * @typedef {React.InputHTMLAttributes<HTMLInputElement> & {
63
+ * className?: string,
64
+ * }} RadioProps
65
+ */
66
+ /**
67
+ * Radio component.
68
+ *
69
+ * Provides a styled radio input that integrates with the Field context and
70
+ * supports both controlled (`checked`) and uncontrolled (`defaultChecked`) use.
71
+ *
72
+ * @component
73
+ * @type {React.ForwardRefExoticComponent<RadioProps & React.RefAttributes<HTMLInputElement>>}
74
+ */
75
+ declare const Radio: React.ForwardRefExoticComponent<RadioProps & React.RefAttributes<HTMLInputElement>>;
76
+ /**
77
+ * Minimal radio control wired to the surrounding Field context.
78
+ */
79
+ type RadioProps = React.InputHTMLAttributes<HTMLInputElement> & {
80
+ className?: string;
81
+ };
61
82
 
62
83
  declare const Checkbox: react.ForwardRefExoticComponent<react.RefAttributes<any>>;
63
84
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
1
  import * as react from 'react';
3
2
 
4
3
  declare function Label({ children, hint, description, ...props }: {
@@ -57,7 +56,29 @@ type InputProps = React.InputHTMLAttributes<HTMLInputElement> & {
57
56
  }) => void;
58
57
  };
59
58
 
60
- declare function Radio(): react_jsx_runtime.JSX.Element;
59
+ /**
60
+ * Minimal radio control wired to the surrounding Field context.
61
+ *
62
+ * @typedef {React.InputHTMLAttributes<HTMLInputElement> & {
63
+ * className?: string,
64
+ * }} RadioProps
65
+ */
66
+ /**
67
+ * Radio component.
68
+ *
69
+ * Provides a styled radio input that integrates with the Field context and
70
+ * supports both controlled (`checked`) and uncontrolled (`defaultChecked`) use.
71
+ *
72
+ * @component
73
+ * @type {React.ForwardRefExoticComponent<RadioProps & React.RefAttributes<HTMLInputElement>>}
74
+ */
75
+ declare const Radio: React.ForwardRefExoticComponent<RadioProps & React.RefAttributes<HTMLInputElement>>;
76
+ /**
77
+ * Minimal radio control wired to the surrounding Field context.
78
+ */
79
+ type RadioProps = React.InputHTMLAttributes<HTMLInputElement> & {
80
+ className?: string;
81
+ };
61
82
 
62
83
  declare const Checkbox: react.ForwardRefExoticComponent<react.RefAttributes<any>>;
63
84
 
package/dist/index.js CHANGED
@@ -283,34 +283,76 @@ Field.Feedback = Feedback;
283
283
  var import_react6 = __toESM(require("react"));
284
284
  var import_utils3 = require("@edux-design/utils");
285
285
  var import_jsx_runtime5 = require("react/jsx-runtime");
286
- function Radio() {
287
- const { labelHTMLForId } = useFieldContext();
288
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative inline-flex items-center justify-center", children: [
289
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
290
- "input",
291
- {
292
- id: labelHTMLForId,
293
- type: "radio",
294
- className: (0, import_utils3.cx)(
295
- "peer absolute inset-0 z-10 cursor-pointer appearance-none rounded-full",
296
- "focus:shadow-focus focus-visible:shadow-focus focus:outline-none focus-visible:outline-none"
297
- )
298
- }
299
- ),
300
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
301
- "span",
286
+ var Radio = (0, import_react6.forwardRef)(
287
+ ({
288
+ className,
289
+ id: providedId,
290
+ checked,
291
+ defaultChecked,
292
+ disabled,
293
+ onChange,
294
+ ...rest
295
+ }, ref) => {
296
+ const {
297
+ ["aria-describedby"]: ariaDescribedByProp,
298
+ ...inputProps
299
+ } = rest;
300
+ const { labelHTMLForId, describedByIds = [] } = useFieldContext();
301
+ const resolvedId = providedId ?? labelHTMLForId;
302
+ const isControlled = checked !== void 0;
303
+ const isDisabled = Boolean(disabled);
304
+ const describedByTokens = [
305
+ ...describedByIds,
306
+ ...ariaDescribedByProp ? ariaDescribedByProp.split(" ") : []
307
+ ].filter(Boolean);
308
+ const ariaDescribedBy = describedByTokens.length ? describedByTokens.join(" ") : void 0;
309
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
310
+ "div",
302
311
  {
303
312
  className: (0, import_utils3.cx)(
304
- "block rounded-full border-1 border-border-base",
305
- "h-[28px] w-[28px]",
306
- "peer-checked:border-border-primary-base peer-checked:border-8",
307
- "transition-colors",
308
- "peer-hover:border-2 peer-hover:border-border-primary-base peer-checked:peer-hover:border-8 peer-checked:peer-hover:border-border-primary-base"
309
- )
313
+ "relative inline-flex h-[28px] w-[28px] items-center justify-center",
314
+ className
315
+ ),
316
+ children: [
317
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
318
+ "input",
319
+ {
320
+ id: resolvedId,
321
+ ref,
322
+ type: "radio",
323
+ className: (0, import_utils3.cx)(
324
+ "peer absolute inset-0 h-full w-full cursor-pointer appearance-none rounded-full bg-transparent",
325
+ "focus:shadow-focus focus-visible:shadow-focus focus:outline-none focus-visible:outline-none",
326
+ isDisabled && "cursor-not-allowed"
327
+ ),
328
+ "aria-describedby": ariaDescribedBy,
329
+ "aria-disabled": isDisabled ? "true" : void 0,
330
+ disabled: isDisabled,
331
+ checked: isControlled ? checked : void 0,
332
+ defaultChecked: !isControlled ? defaultChecked : void 0,
333
+ onChange,
334
+ ...inputProps
335
+ }
336
+ ),
337
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
338
+ "span",
339
+ {
340
+ "aria-hidden": "true",
341
+ "data-slot": "radio-control",
342
+ className: (0, import_utils3.cx)(
343
+ "block h-full w-full rounded-full border-2 border-border-base transition-colors",
344
+ "peer-checked:border-border-primary-base peer-checked:border-[8px]",
345
+ "peer-hover:border-2 peer-hover:border-border-primary-base peer-checked:peer-hover:border-[8px] peer-checked:peer-hover:border-border-primary-base",
346
+ "peer-disabled:border-border-subtle peer-disabled:bg-bg-inactive"
347
+ )
348
+ }
349
+ )
350
+ ]
310
351
  }
311
- )
312
- ] });
313
- }
352
+ );
353
+ }
354
+ );
355
+ Radio.displayName = "Radio";
314
356
 
315
357
  // src/elements/Checkbox.jsx
316
358
  var import_react7 = __toESM(require("react"));
@@ -591,6 +633,7 @@ var Switch = (0, import_react8.forwardRef)(
591
633
  disabled,
592
634
  id: providedId,
593
635
  checked,
636
+ defaultChecked = false,
594
637
  onChange,
595
638
  ...rest
596
639
  }, ref) => {
@@ -606,8 +649,11 @@ var Switch = (0, import_react8.forwardRef)(
606
649
  const derivedDisabled = Boolean(disabled);
607
650
  const isInactiveVariant = variant === "inactive";
608
651
  const isDisabled = derivedDisabled || isInactiveVariant;
609
- const [unControlledChecked, setUnControlledChecked] = (0, import_react8.useState)(false);
610
- const isOn = checked ?? unControlledChecked;
652
+ const [unControlledChecked, setUnControlledChecked] = (0, import_react8.useState)(
653
+ () => Boolean(defaultChecked)
654
+ );
655
+ const isControlled = checked !== void 0;
656
+ const isOn = isControlled ? checked : unControlledChecked;
611
657
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
612
658
  "div",
613
659
  {
@@ -621,8 +667,8 @@ var Switch = (0, import_react8.forwardRef)(
621
667
  {
622
668
  id: resolvedId,
623
669
  ref,
624
- onChange: onChange ? onChange : () => setUnControlledChecked(!unControlledChecked),
625
- checked: checked ? checked : unControlledChecked,
670
+ onChange: onChange ? onChange : (event) => setUnControlledChecked(event.target.checked),
671
+ checked: isControlled ? checked : unControlledChecked,
626
672
  type: "checkbox",
627
673
  role: "switch",
628
674
  className: (0, import_utils5.cx)(
@@ -671,12 +717,14 @@ var Switch = (0, import_react8.forwardRef)(
671
717
  import_icons4.Close,
672
718
  {
673
719
  "aria-hidden": "true",
720
+ "data-state": "off",
674
721
  className: (0, import_utils5.cx)("absolute duration-150", intent.offIcon)
675
722
  }
676
723
  ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
677
724
  import_icons4.Check,
678
725
  {
679
726
  "aria-hidden": "true",
727
+ "data-state": "on",
680
728
  className: (0, import_utils5.cx)("absolute duration-150", intent.onIcon)
681
729
  }
682
730
  )
package/dist/index.mjs CHANGED
@@ -242,40 +242,82 @@ function Feedback({ id, tone, children, className, ...rest }) {
242
242
  Field.Feedback = Feedback;
243
243
 
244
244
  // src/elements/Radio.jsx
245
- import React5 from "react";
245
+ import React5, { forwardRef as forwardRef2 } from "react";
246
246
  import { cx as cx3 } from "@edux-design/utils";
247
247
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
248
- function Radio() {
249
- const { labelHTMLForId } = useFieldContext();
250
- return /* @__PURE__ */ jsxs4("div", { className: "relative inline-flex items-center justify-center", children: [
251
- /* @__PURE__ */ jsx5(
252
- "input",
253
- {
254
- id: labelHTMLForId,
255
- type: "radio",
256
- className: cx3(
257
- "peer absolute inset-0 z-10 cursor-pointer appearance-none rounded-full",
258
- "focus:shadow-focus focus-visible:shadow-focus focus:outline-none focus-visible:outline-none"
259
- )
260
- }
261
- ),
262
- /* @__PURE__ */ jsx5(
263
- "span",
248
+ var Radio = forwardRef2(
249
+ ({
250
+ className,
251
+ id: providedId,
252
+ checked,
253
+ defaultChecked,
254
+ disabled,
255
+ onChange,
256
+ ...rest
257
+ }, ref) => {
258
+ const {
259
+ ["aria-describedby"]: ariaDescribedByProp,
260
+ ...inputProps
261
+ } = rest;
262
+ const { labelHTMLForId, describedByIds = [] } = useFieldContext();
263
+ const resolvedId = providedId ?? labelHTMLForId;
264
+ const isControlled = checked !== void 0;
265
+ const isDisabled = Boolean(disabled);
266
+ const describedByTokens = [
267
+ ...describedByIds,
268
+ ...ariaDescribedByProp ? ariaDescribedByProp.split(" ") : []
269
+ ].filter(Boolean);
270
+ const ariaDescribedBy = describedByTokens.length ? describedByTokens.join(" ") : void 0;
271
+ return /* @__PURE__ */ jsxs4(
272
+ "div",
264
273
  {
265
274
  className: cx3(
266
- "block rounded-full border-1 border-border-base",
267
- "h-[28px] w-[28px]",
268
- "peer-checked:border-border-primary-base peer-checked:border-8",
269
- "transition-colors",
270
- "peer-hover:border-2 peer-hover:border-border-primary-base peer-checked:peer-hover:border-8 peer-checked:peer-hover:border-border-primary-base"
271
- )
275
+ "relative inline-flex h-[28px] w-[28px] items-center justify-center",
276
+ className
277
+ ),
278
+ children: [
279
+ /* @__PURE__ */ jsx5(
280
+ "input",
281
+ {
282
+ id: resolvedId,
283
+ ref,
284
+ type: "radio",
285
+ className: cx3(
286
+ "peer absolute inset-0 h-full w-full cursor-pointer appearance-none rounded-full bg-transparent",
287
+ "focus:shadow-focus focus-visible:shadow-focus focus:outline-none focus-visible:outline-none",
288
+ isDisabled && "cursor-not-allowed"
289
+ ),
290
+ "aria-describedby": ariaDescribedBy,
291
+ "aria-disabled": isDisabled ? "true" : void 0,
292
+ disabled: isDisabled,
293
+ checked: isControlled ? checked : void 0,
294
+ defaultChecked: !isControlled ? defaultChecked : void 0,
295
+ onChange,
296
+ ...inputProps
297
+ }
298
+ ),
299
+ /* @__PURE__ */ jsx5(
300
+ "span",
301
+ {
302
+ "aria-hidden": "true",
303
+ "data-slot": "radio-control",
304
+ className: cx3(
305
+ "block h-full w-full rounded-full border-2 border-border-base transition-colors",
306
+ "peer-checked:border-border-primary-base peer-checked:border-[8px]",
307
+ "peer-hover:border-2 peer-hover:border-border-primary-base peer-checked:peer-hover:border-[8px] peer-checked:peer-hover:border-border-primary-base",
308
+ "peer-disabled:border-border-subtle peer-disabled:bg-bg-inactive"
309
+ )
310
+ }
311
+ )
312
+ ]
272
313
  }
273
- )
274
- ] });
275
- }
314
+ );
315
+ }
316
+ );
317
+ Radio.displayName = "Radio";
276
318
 
277
319
  // src/elements/Checkbox.jsx
278
- import React6, { forwardRef as forwardRef2, useCallback as useCallback3, useEffect as useEffect2, useRef } from "react";
320
+ import React6, { forwardRef as forwardRef3, useCallback as useCallback3, useEffect as useEffect2, useRef } from "react";
279
321
  import { cx as cx4 } from "@edux-design/utils";
280
322
  import { Check, Indeterminate, Plus } from "@edux-design/icons";
281
323
  import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
@@ -341,7 +383,7 @@ var VARIANT_INTENTS = {
341
383
  iconColor: "text-fg-inactive"
342
384
  }
343
385
  };
344
- var Checkbox = forwardRef2(
386
+ var Checkbox = forwardRef3(
345
387
  ({
346
388
  className,
347
389
  indeterminate = false,
@@ -480,7 +522,7 @@ var Checkbox = forwardRef2(
480
522
  Checkbox.displayName = "Checkbox";
481
523
 
482
524
  // src/elements/Switch.jsx
483
- import React7, { forwardRef as forwardRef3, useState as useState2 } from "react";
525
+ import React7, { forwardRef as forwardRef4, useState as useState2 } from "react";
484
526
  import { cx as cx5 } from "@edux-design/utils";
485
527
  import { Check as Check2, Close as Close3 } from "@edux-design/icons";
486
528
  import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
@@ -546,13 +588,14 @@ var SWITCH_INTENTS = {
546
588
  onIcon: "text-fg-inactive"
547
589
  }
548
590
  };
549
- var Switch = forwardRef3(
591
+ var Switch = forwardRef4(
550
592
  ({
551
593
  className,
552
594
  variant = "primary",
553
595
  disabled,
554
596
  id: providedId,
555
597
  checked,
598
+ defaultChecked = false,
556
599
  onChange,
557
600
  ...rest
558
601
  }, ref) => {
@@ -568,8 +611,11 @@ var Switch = forwardRef3(
568
611
  const derivedDisabled = Boolean(disabled);
569
612
  const isInactiveVariant = variant === "inactive";
570
613
  const isDisabled = derivedDisabled || isInactiveVariant;
571
- const [unControlledChecked, setUnControlledChecked] = useState2(false);
572
- const isOn = checked ?? unControlledChecked;
614
+ const [unControlledChecked, setUnControlledChecked] = useState2(
615
+ () => Boolean(defaultChecked)
616
+ );
617
+ const isControlled = checked !== void 0;
618
+ const isOn = isControlled ? checked : unControlledChecked;
573
619
  return /* @__PURE__ */ jsxs6(
574
620
  "div",
575
621
  {
@@ -583,8 +629,8 @@ var Switch = forwardRef3(
583
629
  {
584
630
  id: resolvedId,
585
631
  ref,
586
- onChange: onChange ? onChange : () => setUnControlledChecked(!unControlledChecked),
587
- checked: checked ? checked : unControlledChecked,
632
+ onChange: onChange ? onChange : (event) => setUnControlledChecked(event.target.checked),
633
+ checked: isControlled ? checked : unControlledChecked,
588
634
  type: "checkbox",
589
635
  role: "switch",
590
636
  className: cx5(
@@ -633,12 +679,14 @@ var Switch = forwardRef3(
633
679
  Close3,
634
680
  {
635
681
  "aria-hidden": "true",
682
+ "data-state": "off",
636
683
  className: cx5("absolute duration-150", intent.offIcon)
637
684
  }
638
685
  ) : /* @__PURE__ */ jsx7(
639
686
  Check2,
640
687
  {
641
688
  "aria-hidden": "true",
689
+ "data-state": "on",
642
690
  className: cx5("absolute duration-150", intent.onIcon)
643
691
  }
644
692
  )
@@ -652,11 +700,11 @@ var Switch = forwardRef3(
652
700
  Switch.displayName = "Switch";
653
701
 
654
702
  // src/elements/Textarea.jsx
655
- import React8, { forwardRef as forwardRef4 } from "react";
703
+ import React8, { forwardRef as forwardRef5 } from "react";
656
704
  import { cx as cx6 } from "@edux-design/utils";
657
705
  import { Close as Close4 } from "@edux-design/icons";
658
706
  import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
659
- var Textarea = forwardRef4(
707
+ var Textarea = forwardRef5(
660
708
  ({
661
709
  children,
662
710
  validation,
@@ -743,7 +791,7 @@ var Textarea = forwardRef4(
743
791
 
744
792
  // src/elements/Combobox.jsx
745
793
  import React9, {
746
- forwardRef as forwardRef5,
794
+ forwardRef as forwardRef6,
747
795
  useCallback as useCallback4,
748
796
  useEffect as useEffect3,
749
797
  useId as useId3,
@@ -781,7 +829,7 @@ var defaultFilter = (option, query) => {
781
829
  const normalisedLabel = ((_a = option.label) == null ? void 0 : _a.toString().toLowerCase()) ?? "";
782
830
  return normalisedLabel.includes(query.trim().toLowerCase());
783
831
  };
784
- var ComboboxRoot = forwardRef5(
832
+ var ComboboxRoot = forwardRef6(
785
833
  ({
786
834
  children,
787
835
  value,
@@ -1277,7 +1325,7 @@ var ComboboxRoot = forwardRef5(
1277
1325
  }
1278
1326
  );
1279
1327
  ComboboxRoot.displayName = "Combobox";
1280
- var ComboboxOption = forwardRef5(function ComboboxOption2({ children, label, ...props }, ref) {
1328
+ var ComboboxOption = forwardRef6(function ComboboxOption2({ children, label, ...props }, ref) {
1281
1329
  return /* @__PURE__ */ jsx9("li", { ref, ...props, children: children ?? label });
1282
1330
  });
1283
1331
  ComboboxOption.displayName = OPTION_COMPONENT_NAME;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edux-design/forms",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "sideEffects": [
5
5
  "**/*.css"
6
6
  ],