@spark-ui/components 17.10.5-beta.0 → 17.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/dist/accordion/index.js +1 -1
  2. package/dist/accordion/index.js.map +1 -1
  3. package/dist/accordion/index.mjs +1 -1
  4. package/dist/accordion/index.mjs.map +1 -1
  5. package/dist/alert-dialog/index.js +1 -1
  6. package/dist/alert-dialog/index.js.map +1 -1
  7. package/dist/alert-dialog/index.mjs +1 -1
  8. package/dist/alert-dialog/index.mjs.map +1 -1
  9. package/dist/avatar/index.js +1 -1
  10. package/dist/avatar/index.js.map +1 -1
  11. package/dist/avatar/index.mjs +17 -17
  12. package/dist/avatar/index.mjs.map +1 -1
  13. package/dist/button/index.js +1 -1
  14. package/dist/button/index.mjs +1 -1
  15. package/dist/{button-BtuAr9qV.mjs → button-CNabSkd_.mjs} +2 -2
  16. package/dist/{button-BtuAr9qV.mjs.map → button-CNabSkd_.mjs.map} +1 -1
  17. package/dist/{button-BaJmiSYq.js → button-Tv2N8_24.js} +2 -2
  18. package/dist/{button-BaJmiSYq.js.map → button-Tv2N8_24.js.map} +1 -1
  19. package/dist/card/index.js +1 -1
  20. package/dist/card/index.js.map +1 -1
  21. package/dist/card/index.mjs +1 -1
  22. package/dist/card/index.mjs.map +1 -1
  23. package/dist/carousel/index.js +1 -1
  24. package/dist/carousel/index.js.map +1 -1
  25. package/dist/carousel/index.mjs +2 -2
  26. package/dist/carousel/index.mjs.map +1 -1
  27. package/dist/checkbox/index.js +1 -1
  28. package/dist/checkbox/index.mjs +1 -1
  29. package/dist/{checkbox-xsURzANi.mjs → checkbox-CbMh-21q.mjs} +2 -2
  30. package/dist/{checkbox-xsURzANi.mjs.map → checkbox-CbMh-21q.mjs.map} +1 -1
  31. package/dist/{checkbox-DjwbAH09.js → checkbox-hVGRiWC_.js} +2 -2
  32. package/dist/{checkbox-DjwbAH09.js.map → checkbox-hVGRiWC_.js.map} +1 -1
  33. package/dist/chip/index.js +1 -1
  34. package/dist/chip/index.js.map +1 -1
  35. package/dist/chip/index.mjs +1 -1
  36. package/dist/chip/index.mjs.map +1 -1
  37. package/dist/circular-meter/index.js +1 -1
  38. package/dist/circular-meter/index.js.map +1 -1
  39. package/dist/circular-meter/index.mjs +28 -28
  40. package/dist/circular-meter/index.mjs.map +1 -1
  41. package/dist/combobox/index.js +1 -1
  42. package/dist/combobox/index.js.map +1 -1
  43. package/dist/combobox/index.mjs +10 -13
  44. package/dist/combobox/index.mjs.map +1 -1
  45. package/dist/dialog/index.js +1 -1
  46. package/dist/dialog/index.js.map +1 -1
  47. package/dist/dialog/index.mjs +2 -2
  48. package/dist/dialog/index.mjs.map +1 -1
  49. package/dist/drawer/index.js +1 -1
  50. package/dist/drawer/index.js.map +1 -1
  51. package/dist/drawer/index.mjs +2 -2
  52. package/dist/drawer/index.mjs.map +1 -1
  53. package/dist/dropdown/index.js +1 -1
  54. package/dist/dropdown/index.js.map +1 -1
  55. package/dist/dropdown/index.mjs +9 -12
  56. package/dist/dropdown/index.mjs.map +1 -1
  57. package/dist/file-upload/index.js +1 -1
  58. package/dist/file-upload/index.js.map +1 -1
  59. package/dist/file-upload/index.mjs +5 -5
  60. package/dist/file-upload/index.mjs.map +1 -1
  61. package/dist/form-field/index.js +1 -1
  62. package/dist/form-field/index.mjs +1 -1
  63. package/dist/form-field-BCqHBvWN.js +2 -0
  64. package/dist/form-field-BCqHBvWN.js.map +1 -0
  65. package/dist/{form-field-CV5dzt-I.mjs → form-field-ByLHXtzx.mjs} +27 -27
  66. package/dist/form-field-ByLHXtzx.mjs.map +1 -0
  67. package/dist/icon-button/index.js +1 -1
  68. package/dist/icon-button/index.mjs +1 -1
  69. package/dist/icon-button-CTe0v0g7.js +2 -0
  70. package/dist/{icon-button-BSVlcyAO.js.map → icon-button-CTe0v0g7.js.map} +1 -1
  71. package/dist/{icon-button-XyQSaVPL.mjs → icon-button-DVbKK2_a.mjs} +3 -3
  72. package/dist/{icon-button-XyQSaVPL.mjs.map → icon-button-DVbKK2_a.mjs.map} +1 -1
  73. package/dist/input/index.js +1 -1
  74. package/dist/input/index.mjs +1 -1
  75. package/dist/{input-CJOeEIbx.mjs → input-BxuTPD5-.mjs} +6 -6
  76. package/dist/input-BxuTPD5-.mjs.map +1 -0
  77. package/dist/input-DIGSkxbh.js +2 -0
  78. package/dist/input-DIGSkxbh.js.map +1 -0
  79. package/dist/input-otp/index.js +1 -1
  80. package/dist/input-otp/index.js.map +1 -1
  81. package/dist/input-otp/index.mjs +27 -17
  82. package/dist/input-otp/index.mjs.map +1 -1
  83. package/dist/menu/index.js +1 -1
  84. package/dist/menu/index.js.map +1 -1
  85. package/dist/menu/index.mjs +1 -1
  86. package/dist/menu/index.mjs.map +1 -1
  87. package/dist/meter/index.js +1 -1
  88. package/dist/meter/index.js.map +1 -1
  89. package/dist/meter/index.mjs +17 -17
  90. package/dist/meter/index.mjs.map +1 -1
  91. package/dist/pagination/index.js +1 -1
  92. package/dist/pagination/index.js.map +1 -1
  93. package/dist/pagination/index.mjs +3 -3
  94. package/dist/pagination/index.mjs.map +1 -1
  95. package/dist/popover/index.js +1 -1
  96. package/dist/popover/index.mjs +1 -1
  97. package/dist/{popover-CSmCERcL.mjs → popover-83FABwMs.mjs} +3 -3
  98. package/dist/popover-83FABwMs.mjs.map +1 -0
  99. package/dist/popover-Daknmg_Z.js +2 -0
  100. package/dist/popover-Daknmg_Z.js.map +1 -0
  101. package/dist/progress/index.js +1 -1
  102. package/dist/progress/index.mjs +1 -1
  103. package/dist/{progress-C-Zs94G2.mjs → progress-BfpWgeE1.mjs} +2 -2
  104. package/dist/{progress-C-Zs94G2.mjs.map → progress-BfpWgeE1.mjs.map} +1 -1
  105. package/dist/{progress-DaQt4olK.js → progress-DBD2FiQ1.js} +2 -2
  106. package/dist/{progress-DaQt4olK.js.map → progress-DBD2FiQ1.js.map} +1 -1
  107. package/dist/progress-tracker/index.js +1 -1
  108. package/dist/progress-tracker/index.js.map +1 -1
  109. package/dist/progress-tracker/index.mjs +4 -4
  110. package/dist/progress-tracker/index.mjs.map +1 -1
  111. package/dist/radio-group/index.js +1 -1
  112. package/dist/radio-group/index.js.map +1 -1
  113. package/dist/radio-group/index.mjs +5 -8
  114. package/dist/radio-group/index.mjs.map +1 -1
  115. package/dist/rating/index.js +1 -1
  116. package/dist/rating/index.mjs +1 -1
  117. package/dist/rating-display/index.js +1 -1
  118. package/dist/rating-display/index.js.map +1 -1
  119. package/dist/rating-display/index.mjs +1 -1
  120. package/dist/rating-display/index.mjs.map +1 -1
  121. package/dist/scrolling-list/index.js +1 -1
  122. package/dist/scrolling-list/index.js.map +1 -1
  123. package/dist/scrolling-list/index.mjs +17 -17
  124. package/dist/scrolling-list/index.mjs.map +1 -1
  125. package/dist/segmented-control/index.js +1 -1
  126. package/dist/segmented-control/index.js.map +1 -1
  127. package/dist/segmented-control/index.mjs +1 -1
  128. package/dist/segmented-control/index.mjs.map +1 -1
  129. package/dist/segmented-gauge/index.js +1 -1
  130. package/dist/segmented-gauge/index.js.map +1 -1
  131. package/dist/segmented-gauge/index.mjs +1 -1
  132. package/dist/segmented-gauge/index.mjs.map +1 -1
  133. package/dist/select/index.js +1 -1
  134. package/dist/select/index.js.map +1 -1
  135. package/dist/select/index.mjs +2 -2
  136. package/dist/select/index.mjs.map +1 -1
  137. package/dist/slider/index.js +1 -1
  138. package/dist/slider/index.js.map +1 -1
  139. package/dist/slider/index.mjs +2 -2
  140. package/dist/slider/index.mjs.map +1 -1
  141. package/dist/stepper/index.js +1 -1
  142. package/dist/stepper/index.js.map +1 -1
  143. package/dist/stepper/index.mjs +3 -3
  144. package/dist/stepper/index.mjs.map +1 -1
  145. package/dist/table/index.js +1 -1
  146. package/dist/table/index.js.map +1 -1
  147. package/dist/table/index.mjs +36 -36
  148. package/dist/table/index.mjs.map +1 -1
  149. package/dist/tabs/index.js +1 -1
  150. package/dist/tabs/index.js.map +1 -1
  151. package/dist/tabs/index.mjs +16 -16
  152. package/dist/tabs/index.mjs.map +1 -1
  153. package/dist/tag/index.js +1 -1
  154. package/dist/tag/index.js.map +1 -1
  155. package/dist/tag/index.mjs +1 -1
  156. package/dist/tag/index.mjs.map +1 -1
  157. package/dist/textarea/index.js +1 -1
  158. package/dist/textarea/index.js.map +1 -1
  159. package/dist/textarea/index.mjs +2 -2
  160. package/dist/textarea/index.mjs.map +1 -1
  161. package/dist/toast/index.js +1 -1
  162. package/dist/toast/index.mjs +2 -2
  163. package/package.json +5 -5
  164. package/dist/form-field-CV5dzt-I.mjs.map +0 -1
  165. package/dist/form-field-CYGgse45.js +0 -2
  166. package/dist/form-field-CYGgse45.js.map +0 -1
  167. package/dist/icon-button-BSVlcyAO.js +0 -2
  168. package/dist/input-CJOeEIbx.mjs.map +0 -1
  169. package/dist/input-Dv436NKY.js +0 -2
  170. package/dist/input-Dv436NKY.js.map +0 -1
  171. package/dist/popover-CSmCERcL.mjs.map +0 -1
  172. package/dist/popover-CsCB_Fgs.js +0 -2
  173. package/dist/popover-CsCB_Fgs.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { t as e } from "./button-BtuAr9qV.mjs";
1
+ import { t as e } from "./button-CNabSkd_.mjs";
2
2
  import { cva as t } from "class-variance-authority";
3
3
  import { jsx as n } from "react/jsx-runtime";
4
4
  import { makeVariants as r } from "@spark-ui/internal-utils";
@@ -7,7 +7,7 @@ var i = t(["pl-0 pr-0"], { variants: { size: r({
7
7
  sm: ["text-body-1"],
8
8
  md: ["text-body-1"],
9
9
  lg: ["text-display-3"]
10
- }) } }), a = ({ design: t = "filled", disabled: r = !1, intent: a = "main", shape: o = "pill", size: s = "md", className: c, ref: l, ...u }) => /* @__PURE__ */ n(e, {
10
+ }) } }), a = ({ design: t = "filled", disabled: r = !1, intent: a = "main", shape: o = "rounded", size: s = "md", className: c, ref: l, ...u }) => /* @__PURE__ */ n(e, {
11
11
  "data-spark-component": "icon-button",
12
12
  ref: l,
13
13
  className: i({
@@ -25,4 +25,4 @@ a.displayName = "IconButton";
25
25
  //#endregion
26
26
  export { a as t };
27
27
 
28
- //# sourceMappingURL=icon-button-XyQSaVPL.mjs.map
28
+ //# sourceMappingURL=icon-button-DVbKK2_a.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"icon-button-XyQSaVPL.mjs","names":[],"sources":["../src/icon-button/IconButton.styles.tsx","../src/icon-button/IconButton.tsx"],"sourcesContent":["import { makeVariants } from '@spark-ui/internal-utils'\nimport { cva, VariantProps } from 'class-variance-authority'\n\n// override the Button component's px-lg padding by using a more specific class selector (pl-0 pr-0)\nexport const iconButtonStyles = cva(['pl-0 pr-0'], {\n variants: {\n /**\n * Sets the size of the icon.\n */\n size: makeVariants<'size', ['sm', 'md', 'lg']>({\n sm: ['text-body-1'],\n md: ['text-body-1'],\n lg: ['text-display-3'],\n }),\n },\n})\n\nexport type IconButtonStylesProps = VariantProps<typeof iconButtonStyles>\n","import { Ref } from 'react'\n\nimport { Button, ButtonProps } from '../button'\nimport { iconButtonStyles } from './IconButton.styles'\n\nexport interface IconButtonProps extends Omit<ButtonProps, 'loadingText'> {\n 'aria-label': string\n ref?: Ref<HTMLButtonElement>\n}\n\n/**\n * A button component that contains only an icon without text label.\n */\nexport const IconButton = ({\n design = 'filled',\n disabled = false,\n intent = 'main',\n shape = 'pill',\n size = 'md',\n className,\n ref,\n ...others\n}: IconButtonProps) => {\n return (\n <Button\n data-spark-component=\"icon-button\"\n ref={ref}\n className={iconButtonStyles({ size, className })}\n design={design}\n disabled={disabled}\n intent={intent}\n shape={shape}\n size={size}\n {...others}\n />\n )\n}\n\nIconButton.displayName = 'IconButton'\n"],"mappings":";;;;;AAIA,IAAa,IAAmB,EAAI,CAAC,YAAY,EAAE,EACjD,UAAU,EAIR,MAAM,EAAyC;CAC7C,IAAI,CAAC,cAAc;CACnB,IAAI,CAAC,cAAc;CACnB,IAAI,CAAC,iBAAiB;CACvB,CAAC,EACH,EACF,CAAC,ECFW,KAAc,EACzB,YAAS,UACT,cAAW,IACX,YAAS,QACT,WAAQ,QACR,UAAO,MACP,cACA,QACA,GAAG,QAGD,kBAAC,GAAD;CACE,wBAAqB;CAChB;CACL,WAAW,EAAiB;EAAE;EAAM;EAAW,CAAC;CACxC;CACE;CACF;CACD;CACD;CACN,GAAI;CACJ,CAAA;AAIN,EAAW,cAAc"}
1
+ {"version":3,"file":"icon-button-DVbKK2_a.mjs","names":[],"sources":["../src/icon-button/IconButton.styles.tsx","../src/icon-button/IconButton.tsx"],"sourcesContent":["import { makeVariants } from '@spark-ui/internal-utils'\nimport { cva, VariantProps } from 'class-variance-authority'\n\n// override the Button component's px-lg padding by using a more specific class selector (pl-0 pr-0)\nexport const iconButtonStyles = cva(['pl-0 pr-0'], {\n variants: {\n /**\n * Sets the size of the icon.\n */\n size: makeVariants<'size', ['sm', 'md', 'lg']>({\n sm: ['text-body-1'],\n md: ['text-body-1'],\n lg: ['text-display-3'],\n }),\n },\n})\n\nexport type IconButtonStylesProps = VariantProps<typeof iconButtonStyles>\n","import { Ref } from 'react'\n\nimport { Button, ButtonProps } from '../button'\nimport { iconButtonStyles } from './IconButton.styles'\n\nexport interface IconButtonProps extends Omit<ButtonProps, 'loadingText'> {\n 'aria-label': string\n ref?: Ref<HTMLButtonElement>\n}\n\n/**\n * A button component that contains only an icon without text label.\n */\nexport const IconButton = ({\n design = 'filled',\n disabled = false,\n intent = 'main',\n shape = 'rounded',\n size = 'md',\n className,\n ref,\n ...others\n}: IconButtonProps) => {\n return (\n <Button\n data-spark-component=\"icon-button\"\n ref={ref}\n className={iconButtonStyles({ size, className })}\n design={design}\n disabled={disabled}\n intent={intent}\n shape={shape}\n size={size}\n {...others}\n />\n )\n}\n\nIconButton.displayName = 'IconButton'\n"],"mappings":";;;;;AAIA,IAAa,IAAmB,EAAI,CAAC,YAAY,EAAE,EACjD,UAAU,EAIR,MAAM,EAAyC;CAC7C,IAAI,CAAC,cAAc;CACnB,IAAI,CAAC,cAAc;CACnB,IAAI,CAAC,iBAAiB;CACvB,CAAC,EACH,EACF,CAAC,ECFW,KAAc,EACzB,YAAS,UACT,cAAW,IACX,YAAS,QACT,WAAQ,WACR,UAAO,MACP,cACA,QACA,GAAG,QAGD,kBAAC,GAAD;CACE,wBAAqB;CAChB;CACL,WAAW,EAAiB;EAAE;EAAM;EAAW,CAAC;CACxC;CACE;CACF;CACD;CACD;CACN,GAAI;CACJ,CAAA;AAIN,EAAW,cAAc"}
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../input-Dv436NKY.js`);exports.Input=e.n,exports.InputGroup=e.t,exports.useInputGroup=e.i;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../input-DIGSkxbh.js`);exports.Input=e.n,exports.InputGroup=e.t,exports.useInputGroup=e.i;
@@ -1,2 +1,2 @@
1
- import { i as e, n as t, t as n } from "../input-CJOeEIbx.mjs";
1
+ import { i as e, n as t, t as n } from "../input-BxuTPD5-.mjs";
2
2
  export { t as Input, n as InputGroup, e as useInputGroup };
@@ -85,7 +85,7 @@ var C = n(["relative inline-flex w-full"], { variants: {
85
85
  O.current = l;
86
86
  }, [l]);
87
87
  let Y = D.current?.value;
88
- return /* @__PURE__ */ p(y.Provider, {
88
+ return /* @__PURE__ */ p(y, {
89
89
  value: J,
90
90
  children: /* @__PURE__ */ m("div", {
91
91
  "data-spark-component": "input-group",
@@ -191,10 +191,10 @@ E.displayName = "InputGroup.Addon";
191
191
  var D = ({ className: e, ref: t, ...n }) => {
192
192
  let { disabled: i, readOnly: a } = b();
193
193
  return /* @__PURE__ */ p("div", {
194
- className: r("rounded-l-full", i || a ? "bg-on-surface/dim-5" : null),
194
+ className: r("rounded-l-lg", i || a ? "bg-on-surface/dim-5" : null),
195
195
  children: /* @__PURE__ */ p(E, {
196
196
  ref: t,
197
- className: r(e, "rounded-r-0! -mr-px rounded-l-full"),
197
+ className: r(e, "rounded-r-0! mr-[-1px] rounded-l-lg"),
198
198
  ...n
199
199
  })
200
200
  });
@@ -225,10 +225,10 @@ A.id = "LeadingIcon", A.displayName = "InputGroup.LeadingIcon";
225
225
  var j = ({ className: e, ref: t, ...n }) => {
226
226
  let { disabled: i, readOnly: a } = b();
227
227
  return /* @__PURE__ */ p("div", {
228
- className: r("rounded-r-full", i || a ? "bg-on-surface/dim-5" : null),
228
+ className: r("rounded-r-lg", i || a ? "bg-on-surface/dim-5" : null),
229
229
  children: /* @__PURE__ */ p(E, {
230
230
  ref: t,
231
- className: r(e, "rounded-l-0! -ml-px rounded-r-full"),
231
+ className: r(e, "rounded-l-0! ml-[-1px] rounded-r-lg"),
232
232
  ...n
233
233
  })
234
234
  });
@@ -352,4 +352,4 @@ L.displayName = "InputGroup", O.displayName = "InputGroup.LeadingAddon", M.displ
352
352
  //#endregion
353
353
  export { b as i, I as n, C as r, L as t };
354
354
 
355
- //# sourceMappingURL=input-CJOeEIbx.mjs.map
355
+ //# sourceMappingURL=input-BxuTPD5-.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-BxuTPD5-.mjs","names":[],"sources":["../src/input/InputGroupContext.ts","../src/input/InputClearButton.tsx","../src/input/InputGroup.styles.ts","../src/input/InputGroup.tsx","../src/input/InputAddon.styles.ts","../src/input/InputAddon.tsx","../src/input/InputLeadingAddon.tsx","../src/input/InputIcon.tsx","../src/input/InputLeadingIcon.tsx","../src/input/InputTrailingAddon.tsx","../src/input/InputTrailingIcon.tsx","../src/input/Input.styles.ts","../src/input/Input.tsx","../src/input/index.ts"],"sourcesContent":["import { createContext, useContext } from 'react'\n\nexport interface InputGroupContextValue {\n disabled?: boolean\n readOnly?: boolean\n hasLeadingIcon: boolean\n hasTrailingIcon: boolean\n hasLeadingAddon: boolean\n hasTrailingAddon: boolean\n hasClearButton: boolean\n state: null | undefined | 'error' | 'alert' | 'success'\n isStandalone?: boolean\n onClear: () => void\n}\n\nexport const InputGroupContext = createContext<Partial<InputGroupContextValue> | null>(null)\n\nexport const useInputGroup = () => {\n const context = useContext(InputGroupContext)\n\n return context || { isStandalone: true }\n}\n","import { DeleteOutline } from '@spark-ui/icons/DeleteOutline'\nimport { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, MouseEventHandler, Ref } from 'react'\n\nimport { Icon } from '../icon'\nimport { useInputGroup } from './InputGroupContext'\n\nexport interface InputClearButtonProps extends ComponentPropsWithoutRef<'button'> {\n 'aria-label': string\n inline?: boolean\n ref?: Ref<HTMLButtonElement>\n}\n\n/** A button to clear the input value. Renders a <button> element. */\nconst Root = ({\n className,\n tabIndex = -1,\n onClick,\n inline = false,\n ref,\n ...others\n}: InputClearButtonProps) => {\n const { onClear, hasTrailingIcon } = useInputGroup()\n\n const handleClick: MouseEventHandler<HTMLButtonElement> = event => {\n if (onClick) {\n onClick(event)\n }\n\n if (onClear) {\n onClear()\n }\n }\n\n return (\n <button\n ref={ref}\n data-spark-component=\"input-clear-button\"\n className={cx(\n className,\n 'pointer-events-auto absolute',\n inline ? 'h-sz-44 top-0 -translate-y-0' : 'top-1/2 -translate-y-1/2',\n 'inline-flex h-full items-center justify-center outline-hidden',\n 'text-neutral hover:text-neutral-hovered',\n hasTrailingIcon ? 'right-3xl px-sz-12' : 'pl-md pr-lg right-0'\n )}\n tabIndex={tabIndex}\n onClick={handleClick}\n type=\"button\"\n {...others}\n >\n <Icon size=\"sm\">\n <DeleteOutline />\n </Icon>\n </button>\n )\n}\n\nexport const InputClearButton = Object.assign(Root, {\n id: 'ClearButton',\n})\n\nRoot.displayName = 'InputGroup.ClearButton'\n","import { cva, VariantProps } from 'class-variance-authority'\n\nexport const inputGroupStyles = cva(['relative inline-flex w-full'], {\n variants: {\n /**\n * When `true`, prevents the user from interacting.\n */\n disabled: {\n true: [\n 'cursor-not-allowed',\n 'relative',\n 'after:absolute',\n 'after:top-0',\n 'after:h-full',\n 'after:w-full',\n 'after:border-sm after:border-outline',\n 'after:rounded-lg',\n ],\n false: 'after:hidden',\n },\n /**\n * Sets the component as interactive or not.\n */\n readOnly: {\n true: [\n 'relative',\n 'after:absolute',\n 'after:top-0',\n 'after:h-full',\n 'after:w-full',\n 'after:border-sm after:border-outline',\n 'after:rounded-lg',\n ],\n false: 'after:hidden',\n },\n },\n})\n\nexport type InputGroupStylesProps = VariantProps<typeof inputGroupStyles>\n","/* eslint-disable max-lines-per-function */\n\nimport { useFormFieldControl } from '@spark-ui/components/form-field'\nimport { useCombinedState } from '@spark-ui/hooks/use-combined-state'\nimport { useMergeRefs } from '@spark-ui/hooks/use-merge-refs'\nimport {\n ChangeEventHandler,\n Children,\n cloneElement,\n ComponentPropsWithoutRef,\n DetailedReactHTMLElement,\n FC,\n isValidElement,\n PropsWithChildren,\n ReactElement,\n Ref,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n} from 'react'\n\nimport { InputProps } from './Input'\nimport { inputGroupStyles, InputGroupStylesProps } from './InputGroup.styles'\nimport { InputGroupContext } from './InputGroupContext'\n\nexport interface InputGroupProps extends ComponentPropsWithoutRef<'div'>, InputGroupStylesProps {\n /**\n * Use `state` prop to assign a specific state to the group, choosing from: `error`, `alert` and `success`. By doing so, the outline styles will be updated.\n */\n state?: 'error' | 'alert' | 'success'\n /**\n * Function handler to be executed after the input has been cleared.\n */\n onClear?: () => void\n ref?: Ref<HTMLDivElement>\n}\n\nexport const InputGroup = ({\n className,\n children: childrenProp,\n state: stateProp,\n disabled: disabledProp,\n readOnly: readOnlyProp,\n onClear,\n ref: forwardedRef,\n ...others\n}: PropsWithChildren<InputGroupProps>) => {\n const getElementId = (element?: ReactElement) => {\n return element ? (element.type as FC & { id?: string }).id : ''\n }\n\n const findElement = (...values: string[]) => {\n return children.find(child => values.includes(getElementId(child) || ''))\n }\n\n const children = Children.toArray(childrenProp).filter(isValidElement)\n const input = findElement('Input') as\n | DetailedReactHTMLElement<InputProps, HTMLInputElement>\n | undefined\n const props = input?.props || {}\n\n const inputRef = useRef<HTMLInputElement>(null!)\n const onClearRef = useRef(onClear)\n const ref = useMergeRefs<HTMLInputElement>(input?.ref, inputRef)\n const [value, onChange] = useCombinedState(\n props.value as string,\n props.defaultValue as string,\n props.onValueChange\n )\n\n // Data derivated from FormField context\n const field = useFormFieldControl()\n const state = field.state ?? stateProp\n const disabled = field.disabled || !!disabledProp\n const readOnly = field.readOnly || !!readOnlyProp\n\n // InputGroup elements (in visual order)\n const leadingAddon = findElement('LeadingAddon')\n const leadingIcon = findElement('LeadingIcon')\n const clearButton = findElement('ClearButton')\n const trailingIcon = findElement('TrailingIcon')\n const trailingAddon = findElement('TrailingAddon')\n\n // Acknowledge which subComponents are used in the compound context\n const hasLeadingAddon = !!leadingAddon\n const hasTrailingAddon = !!trailingAddon\n const hasLeadingIcon = !!leadingIcon\n const hasTrailingIcon = !!trailingIcon\n const hasClearButton = !!value && !!clearButton && !disabled && !readOnly\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = event => {\n if (props.onChange) {\n props.onChange(event)\n }\n\n onChange(event.target.value)\n }\n\n const handleClear = useCallback(() => {\n if (onClearRef.current) {\n onClearRef.current()\n }\n\n onChange('')\n\n inputRef.current.focus()\n }, [onChange])\n\n const current = useMemo(() => {\n return {\n state,\n disabled,\n readOnly,\n hasLeadingIcon,\n hasTrailingIcon,\n hasLeadingAddon,\n hasTrailingAddon,\n hasClearButton,\n onClear: handleClear,\n }\n }, [\n state,\n disabled,\n readOnly,\n hasLeadingIcon,\n hasTrailingIcon,\n hasLeadingAddon,\n hasTrailingAddon,\n hasClearButton,\n handleClear,\n ])\n\n useEffect(() => {\n onClearRef.current = onClear\n }, [onClear])\n\n // Preserve the input value when cloning. Some libraries like React Hook Form\n // only expose a ref (via `register`) without direct value access, so we need\n // to manually retrieve the value from the ref to avoid losing it.\n const inputRefValue = inputRef.current?.value\n\n return (\n <InputGroupContext value={current}>\n <div\n data-spark-component=\"input-group\"\n ref={forwardedRef}\n className={inputGroupStyles({ disabled, readOnly, className })}\n {...others}\n >\n {hasLeadingAddon && leadingAddon}\n\n <div className=\"relative inline-flex w-full\">\n {input &&\n cloneElement(input, {\n value: value ?? inputRefValue ?? '',\n ref,\n defaultValue: undefined,\n onChange: handleChange,\n })}\n\n {leadingIcon}\n\n {hasClearButton && clearButton}\n\n {trailingIcon}\n </div>\n\n {hasTrailingAddon && trailingAddon}\n </div>\n </InputGroupContext>\n )\n}\n\nInputGroup.displayName = 'InputGroup'\n","import { cva, VariantProps } from 'class-variance-authority'\n\nexport const inputAddonStyles = cva(\n [\n 'overflow-hidden',\n 'border-sm',\n 'shrink-0',\n 'h-full',\n 'focus-visible:relative focus-visible:z-raised',\n 'mx-0',\n ],\n {\n variants: {\n /**\n * Change the component to the HTML tag or custom component of the only child.\n */\n asChild: { false: ['flex', 'items-center', 'px-lg'] },\n intent: {\n neutral: 'border-outline',\n error: 'border-error',\n alert: 'border-alert',\n success: 'border-success',\n },\n /**\n * Disable the input addon, preventing user interaction and adding opacity.\n */\n disabled: {\n true: ['pointer-events-none border-outline!'],\n },\n /**\n * Changes input addon styles based on the read only status from the input.\n */\n readOnly: {\n true: ['pointer-events-none'],\n },\n /**\n * Main style of the input addon.\n */\n design: {\n text: '',\n solid: '',\n inline: '',\n },\n },\n compoundVariants: [\n {\n disabled: false,\n readOnly: false,\n design: 'text',\n class: ['bg-surface', 'text-on-surface'],\n },\n {\n disabled: true,\n design: 'text',\n class: ['text-on-surface/dim-3'],\n },\n {\n disabled: true,\n design: ['solid', 'inline'],\n class: ['opacity-dim-3'],\n },\n ],\n defaultVariants: {\n intent: 'neutral',\n },\n }\n)\n\nexport type InputAddonStylesProps = VariantProps<typeof inputAddonStyles>\n","import { Children, type ComponentPropsWithoutRef, type PropsWithChildren, Ref } from 'react'\n\nimport { Slot } from '../slot'\nimport { inputAddonStyles, type InputAddonStylesProps } from './InputAddon.styles'\nimport { useInputGroup } from './InputGroupContext'\n\nexport interface InputAddonProps\n extends ComponentPropsWithoutRef<'div'>, Omit<InputAddonStylesProps, 'intent' | 'disabled'> {\n ref?: Ref<HTMLDivElement>\n}\n\nexport const InputAddon = ({\n asChild: asChildProp,\n className,\n children,\n ref,\n ...others\n}: PropsWithChildren<InputAddonProps>) => {\n const { state, disabled, readOnly } = useInputGroup()\n\n const isRawText = typeof children === 'string'\n const asChild = !!(isRawText ? false : asChildProp)\n const child = isRawText ? children : Children.only(children)\n const Component = asChild && !isRawText ? Slot : 'div'\n\n const getDesign = (): InputAddonStylesProps['design'] => {\n if (isRawText) return 'text'\n\n return asChild ? 'solid' : 'inline'\n }\n\n const design = getDesign()\n\n return (\n <Component\n ref={ref}\n data-spark-component=\"input-addon\"\n className={inputAddonStyles({\n className,\n intent: state,\n disabled,\n readOnly,\n asChild,\n design,\n })}\n {...(disabled && { tabIndex: -1 })}\n {...others}\n >\n {child}\n </Component>\n )\n}\n\nInputAddon.displayName = 'InputGroup.Addon'\n","import { cx } from 'class-variance-authority'\nimport { Ref } from 'react'\n\nimport { InputAddon, InputAddonProps } from './InputAddon'\nimport { useInputGroup } from './InputGroupContext'\n\nexport type InputLeadingAddonProps = InputAddonProps & {\n ref?: Ref<HTMLDivElement>\n}\n\n/**\n * An addon displayed before the input. Renders a <span> element.\n */\nconst Root = ({ className, ref, ...others }: InputLeadingAddonProps) => {\n const { disabled, readOnly } = useInputGroup()\n const isInactive = disabled || readOnly\n\n return (\n <div className={cx('rounded-l-lg', isInactive ? 'bg-on-surface/dim-5' : null)}>\n <InputAddon\n ref={ref}\n className={cx(className, 'rounded-r-0! mr-[-1px] rounded-l-lg')}\n {...others}\n />\n </div>\n )\n}\n\nexport const InputLeadingAddon = Object.assign(Root, {\n id: 'LeadingAddon',\n})\n\nRoot.displayName = 'InputGroup.LeadingAddon'\n","import { cx } from 'class-variance-authority'\n\nimport { Icon, type IconProps } from '../icon'\nimport { useInputGroup } from './InputGroupContext'\n\nexport type InputIconProps = IconProps\n\nexport const InputIcon = ({ className, intent, children, ...others }: InputIconProps) => {\n const { disabled, readOnly } = useInputGroup()\n const isInactive = disabled || readOnly\n\n return (\n <Icon\n data-spark-component=\"input-icon\"\n intent={intent}\n className={cx(\n className,\n 'pointer-events-none absolute top-[calc(var(--spacing-sz-44)/2)] -translate-y-1/2',\n intent ? undefined : 'text-neutral peer-focus:text-outline-high',\n isInactive ? 'opacity-dim-3' : undefined\n )}\n {...others}\n >\n {children}\n </Icon>\n )\n}\n\nInputIcon.displayName = 'InputGroup.Icon'\n","import { cx } from 'class-variance-authority'\n\nimport { InputIcon, InputIconProps } from './InputIcon'\n\nexport type InputLeadingIconProps = InputIconProps\n\n/** An icon displayed before the input text. Renders a <div> element. */\nexport const InputLeadingIcon = ({ className, ...others }: InputLeadingIconProps) => (\n <InputIcon className={cx(className, 'left-lg text-body-1')} {...others} />\n)\n\nInputLeadingIcon.id = 'LeadingIcon'\nInputLeadingIcon.displayName = 'InputGroup.LeadingIcon'\n","import { cx } from 'class-variance-authority'\nimport { Ref } from 'react'\n\nimport { InputAddon, InputAddonProps } from './InputAddon'\nimport { useInputGroup } from './InputGroupContext'\n\nexport type InputTrailingAddonProps = InputAddonProps & {\n ref?: Ref<HTMLDivElement>\n}\n\n/** An addon displayed after the input. Renders a <span> element. */\nconst Root = ({ className, ref, ...others }: InputTrailingAddonProps) => {\n const { disabled, readOnly } = useInputGroup()\n const isInactive = disabled || readOnly\n\n return (\n <div className={cx('rounded-r-lg', isInactive ? 'bg-on-surface/dim-5' : null)}>\n <InputAddon\n ref={ref}\n className={cx(className, 'rounded-l-0! ml-[-1px] rounded-r-lg')}\n {...others}\n />\n </div>\n )\n}\n\nexport const InputTrailingAddon = Object.assign(Root, {\n id: 'TrailingAddon',\n})\n\nRoot.displayName = 'InputGroup.TrailingAddon'\n","import { cx } from 'class-variance-authority'\n\nimport { InputIcon, InputIconProps } from './InputIcon'\n\nexport type InputTrailingIconProps = InputIconProps\n\n/** An icon displayed after the input text. Renders a <div> element. */\nexport const InputTrailingIcon = ({ className, ...others }: InputTrailingIconProps) => (\n <InputIcon className={cx(className, 'right-lg text-body-1')} {...others} />\n)\n\nInputTrailingIcon.id = 'TrailingIcon'\nInputTrailingIcon.displayName = 'InputGroup.TrailingIcon'\n","import { cva, VariantProps } from 'class-variance-authority'\n\nexport const inputStyles = cva(\n [\n 'relative',\n 'border-sm',\n 'peer',\n 'w-full',\n 'appearance-none outline-hidden',\n 'bg-surface',\n 'text-ellipsis text-body-1 text-on-surface',\n 'caret-neutral',\n '[&:-webkit-autofill]:[-webkit-text-fill-color:var(--color-on-surface)]',\n 'autofill:shadow-surface autofill:shadow-[inset_0_0_0px_1000px]',\n 'disabled:cursor-not-allowed disabled:border-outline disabled:bg-on-surface/dim-5 disabled:text-on-surface/dim-3',\n 'read-only:cursor-default read-only:pointer-events-none read-only:bg-on-surface/dim-5',\n 'focus:ring-1 focus:ring-inset focus:ring-focus focus:border-focus',\n ],\n {\n variants: {\n /**\n * Change the component to the HTML tag or custom component of the only child.\n */\n asChild: {\n true: ['min-h-sz-44'],\n false: ['h-sz-44'],\n },\n /**\n * Color scheme of the button.\n */\n intent: {\n neutral: ['border-outline', 'default:hover:border-outline-high'],\n success: ['default:border-success'],\n alert: ['default:border-alert'],\n error: ['default:border-error'],\n },\n /**\n * Sets if there is an addon before the input text.\n */\n hasLeadingAddon: {\n true: ['rounded-l-0'],\n false: ['rounded-l-input'],\n },\n /**\n * Sets if there is an addon after the input text.\n */\n hasTrailingAddon: {\n true: ['rounded-r-0'],\n false: ['rounded-r-input'],\n },\n /**\n * Sets if there is an icon before the input text.\n */\n hasLeadingIcon: {\n true: ['pl-3xl'],\n false: ['pl-lg'],\n },\n /**\n * Sets if there is an icon after the input text.\n */\n hasTrailingIcon: { true: '' },\n /**\n * Sets if there is a button to clear the input text.\n */\n hasClearButton: { true: '' },\n },\n compoundVariants: [\n {\n hasTrailingIcon: false,\n hasClearButton: false,\n class: 'pr-lg',\n },\n {\n hasTrailingIcon: true,\n hasClearButton: false,\n class: 'pr-3xl',\n },\n {\n hasTrailingIcon: false,\n hasClearButton: true,\n class: 'pr-3xl',\n },\n {\n hasTrailingIcon: true,\n hasClearButton: true,\n class: 'pr-[calc(var(--spacing-3xl)*2)]',\n },\n ],\n defaultVariants: {\n intent: 'neutral',\n },\n }\n)\n\nexport type InputStylesProps = VariantProps<typeof inputStyles>\n","import { useFormFieldControl } from '@spark-ui/components/form-field'\nimport { ChangeEventHandler, ComponentPropsWithoutRef, KeyboardEventHandler, Ref } from 'react'\n\nimport { Slot } from '../slot'\nimport { inputStyles } from './Input.styles'\nimport { useInputGroup } from './InputGroupContext'\n\ntype InputPrimitiveProps = ComponentPropsWithoutRef<'input'>\n\nexport interface InputProps extends InputPrimitiveProps {\n asChild?: boolean\n onValueChange?: (value: string) => void\n ref?: Ref<HTMLInputElement>\n}\n\nconst Root = ({\n className,\n asChild = false,\n onValueChange,\n onChange,\n onKeyDown,\n disabled: disabledProp,\n readOnly: readOnlyProp,\n ref,\n ...others\n}: InputProps) => {\n const field = useFormFieldControl()\n const group = useInputGroup()\n\n const { id, name, isInvalid, isRequired, description } = field\n const {\n hasLeadingAddon,\n hasTrailingAddon,\n hasLeadingIcon,\n hasTrailingIcon,\n hasClearButton,\n onClear,\n } = group\n const Component = asChild ? Slot : 'input'\n const state = field.state || group.state\n const disabled = field.disabled || group.disabled || disabledProp\n const readOnly = field.readOnly || group.readOnly || readOnlyProp\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = event => {\n if (onChange) {\n onChange(event)\n }\n\n if (onValueChange) {\n onValueChange(event.target.value)\n }\n }\n\n const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = event => {\n if (onKeyDown) {\n onKeyDown(event)\n }\n\n if (hasClearButton && onClear && event.key === 'Escape') {\n onClear()\n }\n }\n\n return (\n <Component\n data-spark-component=\"input\"\n ref={ref}\n id={id}\n name={name}\n className={inputStyles({\n asChild,\n className,\n intent: state,\n hasLeadingAddon: !!hasLeadingAddon,\n hasTrailingAddon: !!hasTrailingAddon,\n hasLeadingIcon: !!hasLeadingIcon,\n hasTrailingIcon: !!hasTrailingIcon,\n hasClearButton: !!hasClearButton,\n })}\n disabled={disabled}\n readOnly={readOnly}\n required={isRequired}\n aria-describedby={description}\n aria-invalid={isInvalid}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n {...others}\n />\n )\n}\n\n/**\n * A text input field that allows users to enter and edit text content.\n */\nexport const Input = Object.assign(Root, {\n id: 'Input',\n})\n\nRoot.displayName = 'Input'\n","import { InputClearButton } from './InputClearButton'\nimport { InputGroup as Root } from './InputGroup'\nimport { InputLeadingAddon } from './InputLeadingAddon'\nimport { InputLeadingIcon } from './InputLeadingIcon'\nimport { InputTrailingAddon } from './InputTrailingAddon'\nimport { InputTrailingIcon } from './InputTrailingIcon'\n\nexport * from './Input'\n\n/**\n * A wrapper component that combines an Input with addons, icons, and interactive elements\n * to create more complex text input patterns like search bars, password fields, or URL inputs.\n */\nexport const InputGroup: typeof Root & {\n LeadingAddon: typeof InputLeadingAddon\n TrailingAddon: typeof InputTrailingAddon\n LeadingIcon: typeof InputLeadingIcon\n TrailingIcon: typeof InputTrailingIcon\n ClearButton: typeof InputClearButton\n} = Object.assign(Root, {\n LeadingAddon: InputLeadingAddon,\n TrailingAddon: InputTrailingAddon,\n LeadingIcon: InputLeadingIcon,\n TrailingIcon: InputTrailingIcon,\n ClearButton: InputClearButton,\n})\n\nInputGroup.displayName = 'InputGroup'\nInputLeadingAddon.displayName = 'InputGroup.LeadingAddon'\nInputTrailingAddon.displayName = 'InputGroup.TrailingAddon'\nInputLeadingIcon.displayName = 'InputGroup.LeadingIcon'\nInputTrailingIcon.displayName = 'InputGroup.TrailingIcon'\nInputClearButton.displayName = 'InputGroup.ClearButton'\n\nexport { useInputGroup } from './InputGroupContext'\nexport { type InputGroupProps } from './InputGroup'\nexport { type InputLeadingIconProps } from './InputLeadingIcon'\nexport { type InputTrailingIconProps } from './InputTrailingIcon'\nexport { type InputLeadingAddonProps } from './InputLeadingAddon'\nexport { type InputTrailingAddonProps } from './InputTrailingAddon'\nexport { type InputClearButtonProps } from './InputClearButton'\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ require(`./chunk-C91j1N6u.js`);const e=require(`./slot/index.js`),t=require(`./icon-CRPcdgYp.js`);let n=require(`class-variance-authority`),r=require(`react`),i=require(`react/jsx-runtime`),a=require(`@spark-ui/hooks/use-merge-refs`),o=require(`@spark-ui/components/form-field`),s=require(`@spark-ui/hooks/use-combined-state`),c=require(`@spark-ui/icons/DeleteOutline`);var l=(0,r.createContext)(null),u=()=>(0,r.useContext)(l)||{isStandalone:!0},d=({className:e,tabIndex:r=-1,onClick:a,inline:o=!1,ref:s,...l})=>{let{onClear:d,hasTrailingIcon:f}=u();return(0,i.jsx)(`button`,{ref:s,"data-spark-component":`input-clear-button`,className:(0,n.cx)(e,`pointer-events-auto absolute`,o?`h-sz-44 top-0 -translate-y-0`:`top-1/2 -translate-y-1/2`,`inline-flex h-full items-center justify-center outline-hidden`,`text-neutral hover:text-neutral-hovered`,f?`right-3xl px-sz-12`:`pl-md pr-lg right-0`),tabIndex:r,onClick:e=>{a&&a(e),d&&d()},type:`button`,...l,children:(0,i.jsx)(t.t,{size:`sm`,children:(0,i.jsx)(c.DeleteOutline,{})})})},f=Object.assign(d,{id:`ClearButton`});d.displayName=`InputGroup.ClearButton`;var p=(0,n.cva)([`relative inline-flex w-full`],{variants:{disabled:{true:[`cursor-not-allowed`,`relative`,`after:absolute`,`after:top-0`,`after:h-full`,`after:w-full`,`after:border-sm after:border-outline`,`after:rounded-lg`],false:`after:hidden`},readOnly:{true:[`relative`,`after:absolute`,`after:top-0`,`after:h-full`,`after:w-full`,`after:border-sm after:border-outline`,`after:rounded-lg`],false:`after:hidden`}}}),m=({className:e,children:t,state:n,disabled:c,readOnly:u,onClear:d,ref:f,...m})=>{let h=e=>e?e.type.id:``,g=(...e)=>_.find(t=>e.includes(h(t)||``)),_=r.Children.toArray(t).filter(r.isValidElement),v=g(`Input`),y=v?.props||{},b=(0,r.useRef)(null),x=(0,r.useRef)(d),S=(0,a.useMergeRefs)(v?.ref,b),[C,w]=(0,s.useCombinedState)(y.value,y.defaultValue,y.onValueChange),T=(0,o.useFormFieldControl)(),E=T.state??n,D=T.disabled||!!c,O=T.readOnly||!!u,k=g(`LeadingAddon`),A=g(`LeadingIcon`),j=g(`ClearButton`),M=g(`TrailingIcon`),N=g(`TrailingAddon`),P=!!k,F=!!N,I=!!A,L=!!M,R=!!C&&!!j&&!D&&!O,z=e=>{y.onChange&&y.onChange(e),w(e.target.value)},B=(0,r.useCallback)(()=>{x.current&&x.current(),w(``),b.current.focus()},[w]),V=(0,r.useMemo)(()=>({state:E,disabled:D,readOnly:O,hasLeadingIcon:I,hasTrailingIcon:L,hasLeadingAddon:P,hasTrailingAddon:F,hasClearButton:R,onClear:B}),[E,D,O,I,L,P,F,R,B]);(0,r.useEffect)(()=>{x.current=d},[d]);let H=b.current?.value;return(0,i.jsx)(l,{value:V,children:(0,i.jsxs)(`div`,{"data-spark-component":`input-group`,ref:f,className:p({disabled:D,readOnly:O,className:e}),...m,children:[P&&k,(0,i.jsxs)(`div`,{className:`relative inline-flex w-full`,children:[v&&(0,r.cloneElement)(v,{value:C??H??``,ref:S,defaultValue:void 0,onChange:z}),A,R&&j,M]}),F&&N]})})};m.displayName=`InputGroup`;var h=(0,n.cva)([`overflow-hidden`,`border-sm`,`shrink-0`,`h-full`,`focus-visible:relative focus-visible:z-raised`,`mx-0`],{variants:{asChild:{false:[`flex`,`items-center`,`px-lg`]},intent:{neutral:`border-outline`,error:`border-error`,alert:`border-alert`,success:`border-success`},disabled:{true:[`pointer-events-none border-outline!`]},readOnly:{true:[`pointer-events-none`]},design:{text:``,solid:``,inline:``}},compoundVariants:[{disabled:!1,readOnly:!1,design:`text`,class:[`bg-surface`,`text-on-surface`]},{disabled:!0,design:`text`,class:[`text-on-surface/dim-3`]},{disabled:!0,design:[`solid`,`inline`],class:[`opacity-dim-3`]}],defaultVariants:{intent:`neutral`}}),g=({asChild:t,className:n,children:a,ref:o,...s})=>{let{state:c,disabled:l,readOnly:d}=u(),f=typeof a==`string`,p=!!(!f&&t),m=f?a:r.Children.only(a),g=p&&!f?e.Slot:`div`;return(0,i.jsx)(g,{ref:o,"data-spark-component":`input-addon`,className:h({className:n,intent:c,disabled:l,readOnly:d,asChild:p,design:f?`text`:p?`solid`:`inline`}),...l&&{tabIndex:-1},...s,children:m})};g.displayName=`InputGroup.Addon`;var _=({className:e,ref:t,...r})=>{let{disabled:a,readOnly:o}=u();return(0,i.jsx)(`div`,{className:(0,n.cx)(`rounded-l-lg`,a||o?`bg-on-surface/dim-5`:null),children:(0,i.jsx)(g,{ref:t,className:(0,n.cx)(e,`rounded-r-0! mr-[-1px] rounded-l-lg`),...r})})},v=Object.assign(_,{id:`LeadingAddon`});_.displayName=`InputGroup.LeadingAddon`;var y=({className:e,intent:r,children:a,...o})=>{let{disabled:s,readOnly:c}=u();return(0,i.jsx)(t.t,{"data-spark-component":`input-icon`,intent:r,className:(0,n.cx)(e,`pointer-events-none absolute top-[calc(var(--spacing-sz-44)/2)] -translate-y-1/2`,r?void 0:`text-neutral peer-focus:text-outline-high`,s||c?`opacity-dim-3`:void 0),...o,children:a})};y.displayName=`InputGroup.Icon`;var b=({className:e,...t})=>(0,i.jsx)(y,{className:(0,n.cx)(e,`left-lg text-body-1`),...t});b.id=`LeadingIcon`,b.displayName=`InputGroup.LeadingIcon`;var x=({className:e,ref:t,...r})=>{let{disabled:a,readOnly:o}=u();return(0,i.jsx)(`div`,{className:(0,n.cx)(`rounded-r-lg`,a||o?`bg-on-surface/dim-5`:null),children:(0,i.jsx)(g,{ref:t,className:(0,n.cx)(e,`rounded-l-0! ml-[-1px] rounded-r-lg`),...r})})},S=Object.assign(x,{id:`TrailingAddon`});x.displayName=`InputGroup.TrailingAddon`;var C=({className:e,...t})=>(0,i.jsx)(y,{className:(0,n.cx)(e,`right-lg text-body-1`),...t});C.id=`TrailingIcon`,C.displayName=`InputGroup.TrailingIcon`;var w=(0,n.cva)([`relative`,`border-sm`,`peer`,`w-full`,`appearance-none outline-hidden`,`bg-surface`,`text-ellipsis text-body-1 text-on-surface`,`caret-neutral`,`[&:-webkit-autofill]:[-webkit-text-fill-color:var(--color-on-surface)]`,`autofill:shadow-surface autofill:shadow-[inset_0_0_0px_1000px]`,`disabled:cursor-not-allowed disabled:border-outline disabled:bg-on-surface/dim-5 disabled:text-on-surface/dim-3`,`read-only:cursor-default read-only:pointer-events-none read-only:bg-on-surface/dim-5`,`focus:ring-1 focus:ring-inset focus:ring-focus focus:border-focus`],{variants:{asChild:{true:[`min-h-sz-44`],false:[`h-sz-44`]},intent:{neutral:[`border-outline`,`default:hover:border-outline-high`],success:[`default:border-success`],alert:[`default:border-alert`],error:[`default:border-error`]},hasLeadingAddon:{true:[`rounded-l-0`],false:[`rounded-l-input`]},hasTrailingAddon:{true:[`rounded-r-0`],false:[`rounded-r-input`]},hasLeadingIcon:{true:[`pl-3xl`],false:[`pl-lg`]},hasTrailingIcon:{true:``},hasClearButton:{true:``}},compoundVariants:[{hasTrailingIcon:!1,hasClearButton:!1,class:`pr-lg`},{hasTrailingIcon:!0,hasClearButton:!1,class:`pr-3xl`},{hasTrailingIcon:!1,hasClearButton:!0,class:`pr-3xl`},{hasTrailingIcon:!0,hasClearButton:!0,class:`pr-[calc(var(--spacing-3xl)*2)]`}],defaultVariants:{intent:`neutral`}}),T=({className:t,asChild:n=!1,onValueChange:r,onChange:a,onKeyDown:s,disabled:c,readOnly:l,ref:d,...f})=>{let p=(0,o.useFormFieldControl)(),m=u(),{id:h,name:g,isInvalid:_,isRequired:v,description:y}=p,{hasLeadingAddon:b,hasTrailingAddon:x,hasLeadingIcon:S,hasTrailingIcon:C,hasClearButton:T,onClear:E}=m,D=n?e.Slot:`input`,O=p.state||m.state,k=p.disabled||m.disabled||c,A=p.readOnly||m.readOnly||l;return(0,i.jsx)(D,{"data-spark-component":`input`,ref:d,id:h,name:g,className:w({asChild:n,className:t,intent:O,hasLeadingAddon:!!b,hasTrailingAddon:!!x,hasLeadingIcon:!!S,hasTrailingIcon:!!C,hasClearButton:!!T}),disabled:k,readOnly:A,required:v,"aria-describedby":y,"aria-invalid":_,onChange:e=>{a&&a(e),r&&r(e.target.value)},onKeyDown:e=>{s&&s(e),T&&E&&e.key===`Escape`&&E()},...f})},E=Object.assign(T,{id:`Input`});T.displayName=`Input`;var D=Object.assign(m,{LeadingAddon:v,TrailingAddon:S,LeadingIcon:b,TrailingIcon:C,ClearButton:f});D.displayName=`InputGroup`,v.displayName=`InputGroup.LeadingAddon`,S.displayName=`InputGroup.TrailingAddon`,b.displayName=`InputGroup.LeadingIcon`,C.displayName=`InputGroup.TrailingIcon`,f.displayName=`InputGroup.ClearButton`,Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return D}});
2
+ //# sourceMappingURL=input-DIGSkxbh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-DIGSkxbh.js","names":[],"sources":["../src/input/InputGroupContext.ts","../src/input/InputClearButton.tsx","../src/input/InputGroup.styles.ts","../src/input/InputGroup.tsx","../src/input/InputAddon.styles.ts","../src/input/InputAddon.tsx","../src/input/InputLeadingAddon.tsx","../src/input/InputIcon.tsx","../src/input/InputLeadingIcon.tsx","../src/input/InputTrailingAddon.tsx","../src/input/InputTrailingIcon.tsx","../src/input/Input.styles.ts","../src/input/Input.tsx","../src/input/index.ts"],"sourcesContent":["import { createContext, useContext } from 'react'\n\nexport interface InputGroupContextValue {\n disabled?: boolean\n readOnly?: boolean\n hasLeadingIcon: boolean\n hasTrailingIcon: boolean\n hasLeadingAddon: boolean\n hasTrailingAddon: boolean\n hasClearButton: boolean\n state: null | undefined | 'error' | 'alert' | 'success'\n isStandalone?: boolean\n onClear: () => void\n}\n\nexport const InputGroupContext = createContext<Partial<InputGroupContextValue> | null>(null)\n\nexport const useInputGroup = () => {\n const context = useContext(InputGroupContext)\n\n return context || { isStandalone: true }\n}\n","import { DeleteOutline } from '@spark-ui/icons/DeleteOutline'\nimport { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, MouseEventHandler, Ref } from 'react'\n\nimport { Icon } from '../icon'\nimport { useInputGroup } from './InputGroupContext'\n\nexport interface InputClearButtonProps extends ComponentPropsWithoutRef<'button'> {\n 'aria-label': string\n inline?: boolean\n ref?: Ref<HTMLButtonElement>\n}\n\n/** A button to clear the input value. Renders a <button> element. */\nconst Root = ({\n className,\n tabIndex = -1,\n onClick,\n inline = false,\n ref,\n ...others\n}: InputClearButtonProps) => {\n const { onClear, hasTrailingIcon } = useInputGroup()\n\n const handleClick: MouseEventHandler<HTMLButtonElement> = event => {\n if (onClick) {\n onClick(event)\n }\n\n if (onClear) {\n onClear()\n }\n }\n\n return (\n <button\n ref={ref}\n data-spark-component=\"input-clear-button\"\n className={cx(\n className,\n 'pointer-events-auto absolute',\n inline ? 'h-sz-44 top-0 -translate-y-0' : 'top-1/2 -translate-y-1/2',\n 'inline-flex h-full items-center justify-center outline-hidden',\n 'text-neutral hover:text-neutral-hovered',\n hasTrailingIcon ? 'right-3xl px-sz-12' : 'pl-md pr-lg right-0'\n )}\n tabIndex={tabIndex}\n onClick={handleClick}\n type=\"button\"\n {...others}\n >\n <Icon size=\"sm\">\n <DeleteOutline />\n </Icon>\n </button>\n )\n}\n\nexport const InputClearButton = Object.assign(Root, {\n id: 'ClearButton',\n})\n\nRoot.displayName = 'InputGroup.ClearButton'\n","import { cva, VariantProps } from 'class-variance-authority'\n\nexport const inputGroupStyles = cva(['relative inline-flex w-full'], {\n variants: {\n /**\n * When `true`, prevents the user from interacting.\n */\n disabled: {\n true: [\n 'cursor-not-allowed',\n 'relative',\n 'after:absolute',\n 'after:top-0',\n 'after:h-full',\n 'after:w-full',\n 'after:border-sm after:border-outline',\n 'after:rounded-lg',\n ],\n false: 'after:hidden',\n },\n /**\n * Sets the component as interactive or not.\n */\n readOnly: {\n true: [\n 'relative',\n 'after:absolute',\n 'after:top-0',\n 'after:h-full',\n 'after:w-full',\n 'after:border-sm after:border-outline',\n 'after:rounded-lg',\n ],\n false: 'after:hidden',\n },\n },\n})\n\nexport type InputGroupStylesProps = VariantProps<typeof inputGroupStyles>\n","/* eslint-disable max-lines-per-function */\n\nimport { useFormFieldControl } from '@spark-ui/components/form-field'\nimport { useCombinedState } from '@spark-ui/hooks/use-combined-state'\nimport { useMergeRefs } from '@spark-ui/hooks/use-merge-refs'\nimport {\n ChangeEventHandler,\n Children,\n cloneElement,\n ComponentPropsWithoutRef,\n DetailedReactHTMLElement,\n FC,\n isValidElement,\n PropsWithChildren,\n ReactElement,\n Ref,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n} from 'react'\n\nimport { InputProps } from './Input'\nimport { inputGroupStyles, InputGroupStylesProps } from './InputGroup.styles'\nimport { InputGroupContext } from './InputGroupContext'\n\nexport interface InputGroupProps extends ComponentPropsWithoutRef<'div'>, InputGroupStylesProps {\n /**\n * Use `state` prop to assign a specific state to the group, choosing from: `error`, `alert` and `success`. By doing so, the outline styles will be updated.\n */\n state?: 'error' | 'alert' | 'success'\n /**\n * Function handler to be executed after the input has been cleared.\n */\n onClear?: () => void\n ref?: Ref<HTMLDivElement>\n}\n\nexport const InputGroup = ({\n className,\n children: childrenProp,\n state: stateProp,\n disabled: disabledProp,\n readOnly: readOnlyProp,\n onClear,\n ref: forwardedRef,\n ...others\n}: PropsWithChildren<InputGroupProps>) => {\n const getElementId = (element?: ReactElement) => {\n return element ? (element.type as FC & { id?: string }).id : ''\n }\n\n const findElement = (...values: string[]) => {\n return children.find(child => values.includes(getElementId(child) || ''))\n }\n\n const children = Children.toArray(childrenProp).filter(isValidElement)\n const input = findElement('Input') as\n | DetailedReactHTMLElement<InputProps, HTMLInputElement>\n | undefined\n const props = input?.props || {}\n\n const inputRef = useRef<HTMLInputElement>(null!)\n const onClearRef = useRef(onClear)\n const ref = useMergeRefs<HTMLInputElement>(input?.ref, inputRef)\n const [value, onChange] = useCombinedState(\n props.value as string,\n props.defaultValue as string,\n props.onValueChange\n )\n\n // Data derivated from FormField context\n const field = useFormFieldControl()\n const state = field.state ?? stateProp\n const disabled = field.disabled || !!disabledProp\n const readOnly = field.readOnly || !!readOnlyProp\n\n // InputGroup elements (in visual order)\n const leadingAddon = findElement('LeadingAddon')\n const leadingIcon = findElement('LeadingIcon')\n const clearButton = findElement('ClearButton')\n const trailingIcon = findElement('TrailingIcon')\n const trailingAddon = findElement('TrailingAddon')\n\n // Acknowledge which subComponents are used in the compound context\n const hasLeadingAddon = !!leadingAddon\n const hasTrailingAddon = !!trailingAddon\n const hasLeadingIcon = !!leadingIcon\n const hasTrailingIcon = !!trailingIcon\n const hasClearButton = !!value && !!clearButton && !disabled && !readOnly\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = event => {\n if (props.onChange) {\n props.onChange(event)\n }\n\n onChange(event.target.value)\n }\n\n const handleClear = useCallback(() => {\n if (onClearRef.current) {\n onClearRef.current()\n }\n\n onChange('')\n\n inputRef.current.focus()\n }, [onChange])\n\n const current = useMemo(() => {\n return {\n state,\n disabled,\n readOnly,\n hasLeadingIcon,\n hasTrailingIcon,\n hasLeadingAddon,\n hasTrailingAddon,\n hasClearButton,\n onClear: handleClear,\n }\n }, [\n state,\n disabled,\n readOnly,\n hasLeadingIcon,\n hasTrailingIcon,\n hasLeadingAddon,\n hasTrailingAddon,\n hasClearButton,\n handleClear,\n ])\n\n useEffect(() => {\n onClearRef.current = onClear\n }, [onClear])\n\n // Preserve the input value when cloning. Some libraries like React Hook Form\n // only expose a ref (via `register`) without direct value access, so we need\n // to manually retrieve the value from the ref to avoid losing it.\n const inputRefValue = inputRef.current?.value\n\n return (\n <InputGroupContext value={current}>\n <div\n data-spark-component=\"input-group\"\n ref={forwardedRef}\n className={inputGroupStyles({ disabled, readOnly, className })}\n {...others}\n >\n {hasLeadingAddon && leadingAddon}\n\n <div className=\"relative inline-flex w-full\">\n {input &&\n cloneElement(input, {\n value: value ?? inputRefValue ?? '',\n ref,\n defaultValue: undefined,\n onChange: handleChange,\n })}\n\n {leadingIcon}\n\n {hasClearButton && clearButton}\n\n {trailingIcon}\n </div>\n\n {hasTrailingAddon && trailingAddon}\n </div>\n </InputGroupContext>\n )\n}\n\nInputGroup.displayName = 'InputGroup'\n","import { cva, VariantProps } from 'class-variance-authority'\n\nexport const inputAddonStyles = cva(\n [\n 'overflow-hidden',\n 'border-sm',\n 'shrink-0',\n 'h-full',\n 'focus-visible:relative focus-visible:z-raised',\n 'mx-0',\n ],\n {\n variants: {\n /**\n * Change the component to the HTML tag or custom component of the only child.\n */\n asChild: { false: ['flex', 'items-center', 'px-lg'] },\n intent: {\n neutral: 'border-outline',\n error: 'border-error',\n alert: 'border-alert',\n success: 'border-success',\n },\n /**\n * Disable the input addon, preventing user interaction and adding opacity.\n */\n disabled: {\n true: ['pointer-events-none border-outline!'],\n },\n /**\n * Changes input addon styles based on the read only status from the input.\n */\n readOnly: {\n true: ['pointer-events-none'],\n },\n /**\n * Main style of the input addon.\n */\n design: {\n text: '',\n solid: '',\n inline: '',\n },\n },\n compoundVariants: [\n {\n disabled: false,\n readOnly: false,\n design: 'text',\n class: ['bg-surface', 'text-on-surface'],\n },\n {\n disabled: true,\n design: 'text',\n class: ['text-on-surface/dim-3'],\n },\n {\n disabled: true,\n design: ['solid', 'inline'],\n class: ['opacity-dim-3'],\n },\n ],\n defaultVariants: {\n intent: 'neutral',\n },\n }\n)\n\nexport type InputAddonStylesProps = VariantProps<typeof inputAddonStyles>\n","import { Children, type ComponentPropsWithoutRef, type PropsWithChildren, Ref } from 'react'\n\nimport { Slot } from '../slot'\nimport { inputAddonStyles, type InputAddonStylesProps } from './InputAddon.styles'\nimport { useInputGroup } from './InputGroupContext'\n\nexport interface InputAddonProps\n extends ComponentPropsWithoutRef<'div'>, Omit<InputAddonStylesProps, 'intent' | 'disabled'> {\n ref?: Ref<HTMLDivElement>\n}\n\nexport const InputAddon = ({\n asChild: asChildProp,\n className,\n children,\n ref,\n ...others\n}: PropsWithChildren<InputAddonProps>) => {\n const { state, disabled, readOnly } = useInputGroup()\n\n const isRawText = typeof children === 'string'\n const asChild = !!(isRawText ? false : asChildProp)\n const child = isRawText ? children : Children.only(children)\n const Component = asChild && !isRawText ? Slot : 'div'\n\n const getDesign = (): InputAddonStylesProps['design'] => {\n if (isRawText) return 'text'\n\n return asChild ? 'solid' : 'inline'\n }\n\n const design = getDesign()\n\n return (\n <Component\n ref={ref}\n data-spark-component=\"input-addon\"\n className={inputAddonStyles({\n className,\n intent: state,\n disabled,\n readOnly,\n asChild,\n design,\n })}\n {...(disabled && { tabIndex: -1 })}\n {...others}\n >\n {child}\n </Component>\n )\n}\n\nInputAddon.displayName = 'InputGroup.Addon'\n","import { cx } from 'class-variance-authority'\nimport { Ref } from 'react'\n\nimport { InputAddon, InputAddonProps } from './InputAddon'\nimport { useInputGroup } from './InputGroupContext'\n\nexport type InputLeadingAddonProps = InputAddonProps & {\n ref?: Ref<HTMLDivElement>\n}\n\n/**\n * An addon displayed before the input. Renders a <span> element.\n */\nconst Root = ({ className, ref, ...others }: InputLeadingAddonProps) => {\n const { disabled, readOnly } = useInputGroup()\n const isInactive = disabled || readOnly\n\n return (\n <div className={cx('rounded-l-lg', isInactive ? 'bg-on-surface/dim-5' : null)}>\n <InputAddon\n ref={ref}\n className={cx(className, 'rounded-r-0! mr-[-1px] rounded-l-lg')}\n {...others}\n />\n </div>\n )\n}\n\nexport const InputLeadingAddon = Object.assign(Root, {\n id: 'LeadingAddon',\n})\n\nRoot.displayName = 'InputGroup.LeadingAddon'\n","import { cx } from 'class-variance-authority'\n\nimport { Icon, type IconProps } from '../icon'\nimport { useInputGroup } from './InputGroupContext'\n\nexport type InputIconProps = IconProps\n\nexport const InputIcon = ({ className, intent, children, ...others }: InputIconProps) => {\n const { disabled, readOnly } = useInputGroup()\n const isInactive = disabled || readOnly\n\n return (\n <Icon\n data-spark-component=\"input-icon\"\n intent={intent}\n className={cx(\n className,\n 'pointer-events-none absolute top-[calc(var(--spacing-sz-44)/2)] -translate-y-1/2',\n intent ? undefined : 'text-neutral peer-focus:text-outline-high',\n isInactive ? 'opacity-dim-3' : undefined\n )}\n {...others}\n >\n {children}\n </Icon>\n )\n}\n\nInputIcon.displayName = 'InputGroup.Icon'\n","import { cx } from 'class-variance-authority'\n\nimport { InputIcon, InputIconProps } from './InputIcon'\n\nexport type InputLeadingIconProps = InputIconProps\n\n/** An icon displayed before the input text. Renders a <div> element. */\nexport const InputLeadingIcon = ({ className, ...others }: InputLeadingIconProps) => (\n <InputIcon className={cx(className, 'left-lg text-body-1')} {...others} />\n)\n\nInputLeadingIcon.id = 'LeadingIcon'\nInputLeadingIcon.displayName = 'InputGroup.LeadingIcon'\n","import { cx } from 'class-variance-authority'\nimport { Ref } from 'react'\n\nimport { InputAddon, InputAddonProps } from './InputAddon'\nimport { useInputGroup } from './InputGroupContext'\n\nexport type InputTrailingAddonProps = InputAddonProps & {\n ref?: Ref<HTMLDivElement>\n}\n\n/** An addon displayed after the input. Renders a <span> element. */\nconst Root = ({ className, ref, ...others }: InputTrailingAddonProps) => {\n const { disabled, readOnly } = useInputGroup()\n const isInactive = disabled || readOnly\n\n return (\n <div className={cx('rounded-r-lg', isInactive ? 'bg-on-surface/dim-5' : null)}>\n <InputAddon\n ref={ref}\n className={cx(className, 'rounded-l-0! ml-[-1px] rounded-r-lg')}\n {...others}\n />\n </div>\n )\n}\n\nexport const InputTrailingAddon = Object.assign(Root, {\n id: 'TrailingAddon',\n})\n\nRoot.displayName = 'InputGroup.TrailingAddon'\n","import { cx } from 'class-variance-authority'\n\nimport { InputIcon, InputIconProps } from './InputIcon'\n\nexport type InputTrailingIconProps = InputIconProps\n\n/** An icon displayed after the input text. Renders a <div> element. */\nexport const InputTrailingIcon = ({ className, ...others }: InputTrailingIconProps) => (\n <InputIcon className={cx(className, 'right-lg text-body-1')} {...others} />\n)\n\nInputTrailingIcon.id = 'TrailingIcon'\nInputTrailingIcon.displayName = 'InputGroup.TrailingIcon'\n","import { cva, VariantProps } from 'class-variance-authority'\n\nexport const inputStyles = cva(\n [\n 'relative',\n 'border-sm',\n 'peer',\n 'w-full',\n 'appearance-none outline-hidden',\n 'bg-surface',\n 'text-ellipsis text-body-1 text-on-surface',\n 'caret-neutral',\n '[&:-webkit-autofill]:[-webkit-text-fill-color:var(--color-on-surface)]',\n 'autofill:shadow-surface autofill:shadow-[inset_0_0_0px_1000px]',\n 'disabled:cursor-not-allowed disabled:border-outline disabled:bg-on-surface/dim-5 disabled:text-on-surface/dim-3',\n 'read-only:cursor-default read-only:pointer-events-none read-only:bg-on-surface/dim-5',\n 'focus:ring-1 focus:ring-inset focus:ring-focus focus:border-focus',\n ],\n {\n variants: {\n /**\n * Change the component to the HTML tag or custom component of the only child.\n */\n asChild: {\n true: ['min-h-sz-44'],\n false: ['h-sz-44'],\n },\n /**\n * Color scheme of the button.\n */\n intent: {\n neutral: ['border-outline', 'default:hover:border-outline-high'],\n success: ['default:border-success'],\n alert: ['default:border-alert'],\n error: ['default:border-error'],\n },\n /**\n * Sets if there is an addon before the input text.\n */\n hasLeadingAddon: {\n true: ['rounded-l-0'],\n false: ['rounded-l-input'],\n },\n /**\n * Sets if there is an addon after the input text.\n */\n hasTrailingAddon: {\n true: ['rounded-r-0'],\n false: ['rounded-r-input'],\n },\n /**\n * Sets if there is an icon before the input text.\n */\n hasLeadingIcon: {\n true: ['pl-3xl'],\n false: ['pl-lg'],\n },\n /**\n * Sets if there is an icon after the input text.\n */\n hasTrailingIcon: { true: '' },\n /**\n * Sets if there is a button to clear the input text.\n */\n hasClearButton: { true: '' },\n },\n compoundVariants: [\n {\n hasTrailingIcon: false,\n hasClearButton: false,\n class: 'pr-lg',\n },\n {\n hasTrailingIcon: true,\n hasClearButton: false,\n class: 'pr-3xl',\n },\n {\n hasTrailingIcon: false,\n hasClearButton: true,\n class: 'pr-3xl',\n },\n {\n hasTrailingIcon: true,\n hasClearButton: true,\n class: 'pr-[calc(var(--spacing-3xl)*2)]',\n },\n ],\n defaultVariants: {\n intent: 'neutral',\n },\n }\n)\n\nexport type InputStylesProps = VariantProps<typeof inputStyles>\n","import { useFormFieldControl } from '@spark-ui/components/form-field'\nimport { ChangeEventHandler, ComponentPropsWithoutRef, KeyboardEventHandler, Ref } from 'react'\n\nimport { Slot } from '../slot'\nimport { inputStyles } from './Input.styles'\nimport { useInputGroup } from './InputGroupContext'\n\ntype InputPrimitiveProps = ComponentPropsWithoutRef<'input'>\n\nexport interface InputProps extends InputPrimitiveProps {\n asChild?: boolean\n onValueChange?: (value: string) => void\n ref?: Ref<HTMLInputElement>\n}\n\nconst Root = ({\n className,\n asChild = false,\n onValueChange,\n onChange,\n onKeyDown,\n disabled: disabledProp,\n readOnly: readOnlyProp,\n ref,\n ...others\n}: InputProps) => {\n const field = useFormFieldControl()\n const group = useInputGroup()\n\n const { id, name, isInvalid, isRequired, description } = field\n const {\n hasLeadingAddon,\n hasTrailingAddon,\n hasLeadingIcon,\n hasTrailingIcon,\n hasClearButton,\n onClear,\n } = group\n const Component = asChild ? Slot : 'input'\n const state = field.state || group.state\n const disabled = field.disabled || group.disabled || disabledProp\n const readOnly = field.readOnly || group.readOnly || readOnlyProp\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = event => {\n if (onChange) {\n onChange(event)\n }\n\n if (onValueChange) {\n onValueChange(event.target.value)\n }\n }\n\n const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = event => {\n if (onKeyDown) {\n onKeyDown(event)\n }\n\n if (hasClearButton && onClear && event.key === 'Escape') {\n onClear()\n }\n }\n\n return (\n <Component\n data-spark-component=\"input\"\n ref={ref}\n id={id}\n name={name}\n className={inputStyles({\n asChild,\n className,\n intent: state,\n hasLeadingAddon: !!hasLeadingAddon,\n hasTrailingAddon: !!hasTrailingAddon,\n hasLeadingIcon: !!hasLeadingIcon,\n hasTrailingIcon: !!hasTrailingIcon,\n hasClearButton: !!hasClearButton,\n })}\n disabled={disabled}\n readOnly={readOnly}\n required={isRequired}\n aria-describedby={description}\n aria-invalid={isInvalid}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n {...others}\n />\n )\n}\n\n/**\n * A text input field that allows users to enter and edit text content.\n */\nexport const Input = Object.assign(Root, {\n id: 'Input',\n})\n\nRoot.displayName = 'Input'\n","import { InputClearButton } from './InputClearButton'\nimport { InputGroup as Root } from './InputGroup'\nimport { InputLeadingAddon } from './InputLeadingAddon'\nimport { InputLeadingIcon } from './InputLeadingIcon'\nimport { InputTrailingAddon } from './InputTrailingAddon'\nimport { InputTrailingIcon } from './InputTrailingIcon'\n\nexport * from './Input'\n\n/**\n * A wrapper component that combines an Input with addons, icons, and interactive elements\n * to create more complex text input patterns like search bars, password fields, or URL inputs.\n */\nexport const InputGroup: typeof Root & {\n LeadingAddon: typeof InputLeadingAddon\n TrailingAddon: typeof InputTrailingAddon\n LeadingIcon: typeof InputLeadingIcon\n TrailingIcon: typeof InputTrailingIcon\n ClearButton: typeof InputClearButton\n} = Object.assign(Root, {\n LeadingAddon: InputLeadingAddon,\n TrailingAddon: InputTrailingAddon,\n LeadingIcon: InputLeadingIcon,\n TrailingIcon: InputTrailingIcon,\n ClearButton: InputClearButton,\n})\n\nInputGroup.displayName = 'InputGroup'\nInputLeadingAddon.displayName = 'InputGroup.LeadingAddon'\nInputTrailingAddon.displayName = 'InputGroup.TrailingAddon'\nInputLeadingIcon.displayName = 'InputGroup.LeadingIcon'\nInputTrailingIcon.displayName = 'InputGroup.TrailingIcon'\nInputClearButton.displayName = 'InputGroup.ClearButton'\n\nexport { useInputGroup } from './InputGroupContext'\nexport { type InputGroupProps } from './InputGroup'\nexport { type InputLeadingIconProps } from './InputLeadingIcon'\nexport { type InputTrailingIconProps } from './InputTrailingIcon'\nexport { type InputLeadingAddonProps } from './InputLeadingAddon'\nexport { type InputTrailingAddonProps } from './InputTrailingAddon'\nexport { type InputClearButtonProps } from './InputClearButton'\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../chunk-C91j1N6u.js`);let e=require(`class-variance-authority`),t=require(`react`),n=require(`react/jsx-runtime`),r=require(`@spark-ui/components/form-field`);var i=(0,t.createContext)(null),a=()=>{let e=(0,t.useContext)(i);if(!e)throw Error(`InputOTP components must be used within InputOTP`);return e};(0,e.cva)([`relative`,`inline-flex`,`items-center`,`gap-sm`]);var o=(0,e.cva)([`relative h-[50px] w-sz-40`,`border-sm rounded-md`,`text-center text-display-3 text-on-surface`,`outline-hidden`,`transition-colors`,`flex items-center justify-center`,`data-[active=true]:ring-1`,`data-[active=true]:ring-inset`,`data-[active=true]:ring-l-2`,`data-[active=true]:border-focus`,`data-[active=true]:z-raised ring-focus`,`data-[disabled=true]:cursor-not-allowed`,`data-[disabled=true]:border-outline`,`data-[disabled=true]:bg-on-surface/dim-5`,`data-[disabled=true]:text-on-surface/dim-3`,`data-[readonly=true]:cursor-default`,`data-[readonly=true]:data-[active=false]:border-outline`,`data-[readonly=true]:bg-on-surface/dim-5`,`group-hover:data-[focus-target=true]:data-[disabled=false]:border-outline-high`],{variants:{intent:{neutral:[`data-[filled=true]:bg-neutral-container bg-surface border-outline`],success:[`border-success bg-success-container text-on-success-container`],alert:[`border-alert bg-alert-container text-on-alert-container`],error:[`border-error bg-error-container text-on-error-container`]}},defaultVariants:{intent:`neutral`}}),s=o,c=({index:e,className:t,...r})=>{let i=a(),s=e??0,c=i.slots[s];if(!c)return null;let{char:l,isActive:u,hasFakeCaret:d}=c,f=!l,p=f&&!d&&i.placeholder,m=s===i.activeIndex;return(0,n.jsxs)(`div`,{className:o({intent:i.intent,className:t}),"data-active":u,"data-disabled":i.disabled,"data-readonly":i.readOnly,"data-filled":!f,"data-focus-target":m,"data-valid":i.intent!==`error`,...r,children:[(0,n.jsx)(`span`,{className:p?`text-on-surface/dim-3`:``,children:i.type===`password`&&l?`•`:l||(!d&&i.placeholder?i.placeholder:``)}),d&&(0,n.jsx)(`span`,{className:`pointer-events-none absolute inset-0 flex items-center justify-center`,"aria-hidden":`true`,children:(0,n.jsx)(`span`,{className:`bg-on-surface animate-standalone-caret-blink h-sz-24 w-sz-2`})})]})};c.displayName=`InputOTP.Slot`;var l=`Backspace`,u=`ArrowLeft`,d=`ArrowUp`,f=`ArrowRight`,p=`ArrowDown`,m=`e`,h=({maxLength:e,type:n,value:i,defaultValue:a,onValueChange:o,isValid:s,disabledProp:c,readOnlyProp:h,autoFocus:g,forceUppercase:_,filterKeys:v,pattern:y,placeholder:b,nameProp:x})=>{let S=(0,t.useId)(),C=(0,t.useRef)(null),w=(0,t.useRef)(null),T=(0,r.useFormFieldControl)(),E=T.id??S,D=x??T.name,O=T.disabled??c,k=T.readOnly??h,A=T.isInvalid??!s,j=T.isRequired??!1,M=T.labelId,N=T.description,P=T.state,F=[`success`,`alert`,`error`].includes(P??``)?P:A?`error`:`neutral`,I=i===void 0?a:i,[L,R]=(0,t.useState)(_?I.toUpperCase():I),[z,B]=(0,t.useState)(!1),V=i===void 0?L:i,H=Math.min(V.length,e-1);(0,t.useEffect)(()=>{C.current&&C.current.setSelectionRange(H,H)},[H,V.length,e]);let U=(0,t.useMemo)(()=>Array.from({length:e},(e,t)=>({char:V[t]||``,isActive:t===H&&z,hasFakeCaret:t===H&&!V[t]&&!O&&!k&&z})),[e,V,H,z,O,k]);(0,t.useEffect)(()=>{C.current&&i!==void 0&&(C.current.value=i)},[i]),(0,t.useEffect)(()=>{g&&C.current&&C.current.focus()},[g]);let W=e=>{let t=e;if(_&&(t=t.toUpperCase()),n===`number`&&(t=t.replace(/[^\d]/g,``)),y)try{let e=y;y.startsWith(`^`)||(e=`^${y}$`);let n=new RegExp(e);t=t.split(``).filter(e=>n.test(e)).join(``)}catch(e){console.error(`Invalid pattern provided to InputOTP:`,y,e)}return t};return{uuid:E,inputRef:C,containerRef:w,name:D,disabled:O,readOnly:k,isInvalid:A,isRequired:j,description:N,maxLength:e,intent:F,currentValue:V,activeIndex:H,slots:U,contextValue:{value:V,maxLength:e,slots:U,activeIndex:H,intent:F,disabled:O,readOnly:k,placeholder:b,type:n},handleChange:t=>{if(O||k)return;let n=t.target.value,r=W(n).slice(0,e);o&&o(r),i===void 0&&R(r);let a=Math.min(r.length,e-1);C.current&&C.current.setSelectionRange(a,a)},handleKeyDown:e=>{if(O||k)return;let t=(e.ctrlKey||e.metaKey)&&[`a`,`c`,`v`,`x`].includes(e.key.toLowerCase());if(v.length>0&&v.includes(e.key)&&!t){e.preventDefault();return}switch(e.key){case l:e.preventDefault();let t=V.length;if(t>0){let e=V.slice(0,t-1);o&&o(e),i===void 0&&R(e);let n=Math.max(0,e.length);C.current&&C.current.setSelectionRange(n,n)}break;case u:case f:e.preventDefault();break;case d:case p:e.preventDefault();break;case m:case`E`:n===`number`&&e.preventDefault();break;default:break}},handleCopy:e=>{O||(e.preventDefault(),V.length>0&&e.clipboardData.setData(`text/plain`,V))},handlePaste:t=>{if(O||k)return;t.preventDefault();let n=t.clipboardData.getData(`text`);if(!n)return;let r=W(n).slice(0,e);o&&o(r),i===void 0&&R(r);let a=Math.min(r.length,e-1);C.current&&C.current.setSelectionRange(a,a)},handleFocus:()=>{if(B(!0),C.current){let t=Math.min(V.length,e-1);C.current.setSelectionRange(t,t)}},handleBlur:()=>{B(!1)},handleClick:()=>{C.current&&C.current.focus()},labelId:M}},g=e=>{let n=0;return t.Children.forEach(e,e=>{if((0,t.isValidElement)(e)){let t=e.props;e.type===c||e.type?.displayName===`InputOTP.Slot`?n++:t.children&&(n+=g(t.children))}}),n},_=(e,n=0)=>{let r=n;return[t.Children.map(e,e=>{if((0,t.isValidElement)(e)){let n=e.props;if(e.type===c||e.type?.displayName===`InputOTP.Slot`){let i=typeof n.index==`number`?n.index:r++;return(0,t.cloneElement)(e,{...n,index:i})}else if(n.children){let[i,a]=_(n.children,r);return r=a,(0,t.cloneElement)(e,{...e.props,children:i})}}return e}),r]},v=({maxLength:r,type:a=`text`,value:o,defaultValue:s=``,onValueChange:c,isValid:l=!0,disabled:u=!1,readOnly:d=!1,autoFocus:f=!1,autoComplete:p=`off`,forceUppercase:m=!1,filterKeys:v=[`-`,`.`],pattern:y,inputMode:b,placeholder:x=`-`,name:S,className:C,children:w,...T})=>{let E=(0,t.useMemo)(()=>{if(r!==void 0)return r;let e=g(w);return e>0?e:4},[r,w]),D=(0,t.useMemo)(()=>{let[e]=_(w);return e},[w]),{uuid:O,inputRef:k,containerRef:A,name:j,disabled:M,readOnly:N,isInvalid:P,isRequired:F,description:I,currentValue:L,contextValue:R,handleChange:z,handleKeyDown:B,handleCopy:V,handlePaste:H,handleFocus:U,handleBlur:W,handleClick:G,labelId:K}=h({maxLength:E,type:a,value:o,defaultValue:s,onValueChange:c,isValid:l,disabledProp:u,readOnlyProp:d,autoFocus:f,forceUppercase:m,filterKeys:v,pattern:y,placeholder:x,nameProp:S}),q=`aria-label`in T?T[`aria-label`]:void 0,{"aria-label":J,...Y}=T,X=K?{"aria-labelledby":K}:q?{"aria-label":q}:{};return(0,n.jsx)(i.Provider,{value:R,children:(0,n.jsxs)(`div`,{ref:A,"data-spark-component":`input-otp`,role:`group`,...X,...I?{"aria-describedby":I}:{},className:(0,e.cx)(`group gap-md relative inline-flex w-fit items-center default:cursor-text`,{"cursor-not-allowed":M,"cursor-default":N},C),onClick:G,...Y,children:[j&&(0,n.jsx)(`input`,{type:`hidden`,name:j,value:L,required:F,"aria-required":F,"aria-invalid":P,...X}),(0,n.jsx)(`input`,{ref:k,id:O,type:a===`password`?`password`:`text`,value:L,maxLength:E,autoFocus:f,autoComplete:p,disabled:M,readOnly:N,pattern:y,inputMode:b,...X,...I?{"aria-describedby":I}:{},"aria-invalid":P,onChange:z,onKeyDown:B,onCopy:V,onPaste:H,onFocus:U,onBlur:W,className:`bg-success z-raised absolute inset-0 m-0 p-0 opacity-0 read-only:cursor-default disabled:cursor-not-allowed`,tabIndex:0}),D]})})};v.displayName=`InputOTP`;var y=({children:e,className:t,...r})=>(0,n.jsx)(`div`,{className:`gap-md flex ${t}`,...r,children:e});y.displayName=`InputOTP.Group`;var b=({className:e,...t})=>(0,n.jsx)(`div`,{className:`text-on-surface/dim-3 flex items-center justify-center ${e||``}`,...t,children:(0,n.jsx)(`div`,{className:`h-sz-4 w-sz-8 bg-outline rounded-full`})});b.displayName=`InputOTP.Separator`;var x=Object.assign(v,{Group:y,Slot:c,Separator:b});x.displayName=`InputOTP`,y.displayName=`InputOTP.Group`,c.displayName=`InputOTP.Slot`,b.displayName=`InputOTP.Separator`,exports.InputOTP=x,exports.inputOTPSlotStyles=o,exports.inputOTPStyles=s;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../chunk-C91j1N6u.js`);let e=require(`class-variance-authority`),t=require(`react`),n=require(`react/jsx-runtime`),r=require(`@spark-ui/components/form-field`);var i=(0,t.createContext)(null),a=()=>{let e=(0,t.useContext)(i);if(!e)throw Error(`InputOTP components must be used within InputOTP`);return e};(0,e.cva)([`relative`,`inline-flex`,`items-center`,`gap-sm`]);var o=(0,e.cva)([`relative h-[50px] w-sz-40`,`border-sm rounded-md`,`text-center text-display-3 text-on-surface`,`outline-hidden`,`transition-colors`,`flex items-center justify-center`,`data-[active=true]:ring-1`,`data-[active=true]:ring-inset`,`data-[active=true]:ring-l-2`,`data-[active=true]:border-focus`,`data-[active=true]:z-raised ring-focus`,`data-[disabled=true]:cursor-not-allowed`,`data-[disabled=true]:border-outline`,`data-[disabled=true]:bg-on-surface/dim-5`,`data-[disabled=true]:text-on-surface/dim-3`,`data-[readonly=true]:cursor-default`,`data-[readonly=true]:data-[active=false]:border-outline`,`data-[readonly=true]:bg-on-surface/dim-5`,`group-hover:data-[focus-target=true]:data-[disabled=false]:border-outline-high`],{variants:{intent:{neutral:[`data-[filled=true]:bg-neutral-container bg-surface border-outline`],success:[`border-success bg-success-container text-on-success-container`],alert:[`border-alert bg-alert-container text-on-alert-container`],error:[`border-error bg-error-container text-on-error-container`]}},defaultVariants:{intent:`neutral`}}),s=o,c=({index:e,className:t,...r})=>{let i=a(),s=e??0,c=i.slots[s];if(!c)return null;let{char:l,isActive:u,hasFakeCaret:d}=c,f=!l,p=f&&!d&&i.placeholder,m=s===i.activeIndex;return(0,n.jsxs)(`div`,{className:o({intent:i.intent,className:t}),"data-active":u,"data-disabled":i.disabled,"data-readonly":i.readOnly,"data-filled":!f,"data-focus-target":m,"data-valid":i.intent!==`error`,...r,children:[(0,n.jsx)(`span`,{className:p?`text-on-surface/dim-3`:``,children:i.type===`password`&&l?`•`:l||(!d&&i.placeholder?i.placeholder:``)}),d&&(0,n.jsx)(`span`,{className:`pointer-events-none absolute inset-0 flex items-center justify-center`,"aria-hidden":`true`,children:(0,n.jsx)(`span`,{className:`bg-on-surface animate-standalone-caret-blink h-sz-24 w-sz-2`})})]})};c.displayName=`InputOTP.Slot`;var l=`Backspace`,u=`ArrowLeft`,d=`ArrowUp`,f=`ArrowRight`,p=`ArrowDown`,m=`e`,h=({maxLength:e,type:n,value:i,defaultValue:a,onValueChange:o,isValid:s,disabledProp:c,readOnlyProp:h,autoFocus:g,forceUppercase:_,filterKeys:v,pattern:y,placeholder:b,nameProp:x})=>{let S=(0,t.useId)(),C=(0,t.useRef)(null),w=(0,t.useRef)(null),T=(0,r.useFormFieldControl)(),E=T.id??S,D=x??T.name,O=T.disabled??c,k=T.readOnly??h,A=T.isInvalid??!s,j=T.isRequired??!1,M=T.labelId,N=T.description,P=T.state,F=[`success`,`alert`,`error`].includes(P??``)?P:A?`error`:`neutral`,I=i===void 0?a:i,[L,R]=(0,t.useState)(_?I.toUpperCase():I),[z,B]=(0,t.useState)(!1),V=i===void 0?L:i,H=Math.min(V.length,e-1);(0,t.useEffect)(()=>{C.current&&C.current.setSelectionRange(H,H)},[H,V.length,e]);let U=(0,t.useMemo)(()=>Array.from({length:e},(e,t)=>({char:V[t]||``,isActive:t===H&&z,hasFakeCaret:t===H&&!V[t]&&!O&&!k&&z})),[e,V,H,z,O,k]);(0,t.useEffect)(()=>{C.current&&i!==void 0&&(C.current.value=i)},[i]),(0,t.useEffect)(()=>{g&&C.current&&C.current.focus()},[g]);let W=e=>{let t=e;if(_&&(t=t.toUpperCase()),n===`number`&&(t=t.replace(/[^\d]/g,``)),y)try{let e=y;y.startsWith(`^`)||(e=`^${y}$`);let n=new RegExp(e);t=t.split(``).filter(e=>n.test(e)).join(``)}catch(e){console.error(`Invalid pattern provided to InputOTP:`,y,e)}return t};return{uuid:E,inputRef:C,containerRef:w,name:D,disabled:O,readOnly:k,isInvalid:A,isRequired:j,description:N,maxLength:e,intent:F,currentValue:V,activeIndex:H,slots:U,contextValue:{value:V,maxLength:e,slots:U,activeIndex:H,intent:F,disabled:O,readOnly:k,placeholder:b,type:n},handleChange:t=>{if(O||k)return;let n=t.target.value,r=W(n).slice(0,e);o&&o(r),i===void 0&&R(r);let a=Math.min(r.length,e-1);C.current&&C.current.setSelectionRange(a,a)},handleKeyDown:t=>{if(O||k)return;let r=(t.ctrlKey||t.metaKey)&&[`a`,`c`,`v`,`x`].includes(t.key.toLowerCase());if(v.length>0&&v.includes(t.key)&&!r){t.preventDefault();return}if(t.key.length===1&&!t.ctrlKey&&!t.metaKey&&!t.altKey&&V.length===e){t.preventDefault();let n=W(t.key);if(n.length===0)return;let r=V.slice(0,e-1)+n;o&&o(r),i===void 0&&R(r);let a=e-1;C.current&&C.current.setSelectionRange(a,a);return}switch(t.key){case l:t.preventDefault();let e=V.length;if(e>0){let t=V.slice(0,e-1);o&&o(t),i===void 0&&R(t);let n=Math.max(0,t.length);C.current&&C.current.setSelectionRange(n,n)}break;case u:case f:t.preventDefault();break;case d:case p:t.preventDefault();break;case m:case`E`:n===`number`&&t.preventDefault();break;default:break}},handleCopy:e=>{O||(e.preventDefault(),V.length>0&&e.clipboardData.setData(`text/plain`,V))},handlePaste:t=>{if(O||k)return;t.preventDefault();let n=t.clipboardData.getData(`text`);if(!n)return;let r=W(n).slice(0,e);o&&o(r),i===void 0&&R(r);let a=Math.min(r.length,e-1);C.current&&C.current.setSelectionRange(a,a)},handleFocus:()=>{if(B(!0),C.current){let t=Math.min(V.length,e-1);C.current.setSelectionRange(t,t)}},handleBlur:()=>{B(!1)},handleClick:()=>{C.current&&C.current.focus()},labelId:M}},g=e=>{let n=0;return t.Children.forEach(e,e=>{if((0,t.isValidElement)(e)){let t=e.props;e.type===c||e.type?.displayName===`InputOTP.Slot`?n++:t.children&&(n+=g(t.children))}}),n},_=(e,n=0)=>{let r=n;return[t.Children.map(e,e=>{if((0,t.isValidElement)(e)){let n=e.props;if(e.type===c||e.type?.displayName===`InputOTP.Slot`){let i=typeof n.index==`number`?n.index:r++;return(0,t.cloneElement)(e,{...n,index:i})}else if(n.children){let[i,a]=_(n.children,r);return r=a,(0,t.cloneElement)(e,{...e.props,children:i})}}return e}),r]},v=({maxLength:r,type:a=`text`,value:o,defaultValue:s=``,onValueChange:c,isValid:l=!0,disabled:u=!1,readOnly:d=!1,autoFocus:f=!1,autoComplete:p=`off`,forceUppercase:m=!1,filterKeys:v=[`-`,`.`],pattern:y,inputMode:b,placeholder:x=`-`,name:S,className:C,children:w,...T})=>{let E=(0,t.useMemo)(()=>{if(r!==void 0)return r;let e=g(w);return e>0?e:4},[r,w]),D=(0,t.useMemo)(()=>{let[e]=_(w);return e},[w]),{uuid:O,inputRef:k,containerRef:A,name:j,disabled:M,readOnly:N,isInvalid:P,isRequired:F,description:I,currentValue:L,contextValue:R,handleChange:z,handleKeyDown:B,handleCopy:V,handlePaste:H,handleFocus:U,handleBlur:W,handleClick:G,labelId:K}=h({maxLength:E,type:a,value:o,defaultValue:s,onValueChange:c,isValid:l,disabledProp:u,readOnlyProp:d,autoFocus:f,forceUppercase:m,filterKeys:v,pattern:y,placeholder:x,nameProp:S}),q=`aria-label`in T?T[`aria-label`]:void 0,{"aria-label":J,...Y}=T,X=K?{"aria-labelledby":K}:q?{"aria-label":q}:{};return(0,n.jsx)(i,{value:R,children:(0,n.jsxs)(`div`,{ref:A,"data-spark-component":`input-otp`,role:`group`,...X,...I?{"aria-describedby":I}:{},className:(0,e.cx)(`group gap-md relative inline-flex w-fit items-center default:cursor-text`,{"cursor-not-allowed":M,"cursor-default":N},C),onClick:G,...Y,children:[j&&(0,n.jsx)(`input`,{type:`hidden`,name:j,value:L,required:F,"aria-required":F,"aria-invalid":P,...X}),(0,n.jsx)(`input`,{ref:k,id:O,type:a===`password`?`password`:`text`,value:L,maxLength:E,autoFocus:f,autoComplete:p,disabled:M,readOnly:N,pattern:y,inputMode:b,...X,...I?{"aria-describedby":I}:{},"aria-invalid":P,onChange:z,onKeyDown:B,onCopy:V,onPaste:H,onFocus:U,onBlur:W,className:`bg-success z-raised absolute inset-0 m-0 p-0 opacity-0 read-only:cursor-default disabled:cursor-not-allowed`,tabIndex:0}),D]})})};v.displayName=`InputOTP`;var y=({children:e,className:t,...r})=>(0,n.jsx)(`div`,{className:`gap-md flex ${t}`,...r,children:e});y.displayName=`InputOTP.Group`;var b=({className:e,...t})=>(0,n.jsx)(`div`,{className:`text-on-surface/dim-3 flex items-center justify-center ${e||``}`,...t,children:(0,n.jsx)(`div`,{className:`h-sz-4 w-sz-8 bg-outline rounded-full`})});b.displayName=`InputOTP.Separator`;var x=Object.assign(v,{Group:y,Slot:c,Separator:b});x.displayName=`InputOTP`,y.displayName=`InputOTP.Group`,c.displayName=`InputOTP.Slot`,b.displayName=`InputOTP.Separator`,exports.InputOTP=x,exports.inputOTPSlotStyles=o,exports.inputOTPStyles=s;
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/input-otp/InputOTPContext.tsx","../../src/input-otp/InputOTP.styles.ts","../../src/input-otp/InputOTPSlot.tsx","../../src/input-otp/useInputOTP.ts","../../src/input-otp/InputOTP.tsx","../../src/input-otp/InputOTPGroup.tsx","../../src/input-otp/InputOTPSeparator.tsx","../../src/input-otp/index.ts"],"sourcesContent":["import { createContext, useContext } from 'react'\n\nexport interface InputOTPContextValue {\n value: string\n maxLength: number\n slots: {\n char: string\n isActive: boolean\n hasFakeCaret: boolean\n }[]\n activeIndex: number\n intent: 'neutral' | 'success' | 'alert' | 'error'\n disabled: boolean\n readOnly: boolean\n placeholder?: string\n type: 'text' | 'number' | 'password' | 'tel'\n}\n\nexport const InputOTPContext = createContext<InputOTPContextValue | null>(null)\n\nexport const useInputOTPContext = () => {\n const context = useContext(InputOTPContext)\n if (!context) {\n throw new Error('InputOTP components must be used within InputOTP')\n }\n\n return context\n}\n","import { cva, VariantProps } from 'class-variance-authority'\n\nexport const inputOTPContainerStyles = cva(['relative', 'inline-flex', 'items-center', 'gap-sm'])\n\nexport const inputOTPSlotStyles = cva(\n [\n // Base slot styles\n 'relative h-[50px] w-sz-40',\n 'border-sm rounded-md',\n 'text-center text-display-3 text-on-surface',\n 'outline-hidden',\n 'transition-colors',\n 'flex items-center justify-center',\n // Slot that receives focus when clicking the group (first empty or last slot)\n // Use data-[focus-target=true]:... for distinct styles\n // Active state (when focused)\n 'data-[active=true]:ring-1',\n 'data-[active=true]:ring-inset',\n 'data-[active=true]:ring-l-2',\n 'data-[active=true]:border-focus',\n 'data-[active=true]:z-raised ring-focus',\n // Disabled state\n 'data-[disabled=true]:cursor-not-allowed',\n 'data-[disabled=true]:border-outline',\n 'data-[disabled=true]:bg-on-surface/dim-5',\n 'data-[disabled=true]:text-on-surface/dim-3',\n // Read-only state (same as disabled but text stays normal)\n 'data-[readonly=true]:cursor-default',\n 'data-[readonly=true]:data-[active=false]:border-outline',\n 'data-[readonly=true]:bg-on-surface/dim-5',\n 'group-hover:data-[focus-target=true]:data-[disabled=false]:border-outline-high',\n ],\n {\n variants: {\n /**\n * Color scheme of the slot\n */\n intent: {\n neutral: ['data-[filled=true]:bg-neutral-container bg-surface border-outline'],\n success: ['border-success bg-success-container text-on-success-container'],\n alert: ['border-alert bg-alert-container text-on-alert-container'],\n error: ['border-error bg-error-container text-on-error-container'],\n },\n },\n defaultVariants: {\n intent: 'neutral',\n },\n }\n)\n\nexport type InputOTPSlotStylesProps = VariantProps<typeof inputOTPSlotStyles>\n\n// Keep for backward compatibility\nexport const inputOTPStyles = inputOTPSlotStyles\nexport type InputOTPStylesProps = InputOTPSlotStylesProps\n","import { ComponentPropsWithoutRef } from 'react'\n\nimport { inputOTPSlotStyles } from './InputOTP.styles'\nimport { useInputOTPContext } from './InputOTPContext'\n\nexport interface InputOTPSlotProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * Index of the slot (0-based).\n * If not provided, will be automatically assigned based on position in children.\n */\n index?: number\n}\n\n/**\n * An individual slot for a single OTP character. Renders a <div> element.\n */\nexport const InputOTPSlot = ({ index: indexProp, className, ...props }: InputOTPSlotProps) => {\n const context = useInputOTPContext()\n\n // Use provided index or fallback to 0 (should not happen if auto-assignment works)\n const index = indexProp ?? 0\n const slot = context.slots[index]\n\n if (!slot) {\n return null\n }\n\n const { char, isActive, hasFakeCaret } = slot\n const isEmpty = !char\n const isPlaceholder = isEmpty && !hasFakeCaret && context.placeholder\n\n const isFocusTarget = index === context.activeIndex\n\n return (\n <div\n className={inputOTPSlotStyles({\n intent: context.intent,\n className,\n })}\n data-active={isActive}\n data-disabled={context.disabled}\n data-readonly={context.readOnly}\n data-filled={!isEmpty}\n data-focus-target={isFocusTarget}\n data-valid={context.intent !== 'error'}\n {...props}\n >\n <span className={isPlaceholder ? 'text-on-surface/dim-3' : ''}>\n {context.type === 'password' && char\n ? '•'\n : char || (!hasFakeCaret && context.placeholder ? context.placeholder : '')}\n </span>\n {hasFakeCaret && (\n <span\n className=\"pointer-events-none absolute inset-0 flex items-center justify-center\"\n aria-hidden=\"true\"\n >\n <span className=\"bg-on-surface animate-standalone-caret-blink h-sz-24 w-sz-2\" />\n </span>\n )}\n </div>\n )\n}\n\nInputOTPSlot.displayName = 'InputOTP.Slot'\n","/* eslint-disable max-lines-per-function */\nimport { useFormFieldControl } from '@spark-ui/components/form-field'\nimport {\n ChangeEventHandler,\n ClipboardEventHandler,\n KeyboardEventHandler,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react'\n\nimport type { InputOTPContextValue } from './InputOTPContext'\n\nconst BACKSPACE_KEY = 'Backspace'\nconst LEFT_ARROW_KEY = 'ArrowLeft'\nconst UP_ARROW_KEY = 'ArrowUp'\nconst RIGHT_ARROW_KEY = 'ArrowRight'\nconst DOWN_ARROW_KEY = 'ArrowDown'\nconst E_KEY = 'e'\n\nexport interface UseInputOTPProps {\n maxLength: number\n type: 'text' | 'number' | 'password' | 'tel'\n value?: string\n defaultValue: string\n onValueChange?: (value: string) => void\n isValid: boolean\n disabledProp: boolean\n readOnlyProp: boolean\n autoFocus: boolean\n forceUppercase: boolean\n filterKeys: string[]\n pattern?: string\n placeholder: string\n nameProp?: string\n}\n\nexport interface UseInputOTPReturn {\n uuid: string\n inputRef: React.RefObject<HTMLInputElement | null>\n containerRef: React.RefObject<HTMLDivElement | null>\n name: string | undefined\n disabled: boolean\n readOnly: boolean\n isInvalid: boolean\n isRequired: boolean\n description: string | undefined\n maxLength: number\n intent: 'neutral' | 'success' | 'alert' | 'error'\n currentValue: string\n activeIndex: number\n slots: {\n char: string\n isActive: boolean\n hasFakeCaret: boolean\n }[]\n contextValue: InputOTPContextValue\n handleChange: ChangeEventHandler<HTMLInputElement>\n handleKeyDown: KeyboardEventHandler<HTMLInputElement>\n handleCopy: ClipboardEventHandler<HTMLInputElement>\n handlePaste: ClipboardEventHandler<HTMLInputElement>\n handleFocus: () => void\n handleBlur: () => void\n handleClick: () => void\n labelId: string | undefined\n}\n\nexport const useInputOTP = ({\n maxLength,\n type,\n value: controlledValue,\n defaultValue,\n onValueChange,\n isValid,\n disabledProp,\n readOnlyProp,\n autoFocus,\n forceUppercase,\n filterKeys,\n pattern,\n placeholder,\n nameProp,\n}: UseInputOTPProps): UseInputOTPReturn => {\n const uuid = useId()\n const inputRef = useRef<HTMLInputElement>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n\n // Get FormField context (optional, falls back gracefully if not present)\n const field = useFormFieldControl()\n\n // Use FormField values if available, otherwise fall back to props\n // Use FormField id when available so label htmlFor works correctly\n const id = field.id ?? uuid\n const name = nameProp ?? field.name\n const disabled = field.disabled ?? disabledProp\n const readOnly = field.readOnly ?? readOnlyProp\n const isInvalid = field.isInvalid ?? !isValid\n const isRequired = field.isRequired ?? false\n const labelId = field.labelId\n const description = field.description\n const fieldState = field.state\n\n // Determine intent based on FormField state or isValid prop\n const getIntent = (): 'neutral' | 'success' | 'alert' | 'error' => {\n // FormField state takes priority\n if (['success', 'alert', 'error'].includes(fieldState ?? '')) {\n return fieldState as 'success' | 'alert' | 'error'\n }\n\n // Fallback to isValid prop for backward compatibility\n if (isInvalid) {\n return 'error'\n }\n\n return 'neutral'\n }\n\n const intent = getIntent()\n\n // Initialize value\n const initialValue = controlledValue !== undefined ? controlledValue : defaultValue\n const processedValue = forceUppercase ? initialValue.toUpperCase() : initialValue\n\n const [internalValue, setInternalValue] = useState<string>(processedValue)\n const [isFocused, setIsFocused] = useState<boolean>(false)\n\n // Use controlled value if provided, otherwise use internal state\n const currentValue = controlledValue !== undefined ? controlledValue : internalValue\n\n // Calculate active index: last empty slot, or last slot if all are filled\n const activeIndex = Math.min(currentValue.length, maxLength - 1)\n\n // Sync cursor position with active index\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.setSelectionRange(activeIndex, activeIndex)\n }\n }, [activeIndex, currentValue.length, maxLength])\n\n // Create slots array\n const slots = useMemo(\n () =>\n Array.from({ length: maxLength }, (_, i) => ({\n char: currentValue[i] || '',\n isActive: i === activeIndex && isFocused,\n hasFakeCaret: i === activeIndex && !currentValue[i] && !disabled && !readOnly && isFocused,\n })),\n [maxLength, currentValue, activeIndex, isFocused, disabled, readOnly]\n )\n\n // Sync controlled value with input ref\n useEffect(() => {\n if (inputRef.current && controlledValue !== undefined) {\n inputRef.current.value = controlledValue\n }\n }, [controlledValue])\n\n // Focus management\n useEffect(() => {\n if (autoFocus && inputRef.current) {\n inputRef.current.focus()\n }\n }, [autoFocus])\n\n const processInputValue = (inputValue: string): string => {\n let processed = inputValue\n\n if (forceUppercase) {\n processed = processed.toUpperCase()\n }\n\n if (type === 'number') {\n processed = processed.replace(/[^\\d]/g, '')\n }\n\n // Filter characters using pattern if provided\n if (pattern) {\n try {\n // Convert HTML pattern (string) to RegExp\n // HTML patterns validate the entire string, but we need to test each character\n // We create a regex that tests if a single character matches the pattern\n // For example: [0-9]* becomes ^[0-9]$ to test a single digit\n // We wrap the pattern in ^...$ to ensure it matches a single character\n let regexPattern = pattern\n // If pattern doesn't start with ^, wrap it to test single character\n if (!pattern.startsWith('^')) {\n regexPattern = `^${pattern}$`\n }\n const regex = new RegExp(regexPattern)\n processed = processed\n .split('')\n .filter(currChar => {\n // Test if the character matches the pattern\n return regex.test(currChar)\n })\n .join('')\n } catch (error) {\n // If pattern is invalid, ignore it and continue with other filters\n console.error('Invalid pattern provided to InputOTP:', pattern, error)\n }\n }\n\n return processed\n }\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = e => {\n if (disabled || readOnly) return\n\n const inputValue = e.target.value\n const processedValue = processInputValue(inputValue)\n\n // Limit to maxLength\n const newValue = processedValue.slice(0, maxLength)\n\n // Call onValueChange callback first (before updating state)\n if (onValueChange) {\n onValueChange(newValue)\n }\n\n // Update state only in uncontrolled mode\n if (controlledValue === undefined) {\n setInternalValue(newValue)\n }\n\n // Active index is automatically calculated based on value length\n // Sync cursor position\n const newActiveIndex = Math.min(newValue.length, maxLength - 1)\n if (inputRef.current) {\n inputRef.current.setSelectionRange(newActiveIndex, newActiveIndex)\n }\n }\n\n const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = e => {\n if (disabled || readOnly) return\n\n // Allow copy/cut/paste/selectAll shortcuts even when key is in filterKeys\n const isShortcut =\n (e.ctrlKey || e.metaKey) && ['a', 'c', 'v', 'x'].includes(e.key.toLowerCase())\n\n // Filter keys\n if (filterKeys.length > 0 && filterKeys.includes(e.key) && !isShortcut) {\n e.preventDefault()\n\n return\n }\n\n switch (e.key) {\n case BACKSPACE_KEY:\n e.preventDefault()\n const currentLength = currentValue.length\n if (currentLength > 0) {\n const newValue = currentValue.slice(0, currentLength - 1)\n\n // Call onValueChange first\n if (onValueChange) {\n onValueChange(newValue)\n }\n\n // Update state only in uncontrolled mode\n if (controlledValue === undefined) {\n setInternalValue(newValue)\n }\n\n // Active index is automatically calculated based on value length\n // Sync cursor position\n const newActiveIndex = Math.max(0, newValue.length)\n if (inputRef.current) {\n inputRef.current.setSelectionRange(newActiveIndex, newActiveIndex)\n }\n }\n break\n\n case LEFT_ARROW_KEY:\n case RIGHT_ARROW_KEY:\n // Prevent navigation with arrow keys - focus stays on last empty slot\n e.preventDefault()\n break\n\n case UP_ARROW_KEY:\n case DOWN_ARROW_KEY:\n e.preventDefault()\n break\n\n case E_KEY:\n case 'E':\n // Prevent 'e' or 'E' in number inputs\n if (type === 'number') {\n e.preventDefault()\n }\n break\n\n default:\n break\n }\n }\n\n const handleCopy: ClipboardEventHandler<HTMLInputElement> = e => {\n if (disabled) return\n\n e.preventDefault()\n if (currentValue.length > 0) {\n e.clipboardData.setData('text/plain', currentValue)\n }\n }\n\n const handlePaste: ClipboardEventHandler<HTMLInputElement> = e => {\n if (disabled || readOnly) return\n\n e.preventDefault()\n\n const pastedText = e.clipboardData.getData('text')\n\n if (!pastedText) return\n\n const processedText = processInputValue(pastedText)\n const newValue = processedText.slice(0, maxLength)\n\n // Call onValueChange callback first (before updating state)\n if (onValueChange) {\n onValueChange(newValue)\n }\n\n // Update state only in uncontrolled mode\n if (controlledValue === undefined) {\n setInternalValue(newValue)\n }\n\n // Active index is automatically calculated based on value length\n // Move cursor to end\n const newActiveIndex = Math.min(newValue.length, maxLength - 1)\n if (inputRef.current) {\n inputRef.current.setSelectionRange(newActiveIndex, newActiveIndex)\n }\n }\n\n const handleFocus = () => {\n setIsFocused(true)\n if (inputRef.current) {\n // Focus on last empty slot, or last slot if all are filled\n const cursorPosition = Math.min(currentValue.length, maxLength - 1)\n inputRef.current.setSelectionRange(cursorPosition, cursorPosition)\n }\n }\n\n const handleBlur = () => {\n setIsFocused(false)\n }\n\n const handleClick = () => {\n if (inputRef.current) {\n inputRef.current.focus()\n }\n }\n\n const contextValue: InputOTPContextValue = {\n value: currentValue,\n maxLength,\n slots,\n activeIndex,\n intent,\n disabled,\n readOnly,\n placeholder,\n type,\n }\n\n const returnValue: UseInputOTPReturn = {\n uuid: id,\n inputRef,\n containerRef,\n name,\n disabled,\n readOnly,\n isInvalid,\n isRequired,\n description,\n maxLength,\n intent,\n currentValue,\n activeIndex,\n slots,\n contextValue,\n handleChange,\n handleKeyDown,\n handleCopy,\n handlePaste,\n handleFocus,\n handleBlur,\n handleClick,\n labelId,\n }\n\n return returnValue\n}\n","/* eslint-disable max-lines-per-function */\nimport { cx } from 'class-variance-authority'\nimport {\n Children,\n cloneElement,\n ComponentPropsWithoutRef,\n isValidElement,\n ReactElement,\n ReactNode,\n Ref,\n useMemo,\n} from 'react'\n\nimport { InputOTPContext } from './InputOTPContext'\nimport { InputOTPSlot } from './InputOTPSlot'\nimport { useInputOTP } from './useInputOTP'\n\n/**\n * Counts the number of InputOTPSlot components in the children tree\n */\nconst countSlots = (children: ReactNode): number => {\n let count = 0\n\n Children.forEach(children, child => {\n if (isValidElement(child)) {\n const props = child.props as { children?: ReactNode }\n // Check if it's an InputOTPSlot by checking displayName\n if (\n child.type === InputOTPSlot ||\n (child.type as { displayName?: string })?.displayName === 'InputOTP.Slot'\n ) {\n count++\n } else if (props.children) {\n // Recursively count slots in nested children (e.g., inside InputOTPGroup)\n count += countSlots(props.children)\n }\n }\n })\n\n return count\n}\n\n/**\n * Recursively assigns index to InputOTPSlot components\n * Returns a tuple of [processedChildren, nextIndex]\n */\nconst assignSlotIndexes = (children: ReactNode, startIndex: number = 0): [ReactNode, number] => {\n let currentIndex = startIndex\n\n const processed = Children.map(children, child => {\n if (isValidElement(child)) {\n const props = child.props as { index?: number; children?: ReactNode }\n // Check if it's an InputOTPSlot\n if (\n child.type === InputOTPSlot ||\n (child.type as { displayName?: string })?.displayName === 'InputOTP.Slot'\n ) {\n // Only assign index if not already provided\n const slotIndex = typeof props.index === 'number' ? props.index : currentIndex++\n\n return cloneElement(child as ReactElement<{ index?: number }>, {\n ...props,\n index: slotIndex,\n })\n } else if (props.children) {\n // Recursively process nested children\n const [processedChildren, nextIndex] = assignSlotIndexes(props.children, currentIndex)\n currentIndex = nextIndex\n\n return cloneElement(child, {\n ...(child.props as Record<string, unknown>),\n children: processedChildren,\n } as Parameters<typeof cloneElement>[1])\n }\n }\n\n return child\n })\n\n return [processed, currentIndex]\n}\n\nexport interface InputOTPProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'onChange' | 'inputMode'\n> {\n /**\n * Maximum length of the input value.\n * If not provided, will be automatically detected from the number of InputOTP.Slot children.\n */\n maxLength?: number\n /**\n * Type of input\n * @default 'text'\n */\n type?: 'text' | 'number' | 'password' | 'tel'\n /**\n * Current value (controlled mode)\n */\n value?: string\n /**\n * Default value (uncontrolled mode)\n */\n defaultValue?: string\n /**\n * Callback fired when the value changes\n */\n onValueChange?: (value: string) => void\n /**\n * Whether the input is valid\n * @default true\n */\n isValid?: boolean\n /**\n * Whether the input is disabled\n * @default false\n */\n disabled?: boolean\n /**\n * Whether the input is read-only (value visible but not editable)\n * @default false\n */\n readOnly?: boolean\n /**\n * Whether to auto-focus the input\n * @default false\n */\n autoFocus?: boolean\n /**\n * Auto-complete attribute\n * @default 'off'\n */\n autoComplete?: string\n /**\n * Whether to force uppercase\n * @default false\n */\n forceUppercase?: boolean\n /**\n * Array of keys to filter out (using KeyboardEvent.key values)\n * @default ['-', '.']\n */\n filterKeys?: string[]\n /**\n * Pattern attribute for input validation and character filtering.\n * Uses a regular expression to filter allowed characters in real-time.\n * For example: \"[0-9]\" for digits only, \"[a-c]\" for letters a, b, c only.\n */\n pattern?: string\n /**\n * Input mode attribute\n */\n inputMode?: string\n /**\n * Placeholder text\n */\n placeholder?: string\n /**\n * Name attribute for form integration\n */\n name?: string\n /**\n * Children components (InputOTPGroup, InputOTPSlot, InputOTPSeparator)\n */\n children: ReactNode\n /**\n * Ref callback for the container\n */\n ref?: Ref<HTMLDivElement>\n}\n\nexport const InputOTP = ({\n maxLength: maxLengthProp,\n type = 'text',\n value: controlledValue,\n defaultValue = '',\n onValueChange,\n isValid = true,\n disabled: disabledProp = false,\n readOnly: readOnlyProp = false,\n autoFocus = false,\n autoComplete = 'off',\n forceUppercase = false,\n filterKeys = ['-', '.'],\n pattern,\n inputMode,\n placeholder = '-',\n name: nameProp,\n className,\n children,\n ...others\n}: InputOTPProps) => {\n // Auto-detect maxLength from children if not provided\n const maxLength = useMemo(() => {\n if (maxLengthProp !== undefined) {\n return maxLengthProp\n }\n\n const detectedLength = countSlots(children)\n const DEFAULT_MAX_LENGTH = 4\n\n return detectedLength > 0 ? detectedLength : DEFAULT_MAX_LENGTH // fallback to 4 if no slots found\n }, [maxLengthProp, children])\n\n // Assign indexes to slots automatically\n const processedChildren = useMemo(() => {\n const [processed] = assignSlotIndexes(children)\n\n return processed\n }, [children])\n\n // Use the hook for all business logic\n const {\n uuid,\n inputRef,\n containerRef,\n name,\n disabled,\n readOnly,\n isInvalid,\n isRequired,\n description,\n currentValue,\n contextValue,\n handleChange,\n handleKeyDown,\n handleCopy,\n handlePaste,\n handleFocus,\n handleBlur,\n handleClick,\n labelId,\n } = useInputOTP({\n maxLength,\n type,\n value: controlledValue,\n defaultValue,\n onValueChange,\n isValid,\n disabledProp,\n readOnlyProp,\n autoFocus,\n forceUppercase,\n filterKeys,\n pattern,\n placeholder,\n nameProp,\n })\n\n // Extract aria-label from others if provided (for cases without FormField)\n const ariaLabel =\n 'aria-label' in others ? (others['aria-label'] as string | undefined) : undefined\n const { 'aria-label': _, ...restOthers } = others\n\n const getAccessibleNameProps = (): Record<string, string | undefined> => {\n if (labelId) {\n return { 'aria-labelledby': labelId }\n }\n\n if (ariaLabel) {\n return { 'aria-label': ariaLabel }\n }\n\n return {}\n }\n\n const accessibleNameProps = getAccessibleNameProps()\n\n return (\n <InputOTPContext.Provider value={contextValue}>\n <div\n ref={containerRef}\n data-spark-component=\"input-otp\"\n role=\"group\"\n {...accessibleNameProps}\n {...(description ? { 'aria-describedby': description } : {})}\n className={cx(\n 'group gap-md relative inline-flex w-fit items-center default:cursor-text',\n {\n 'cursor-not-allowed': disabled,\n 'cursor-default': readOnly,\n },\n className\n )}\n onClick={handleClick}\n {...restOthers}\n >\n {/* Hidden input for form submission with complete value */}\n {name && (\n <input\n type=\"hidden\"\n name={name}\n value={currentValue}\n required={isRequired}\n aria-required={isRequired}\n aria-invalid={isInvalid}\n {...accessibleNameProps}\n />\n )}\n {/* Actual input that handles all interactions */}\n <input\n ref={inputRef}\n id={uuid}\n type={type === 'password' ? 'password' : 'text'}\n value={currentValue}\n maxLength={maxLength}\n autoFocus={autoFocus}\n autoComplete={autoComplete}\n disabled={disabled}\n readOnly={readOnly}\n pattern={pattern}\n inputMode={inputMode as React.InputHTMLAttributes<HTMLInputElement>['inputMode']}\n {...accessibleNameProps}\n {...(description ? { 'aria-describedby': description } : {})}\n aria-invalid={isInvalid}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onCopy={handleCopy}\n onPaste={handlePaste}\n onFocus={handleFocus}\n onBlur={handleBlur}\n className=\"bg-success z-raised absolute inset-0 m-0 p-0 opacity-0 read-only:cursor-default disabled:cursor-not-allowed\"\n tabIndex={0}\n />\n {/* Children render slots with auto-assigned indexes */}\n {processedChildren}\n </div>\n </InputOTPContext.Provider>\n )\n}\n\nInputOTP.displayName = 'InputOTP'\n","import { ComponentPropsWithoutRef } from 'react'\n\nexport interface InputOTPGroupProps extends ComponentPropsWithoutRef<'div'> {}\n\n/**\n * Container for a group of OTP input slots. Renders a <div> element.\n */\nexport const InputOTPGroup = ({ children, className, ...props }: InputOTPGroupProps) => {\n return (\n <div className={`gap-md flex ${className}`} {...props}>\n {children}\n </div>\n )\n}\n\nInputOTPGroup.displayName = 'InputOTP.Group'\n","import { ComponentPropsWithoutRef } from 'react'\n\nexport interface InputOTPSeparatorProps extends ComponentPropsWithoutRef<'div'> {}\n\n/**\n * A visual separator between OTP input groups. Renders a <div> element.\n */\nexport const InputOTPSeparator = ({ className, ...props }: InputOTPSeparatorProps) => {\n return (\n <div\n className={`text-on-surface/dim-3 flex items-center justify-center ${className || ''}`}\n {...props}\n >\n <div className=\"h-sz-4 w-sz-8 bg-outline rounded-full\" />\n </div>\n )\n}\n\nInputOTPSeparator.displayName = 'InputOTP.Separator'\n","import { InputOTP as Root } from './InputOTP'\nimport { InputOTPGroup } from './InputOTPGroup'\nimport { InputOTPSeparator } from './InputOTPSeparator'\nimport { InputOTPSlot } from './InputOTPSlot'\n\n/**\n * An input component for entering one-time passwords or verification codes with individual character slots.\n */\nexport const InputOTP: typeof Root & {\n Group: typeof InputOTPGroup\n Slot: typeof InputOTPSlot\n Separator: typeof InputOTPSeparator\n} = Object.assign(Root, {\n Group: InputOTPGroup,\n Slot: InputOTPSlot,\n Separator: InputOTPSeparator,\n})\n\nInputOTP.displayName = 'InputOTP'\nInputOTPGroup.displayName = 'InputOTP.Group'\nInputOTPSlot.displayName = 'InputOTP.Slot'\nInputOTPSeparator.displayName = 'InputOTP.Separator'\n\nexport { type InputOTPProps } from './InputOTP'\nexport { type InputOTPGroupProps } from './InputOTPGroup'\nexport { type InputOTPSlotProps } from './InputOTPSlot'\nexport { type InputOTPSeparatorProps } from './InputOTPSeparator'\nexport {\n inputOTPSlotStyles,\n inputOTPStyles,\n type InputOTPSlotStylesProps,\n type InputOTPStylesProps,\n} from './InputOTP.styles'\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/input-otp/InputOTPContext.tsx","../../src/input-otp/InputOTP.styles.ts","../../src/input-otp/InputOTPSlot.tsx","../../src/input-otp/useInputOTP.ts","../../src/input-otp/InputOTP.tsx","../../src/input-otp/InputOTPGroup.tsx","../../src/input-otp/InputOTPSeparator.tsx","../../src/input-otp/index.ts"],"sourcesContent":["import { createContext, useContext } from 'react'\n\nexport interface InputOTPContextValue {\n value: string\n maxLength: number\n slots: {\n char: string\n isActive: boolean\n hasFakeCaret: boolean\n }[]\n activeIndex: number\n intent: 'neutral' | 'success' | 'alert' | 'error'\n disabled: boolean\n readOnly: boolean\n placeholder?: string\n type: 'text' | 'number' | 'password' | 'tel'\n}\n\nexport const InputOTPContext = createContext<InputOTPContextValue | null>(null)\n\nexport const useInputOTPContext = () => {\n const context = useContext(InputOTPContext)\n if (!context) {\n throw new Error('InputOTP components must be used within InputOTP')\n }\n\n return context\n}\n","import { cva, VariantProps } from 'class-variance-authority'\n\nexport const inputOTPContainerStyles = cva(['relative', 'inline-flex', 'items-center', 'gap-sm'])\n\nexport const inputOTPSlotStyles = cva(\n [\n // Base slot styles\n 'relative h-[50px] w-sz-40',\n 'border-sm rounded-md',\n 'text-center text-display-3 text-on-surface',\n 'outline-hidden',\n 'transition-colors',\n 'flex items-center justify-center',\n // Slot that receives focus when clicking the group (first empty or last slot)\n // Use data-[focus-target=true]:... for distinct styles\n // Active state (when focused)\n 'data-[active=true]:ring-1',\n 'data-[active=true]:ring-inset',\n 'data-[active=true]:ring-l-2',\n 'data-[active=true]:border-focus',\n 'data-[active=true]:z-raised ring-focus',\n // Disabled state\n 'data-[disabled=true]:cursor-not-allowed',\n 'data-[disabled=true]:border-outline',\n 'data-[disabled=true]:bg-on-surface/dim-5',\n 'data-[disabled=true]:text-on-surface/dim-3',\n // Read-only state (same as disabled but text stays normal)\n 'data-[readonly=true]:cursor-default',\n 'data-[readonly=true]:data-[active=false]:border-outline',\n 'data-[readonly=true]:bg-on-surface/dim-5',\n 'group-hover:data-[focus-target=true]:data-[disabled=false]:border-outline-high',\n ],\n {\n variants: {\n /**\n * Color scheme of the slot\n */\n intent: {\n neutral: ['data-[filled=true]:bg-neutral-container bg-surface border-outline'],\n success: ['border-success bg-success-container text-on-success-container'],\n alert: ['border-alert bg-alert-container text-on-alert-container'],\n error: ['border-error bg-error-container text-on-error-container'],\n },\n },\n defaultVariants: {\n intent: 'neutral',\n },\n }\n)\n\nexport type InputOTPSlotStylesProps = VariantProps<typeof inputOTPSlotStyles>\n\n// Keep for backward compatibility\nexport const inputOTPStyles = inputOTPSlotStyles\nexport type InputOTPStylesProps = InputOTPSlotStylesProps\n","import { ComponentPropsWithoutRef } from 'react'\n\nimport { inputOTPSlotStyles } from './InputOTP.styles'\nimport { useInputOTPContext } from './InputOTPContext'\n\nexport interface InputOTPSlotProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * Index of the slot (0-based).\n * If not provided, will be automatically assigned based on position in children.\n */\n index?: number\n}\n\n/**\n * An individual slot for a single OTP character. Renders a <div> element.\n */\nexport const InputOTPSlot = ({ index: indexProp, className, ...props }: InputOTPSlotProps) => {\n const context = useInputOTPContext()\n\n // Use provided index or fallback to 0 (should not happen if auto-assignment works)\n const index = indexProp ?? 0\n const slot = context.slots[index]\n\n if (!slot) {\n return null\n }\n\n const { char, isActive, hasFakeCaret } = slot\n const isEmpty = !char\n const isPlaceholder = isEmpty && !hasFakeCaret && context.placeholder\n\n const isFocusTarget = index === context.activeIndex\n\n return (\n <div\n className={inputOTPSlotStyles({\n intent: context.intent,\n className,\n })}\n data-active={isActive}\n data-disabled={context.disabled}\n data-readonly={context.readOnly}\n data-filled={!isEmpty}\n data-focus-target={isFocusTarget}\n data-valid={context.intent !== 'error'}\n {...props}\n >\n <span className={isPlaceholder ? 'text-on-surface/dim-3' : ''}>\n {context.type === 'password' && char\n ? '•'\n : char || (!hasFakeCaret && context.placeholder ? context.placeholder : '')}\n </span>\n {hasFakeCaret && (\n <span\n className=\"pointer-events-none absolute inset-0 flex items-center justify-center\"\n aria-hidden=\"true\"\n >\n <span className=\"bg-on-surface animate-standalone-caret-blink h-sz-24 w-sz-2\" />\n </span>\n )}\n </div>\n )\n}\n\nInputOTPSlot.displayName = 'InputOTP.Slot'\n","/* eslint-disable max-lines-per-function */\nimport { useFormFieldControl } from '@spark-ui/components/form-field'\nimport {\n ChangeEventHandler,\n ClipboardEventHandler,\n KeyboardEventHandler,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react'\n\nimport type { InputOTPContextValue } from './InputOTPContext'\n\nconst BACKSPACE_KEY = 'Backspace'\nconst LEFT_ARROW_KEY = 'ArrowLeft'\nconst UP_ARROW_KEY = 'ArrowUp'\nconst RIGHT_ARROW_KEY = 'ArrowRight'\nconst DOWN_ARROW_KEY = 'ArrowDown'\nconst E_KEY = 'e'\n\nexport interface UseInputOTPProps {\n maxLength: number\n type: 'text' | 'number' | 'password' | 'tel'\n value?: string\n defaultValue: string\n onValueChange?: (value: string) => void\n isValid: boolean\n disabledProp: boolean\n readOnlyProp: boolean\n autoFocus: boolean\n forceUppercase: boolean\n filterKeys: string[]\n pattern?: string\n placeholder: string\n nameProp?: string\n}\n\nexport interface UseInputOTPReturn {\n uuid: string\n inputRef: React.RefObject<HTMLInputElement | null>\n containerRef: React.RefObject<HTMLDivElement | null>\n name: string | undefined\n disabled: boolean\n readOnly: boolean\n isInvalid: boolean\n isRequired: boolean\n description: string | undefined\n maxLength: number\n intent: 'neutral' | 'success' | 'alert' | 'error'\n currentValue: string\n activeIndex: number\n slots: {\n char: string\n isActive: boolean\n hasFakeCaret: boolean\n }[]\n contextValue: InputOTPContextValue\n handleChange: ChangeEventHandler<HTMLInputElement>\n handleKeyDown: KeyboardEventHandler<HTMLInputElement>\n handleCopy: ClipboardEventHandler<HTMLInputElement>\n handlePaste: ClipboardEventHandler<HTMLInputElement>\n handleFocus: () => void\n handleBlur: () => void\n handleClick: () => void\n labelId: string | undefined\n}\n\nexport const useInputOTP = ({\n maxLength,\n type,\n value: controlledValue,\n defaultValue,\n onValueChange,\n isValid,\n disabledProp,\n readOnlyProp,\n autoFocus,\n forceUppercase,\n filterKeys,\n pattern,\n placeholder,\n nameProp,\n}: UseInputOTPProps): UseInputOTPReturn => {\n const uuid = useId()\n const inputRef = useRef<HTMLInputElement>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n\n // Get FormField context (optional, falls back gracefully if not present)\n const field = useFormFieldControl()\n\n // Use FormField values if available, otherwise fall back to props\n // Use FormField id when available so label htmlFor works correctly\n const id = field.id ?? uuid\n const name = nameProp ?? field.name\n const disabled = field.disabled ?? disabledProp\n const readOnly = field.readOnly ?? readOnlyProp\n const isInvalid = field.isInvalid ?? !isValid\n const isRequired = field.isRequired ?? false\n const labelId = field.labelId\n const description = field.description\n const fieldState = field.state\n\n // Determine intent based on FormField state or isValid prop\n const getIntent = (): 'neutral' | 'success' | 'alert' | 'error' => {\n // FormField state takes priority\n if (['success', 'alert', 'error'].includes(fieldState ?? '')) {\n return fieldState as 'success' | 'alert' | 'error'\n }\n\n // Fallback to isValid prop for backward compatibility\n if (isInvalid) {\n return 'error'\n }\n\n return 'neutral'\n }\n\n const intent = getIntent()\n\n // Initialize value\n const initialValue = controlledValue !== undefined ? controlledValue : defaultValue\n const processedValue = forceUppercase ? initialValue.toUpperCase() : initialValue\n\n const [internalValue, setInternalValue] = useState<string>(processedValue)\n const [isFocused, setIsFocused] = useState<boolean>(false)\n\n // Use controlled value if provided, otherwise use internal state\n const currentValue = controlledValue !== undefined ? controlledValue : internalValue\n\n // Calculate active index: last empty slot, or last slot if all are filled\n const activeIndex = Math.min(currentValue.length, maxLength - 1)\n\n // Sync cursor position with active index\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.setSelectionRange(activeIndex, activeIndex)\n }\n }, [activeIndex, currentValue.length, maxLength])\n\n // Create slots array\n const slots = useMemo(\n () =>\n Array.from({ length: maxLength }, (_, i) => ({\n char: currentValue[i] || '',\n isActive: i === activeIndex && isFocused,\n hasFakeCaret: i === activeIndex && !currentValue[i] && !disabled && !readOnly && isFocused,\n })),\n [maxLength, currentValue, activeIndex, isFocused, disabled, readOnly]\n )\n\n // Sync controlled value with input ref\n useEffect(() => {\n if (inputRef.current && controlledValue !== undefined) {\n inputRef.current.value = controlledValue\n }\n }, [controlledValue])\n\n // Focus management\n useEffect(() => {\n if (autoFocus && inputRef.current) {\n inputRef.current.focus()\n }\n }, [autoFocus])\n\n const processInputValue = (inputValue: string): string => {\n let processed = inputValue\n\n if (forceUppercase) {\n processed = processed.toUpperCase()\n }\n\n if (type === 'number') {\n processed = processed.replace(/[^\\d]/g, '')\n }\n\n // Filter characters using pattern if provided\n if (pattern) {\n try {\n // Convert HTML pattern (string) to RegExp\n // HTML patterns validate the entire string, but we need to test each character\n // We create a regex that tests if a single character matches the pattern\n // For example: [0-9]* becomes ^[0-9]$ to test a single digit\n // We wrap the pattern in ^...$ to ensure it matches a single character\n let regexPattern = pattern\n // If pattern doesn't start with ^, wrap it to test single character\n if (!pattern.startsWith('^')) {\n regexPattern = `^${pattern}$`\n }\n const regex = new RegExp(regexPattern)\n processed = processed\n .split('')\n .filter(currChar => {\n // Test if the character matches the pattern\n return regex.test(currChar)\n })\n .join('')\n } catch (error) {\n // If pattern is invalid, ignore it and continue with other filters\n console.error('Invalid pattern provided to InputOTP:', pattern, error)\n }\n }\n\n return processed\n }\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = e => {\n if (disabled || readOnly) return\n\n const inputValue = e.target.value\n const processedValue = processInputValue(inputValue)\n\n // Limit to maxLength\n const newValue = processedValue.slice(0, maxLength)\n\n // Call onValueChange callback first (before updating state)\n if (onValueChange) {\n onValueChange(newValue)\n }\n\n // Update state only in uncontrolled mode\n if (controlledValue === undefined) {\n setInternalValue(newValue)\n }\n\n // Active index is automatically calculated based on value length\n // Sync cursor position\n const newActiveIndex = Math.min(newValue.length, maxLength - 1)\n if (inputRef.current) {\n inputRef.current.setSelectionRange(newActiveIndex, newActiveIndex)\n }\n }\n\n const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = e => {\n if (disabled || readOnly) return\n\n // Allow copy/cut/paste/selectAll shortcuts even when key is in filterKeys\n const isShortcut =\n (e.ctrlKey || e.metaKey) && ['a', 'c', 'v', 'x'].includes(e.key.toLowerCase())\n\n // Filter keys\n if (filterKeys.length > 0 && filterKeys.includes(e.key) && !isShortcut) {\n e.preventDefault()\n\n return\n }\n\n // Check if user is typing a printable character when input is full\n const isPrintableCharacter = e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey\n if (isPrintableCharacter && currentValue.length === maxLength) {\n e.preventDefault()\n\n // Process the new character through filters\n const processedChar = processInputValue(e.key)\n\n // If the character is filtered out, don't do anything\n if (processedChar.length === 0) {\n return\n }\n\n // Replace the last character with the new one\n const newValue = currentValue.slice(0, maxLength - 1) + processedChar\n\n // Call onValueChange callback\n if (onValueChange) {\n onValueChange(newValue)\n }\n\n // Update state only in uncontrolled mode\n if (controlledValue === undefined) {\n setInternalValue(newValue)\n }\n\n // Keep cursor at the end\n const newActiveIndex = maxLength - 1\n if (inputRef.current) {\n inputRef.current.setSelectionRange(newActiveIndex, newActiveIndex)\n }\n\n return\n }\n\n switch (e.key) {\n case BACKSPACE_KEY:\n e.preventDefault()\n const currentLength = currentValue.length\n if (currentLength > 0) {\n const newValue = currentValue.slice(0, currentLength - 1)\n\n // Call onValueChange first\n if (onValueChange) {\n onValueChange(newValue)\n }\n\n // Update state only in uncontrolled mode\n if (controlledValue === undefined) {\n setInternalValue(newValue)\n }\n\n // Active index is automatically calculated based on value length\n // Sync cursor position\n const newActiveIndex = Math.max(0, newValue.length)\n if (inputRef.current) {\n inputRef.current.setSelectionRange(newActiveIndex, newActiveIndex)\n }\n }\n break\n\n case LEFT_ARROW_KEY:\n case RIGHT_ARROW_KEY:\n // Prevent navigation with arrow keys - focus stays on last empty slot\n e.preventDefault()\n break\n\n case UP_ARROW_KEY:\n case DOWN_ARROW_KEY:\n e.preventDefault()\n break\n\n case E_KEY:\n case 'E':\n // Prevent 'e' or 'E' in number inputs\n if (type === 'number') {\n e.preventDefault()\n }\n break\n\n default:\n break\n }\n }\n\n const handleCopy: ClipboardEventHandler<HTMLInputElement> = e => {\n if (disabled) return\n\n e.preventDefault()\n if (currentValue.length > 0) {\n e.clipboardData.setData('text/plain', currentValue)\n }\n }\n\n const handlePaste: ClipboardEventHandler<HTMLInputElement> = e => {\n if (disabled || readOnly) return\n\n e.preventDefault()\n\n const pastedText = e.clipboardData.getData('text')\n\n if (!pastedText) return\n\n const processedText = processInputValue(pastedText)\n const newValue = processedText.slice(0, maxLength)\n\n // Call onValueChange callback first (before updating state)\n if (onValueChange) {\n onValueChange(newValue)\n }\n\n // Update state only in uncontrolled mode\n if (controlledValue === undefined) {\n setInternalValue(newValue)\n }\n\n // Active index is automatically calculated based on value length\n // Move cursor to end\n const newActiveIndex = Math.min(newValue.length, maxLength - 1)\n if (inputRef.current) {\n inputRef.current.setSelectionRange(newActiveIndex, newActiveIndex)\n }\n }\n\n const handleFocus = () => {\n setIsFocused(true)\n if (inputRef.current) {\n // Focus on last empty slot, or last slot if all are filled\n const cursorPosition = Math.min(currentValue.length, maxLength - 1)\n inputRef.current.setSelectionRange(cursorPosition, cursorPosition)\n }\n }\n\n const handleBlur = () => {\n setIsFocused(false)\n }\n\n const handleClick = () => {\n if (inputRef.current) {\n inputRef.current.focus()\n }\n }\n\n const contextValue: InputOTPContextValue = {\n value: currentValue,\n maxLength,\n slots,\n activeIndex,\n intent,\n disabled,\n readOnly,\n placeholder,\n type,\n }\n\n const returnValue: UseInputOTPReturn = {\n uuid: id,\n inputRef,\n containerRef,\n name,\n disabled,\n readOnly,\n isInvalid,\n isRequired,\n description,\n maxLength,\n intent,\n currentValue,\n activeIndex,\n slots,\n contextValue,\n handleChange,\n handleKeyDown,\n handleCopy,\n handlePaste,\n handleFocus,\n handleBlur,\n handleClick,\n labelId,\n }\n\n return returnValue\n}\n","/* eslint-disable max-lines-per-function */\nimport { cx } from 'class-variance-authority'\nimport {\n Children,\n cloneElement,\n ComponentPropsWithoutRef,\n isValidElement,\n ReactElement,\n ReactNode,\n Ref,\n useMemo,\n} from 'react'\n\nimport { InputOTPContext } from './InputOTPContext'\nimport { InputOTPSlot } from './InputOTPSlot'\nimport { useInputOTP } from './useInputOTP'\n\n/**\n * Counts the number of InputOTPSlot components in the children tree\n */\nconst countSlots = (children: ReactNode): number => {\n let count = 0\n\n Children.forEach(children, child => {\n if (isValidElement(child)) {\n const props = child.props as { children?: ReactNode }\n // Check if it's an InputOTPSlot by checking displayName\n if (\n child.type === InputOTPSlot ||\n (child.type as { displayName?: string })?.displayName === 'InputOTP.Slot'\n ) {\n count++\n } else if (props.children) {\n // Recursively count slots in nested children (e.g., inside InputOTPGroup)\n count += countSlots(props.children)\n }\n }\n })\n\n return count\n}\n\n/**\n * Recursively assigns index to InputOTPSlot components\n * Returns a tuple of [processedChildren, nextIndex]\n */\nconst assignSlotIndexes = (children: ReactNode, startIndex: number = 0): [ReactNode, number] => {\n let currentIndex = startIndex\n\n const processed = Children.map(children, child => {\n if (isValidElement(child)) {\n const props = child.props as { index?: number; children?: ReactNode }\n // Check if it's an InputOTPSlot\n if (\n child.type === InputOTPSlot ||\n (child.type as { displayName?: string })?.displayName === 'InputOTP.Slot'\n ) {\n // Only assign index if not already provided\n const slotIndex = typeof props.index === 'number' ? props.index : currentIndex++\n\n return cloneElement(child as ReactElement<{ index?: number }>, {\n ...props,\n index: slotIndex,\n })\n } else if (props.children) {\n // Recursively process nested children\n const [processedChildren, nextIndex] = assignSlotIndexes(props.children, currentIndex)\n currentIndex = nextIndex\n\n return cloneElement(child, {\n ...(child.props as Record<string, unknown>),\n children: processedChildren,\n } as Parameters<typeof cloneElement>[1])\n }\n }\n\n return child\n })\n\n return [processed, currentIndex]\n}\n\nexport interface InputOTPProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'onChange' | 'inputMode'\n> {\n /**\n * Maximum length of the input value.\n * If not provided, will be automatically detected from the number of InputOTP.Slot children.\n */\n maxLength?: number\n /**\n * Type of input\n * @default 'text'\n */\n type?: 'text' | 'number' | 'password' | 'tel'\n /**\n * Current value (controlled mode)\n */\n value?: string\n /**\n * Default value (uncontrolled mode)\n */\n defaultValue?: string\n /**\n * Callback fired when the value changes\n */\n onValueChange?: (value: string) => void\n /**\n * Whether the input is valid\n * @default true\n */\n isValid?: boolean\n /**\n * Whether the input is disabled\n * @default false\n */\n disabled?: boolean\n /**\n * Whether the input is read-only (value visible but not editable)\n * @default false\n */\n readOnly?: boolean\n /**\n * Whether to auto-focus the input\n * @default false\n */\n autoFocus?: boolean\n /**\n * Auto-complete attribute\n * @default 'off'\n */\n autoComplete?: string\n /**\n * Whether to force uppercase\n * @default false\n */\n forceUppercase?: boolean\n /**\n * Array of keys to filter out (using KeyboardEvent.key values)\n * @default ['-', '.']\n */\n filterKeys?: string[]\n /**\n * Pattern attribute for input validation and character filtering.\n * Uses a regular expression to filter allowed characters in real-time.\n * For example: \"[0-9]\" for digits only, \"[a-c]\" for letters a, b, c only.\n */\n pattern?: string\n /**\n * Input mode attribute\n */\n inputMode?: string\n /**\n * Placeholder text\n */\n placeholder?: string\n /**\n * Name attribute for form integration\n */\n name?: string\n /**\n * Children components (InputOTPGroup, InputOTPSlot, InputOTPSeparator)\n */\n children: ReactNode\n /**\n * Ref callback for the container\n */\n ref?: Ref<HTMLDivElement>\n}\n\nexport const InputOTP = ({\n maxLength: maxLengthProp,\n type = 'text',\n value: controlledValue,\n defaultValue = '',\n onValueChange,\n isValid = true,\n disabled: disabledProp = false,\n readOnly: readOnlyProp = false,\n autoFocus = false,\n autoComplete = 'off',\n forceUppercase = false,\n filterKeys = ['-', '.'],\n pattern,\n inputMode,\n placeholder = '-',\n name: nameProp,\n className,\n children,\n ...others\n}: InputOTPProps) => {\n // Auto-detect maxLength from children if not provided\n const maxLength = useMemo(() => {\n if (maxLengthProp !== undefined) {\n return maxLengthProp\n }\n\n const detectedLength = countSlots(children)\n const DEFAULT_MAX_LENGTH = 4\n\n return detectedLength > 0 ? detectedLength : DEFAULT_MAX_LENGTH // fallback to 4 if no slots found\n }, [maxLengthProp, children])\n\n // Assign indexes to slots automatically\n const processedChildren = useMemo(() => {\n const [processed] = assignSlotIndexes(children)\n\n return processed\n }, [children])\n\n // Use the hook for all business logic\n const {\n uuid,\n inputRef,\n containerRef,\n name,\n disabled,\n readOnly,\n isInvalid,\n isRequired,\n description,\n currentValue,\n contextValue,\n handleChange,\n handleKeyDown,\n handleCopy,\n handlePaste,\n handleFocus,\n handleBlur,\n handleClick,\n labelId,\n } = useInputOTP({\n maxLength,\n type,\n value: controlledValue,\n defaultValue,\n onValueChange,\n isValid,\n disabledProp,\n readOnlyProp,\n autoFocus,\n forceUppercase,\n filterKeys,\n pattern,\n placeholder,\n nameProp,\n })\n\n // Extract aria-label from others if provided (for cases without FormField)\n const ariaLabel =\n 'aria-label' in others ? (others['aria-label'] as string | undefined) : undefined\n const { 'aria-label': _, ...restOthers } = others\n\n const getAccessibleNameProps = (): Record<string, string | undefined> => {\n if (labelId) {\n return { 'aria-labelledby': labelId }\n }\n\n if (ariaLabel) {\n return { 'aria-label': ariaLabel }\n }\n\n return {}\n }\n\n const accessibleNameProps = getAccessibleNameProps()\n\n return (\n <InputOTPContext value={contextValue}>\n <div\n ref={containerRef}\n data-spark-component=\"input-otp\"\n role=\"group\"\n {...accessibleNameProps}\n {...(description ? { 'aria-describedby': description } : {})}\n className={cx(\n 'group gap-md relative inline-flex w-fit items-center default:cursor-text',\n {\n 'cursor-not-allowed': disabled,\n 'cursor-default': readOnly,\n },\n className\n )}\n onClick={handleClick}\n {...restOthers}\n >\n {/* Hidden input for form submission with complete value */}\n {name && (\n <input\n type=\"hidden\"\n name={name}\n value={currentValue}\n required={isRequired}\n aria-required={isRequired}\n aria-invalid={isInvalid}\n {...accessibleNameProps}\n />\n )}\n {/* Actual input that handles all interactions */}\n <input\n ref={inputRef}\n id={uuid}\n type={type === 'password' ? 'password' : 'text'}\n value={currentValue}\n maxLength={maxLength}\n autoFocus={autoFocus}\n autoComplete={autoComplete}\n disabled={disabled}\n readOnly={readOnly}\n pattern={pattern}\n inputMode={inputMode as React.InputHTMLAttributes<HTMLInputElement>['inputMode']}\n {...accessibleNameProps}\n {...(description ? { 'aria-describedby': description } : {})}\n aria-invalid={isInvalid}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onCopy={handleCopy}\n onPaste={handlePaste}\n onFocus={handleFocus}\n onBlur={handleBlur}\n className=\"bg-success z-raised absolute inset-0 m-0 p-0 opacity-0 read-only:cursor-default disabled:cursor-not-allowed\"\n tabIndex={0}\n />\n {/* Children render slots with auto-assigned indexes */}\n {processedChildren}\n </div>\n </InputOTPContext>\n )\n}\n\nInputOTP.displayName = 'InputOTP'\n","import { ComponentPropsWithoutRef } from 'react'\n\nexport interface InputOTPGroupProps extends ComponentPropsWithoutRef<'div'> {}\n\n/**\n * Container for a group of OTP input slots. Renders a <div> element.\n */\nexport const InputOTPGroup = ({ children, className, ...props }: InputOTPGroupProps) => {\n return (\n <div className={`gap-md flex ${className}`} {...props}>\n {children}\n </div>\n )\n}\n\nInputOTPGroup.displayName = 'InputOTP.Group'\n","import { ComponentPropsWithoutRef } from 'react'\n\nexport interface InputOTPSeparatorProps extends ComponentPropsWithoutRef<'div'> {}\n\n/**\n * A visual separator between OTP input groups. Renders a <div> element.\n */\nexport const InputOTPSeparator = ({ className, ...props }: InputOTPSeparatorProps) => {\n return (\n <div\n className={`text-on-surface/dim-3 flex items-center justify-center ${className || ''}`}\n {...props}\n >\n <div className=\"h-sz-4 w-sz-8 bg-outline rounded-full\" />\n </div>\n )\n}\n\nInputOTPSeparator.displayName = 'InputOTP.Separator'\n","import { InputOTP as Root } from './InputOTP'\nimport { InputOTPGroup } from './InputOTPGroup'\nimport { InputOTPSeparator } from './InputOTPSeparator'\nimport { InputOTPSlot } from './InputOTPSlot'\n\n/**\n * An input component for entering one-time passwords or verification codes with individual character slots.\n */\nexport const InputOTP: typeof Root & {\n Group: typeof InputOTPGroup\n Slot: typeof InputOTPSlot\n Separator: typeof InputOTPSeparator\n} = Object.assign(Root, {\n Group: InputOTPGroup,\n Slot: InputOTPSlot,\n Separator: InputOTPSeparator,\n})\n\nInputOTP.displayName = 'InputOTP'\nInputOTPGroup.displayName = 'InputOTP.Group'\nInputOTPSlot.displayName = 'InputOTP.Slot'\nInputOTPSeparator.displayName = 'InputOTP.Separator'\n\nexport { type InputOTPProps } from './InputOTP'\nexport { type InputOTPGroupProps } from './InputOTPGroup'\nexport { type InputOTPSlotProps } from './InputOTPSlot'\nexport { type InputOTPSeparatorProps } from './InputOTPSeparator'\nexport {\n inputOTPSlotStyles,\n inputOTPStyles,\n type InputOTPSlotStylesProps,\n type InputOTPStylesProps,\n} from './InputOTP.styles'\n"],"mappings":"4OAkBA,IAAa,GAAA,EAAA,EAAA,eAA6D,KAAK,CAElE,MAA2B,CACtC,IAAM,GAAA,EAAA,EAAA,YAAqB,EAAgB,CAC3C,GAAI,CAAC,EACH,MAAU,MAAM,mDAAmD,CAGrE,OAAO,ICxBI,EAAA,EAAA,KAA8B,CAAC,WAAY,cAAe,eAAgB,SAAS,CAAC,CAEjG,IAAa,GAAA,EAAA,EAAA,KACX,CAEE,4BACA,uBACA,6CACA,iBACA,oBACA,mCAIA,4BACA,gCACA,8BACA,kCACA,yCAEA,0CACA,sCACA,2CACA,6CAEA,sCACA,0DACA,2CACA,iFACD,CACD,CACE,SAAU,CAIR,OAAQ,CACN,QAAS,CAAC,oEAAoE,CAC9E,QAAS,CAAC,gEAAgE,CAC1E,MAAO,CAAC,0DAA0D,CAClE,MAAO,CAAC,0DAA0D,CACnE,CACF,CACD,gBAAiB,CACf,OAAQ,UACT,CACF,CACF,CAKY,EAAiB,ECrCjB,GAAgB,CAAE,MAAO,EAAW,YAAW,GAAG,KAA+B,CAC5F,IAAM,EAAU,GAAoB,CAG9B,EAAQ,GAAa,EACrB,EAAO,EAAQ,MAAM,GAE3B,GAAI,CAAC,EACH,OAAO,KAGT,GAAM,CAAE,OAAM,WAAU,gBAAiB,EACnC,EAAU,CAAC,EACX,EAAgB,GAAW,CAAC,GAAgB,EAAQ,YAEpD,EAAgB,IAAU,EAAQ,YAExC,OACE,EAAA,EAAA,MAAC,MAAD,CACE,UAAW,EAAmB,CAC5B,OAAQ,EAAQ,OAChB,YACD,CAAC,CACF,cAAa,EACb,gBAAe,EAAQ,SACvB,gBAAe,EAAQ,SACvB,cAAa,CAAC,EACd,oBAAmB,EACnB,aAAY,EAAQ,SAAW,QAC/B,GAAI,WAXN,EAaE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,EAAgB,wBAA0B,YACxD,EAAQ,OAAS,YAAc,EAC5B,IACA,IAAS,CAAC,GAAgB,EAAQ,YAAc,EAAQ,YAAc,IACrE,CAAA,CACN,IACC,EAAA,EAAA,KAAC,OAAD,CACE,UAAU,wEACV,cAAY,iBAEZ,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,8DAAgE,CAAA,CAC3E,CAAA,CAEL,IAIV,EAAa,YAAc,gBCjD3B,IAAM,EAAgB,YAChB,EAAiB,YACjB,EAAe,UACf,EAAkB,aAClB,EAAiB,YACjB,EAAQ,IAiDD,GAAe,CAC1B,YACA,OACA,MAAO,EACP,eACA,gBACA,UACA,eACA,eACA,YACA,iBACA,aACA,UACA,cACA,cACyC,CACzC,IAAM,GAAA,EAAA,EAAA,QAAc,CACd,GAAA,EAAA,EAAA,QAAoC,KAAK,CACzC,GAAA,EAAA,EAAA,QAAsC,KAAK,CAG3C,GAAA,EAAA,EAAA,sBAA6B,CAI7B,EAAK,EAAM,IAAM,EACjB,EAAO,GAAY,EAAM,KACzB,EAAW,EAAM,UAAY,EAC7B,EAAW,EAAM,UAAY,EAC7B,EAAY,EAAM,WAAa,CAAC,EAChC,EAAa,EAAM,YAAc,GACjC,EAAU,EAAM,QAChB,EAAc,EAAM,YACpB,EAAa,EAAM,MAiBnB,EAZA,CAAC,UAAW,QAAS,QAAQ,CAAC,SAAS,GAAc,GAAG,CACnD,EAIL,EACK,QAGF,UAMH,EAAe,IAAoB,IAAA,GAA8B,EAAlB,EAG/C,CAAC,EAAe,IAAA,EAAA,EAAA,UAFC,EAAiB,EAAa,aAAa,CAAG,EAEK,CACpE,CAAC,EAAW,IAAA,EAAA,EAAA,UAAkC,GAAM,CAGpD,EAAe,IAAoB,IAAA,GAA8B,EAAlB,EAG/C,EAAc,KAAK,IAAI,EAAa,OAAQ,EAAY,EAAE,EAGhE,EAAA,EAAA,eAAgB,CACV,EAAS,SACX,EAAS,QAAQ,kBAAkB,EAAa,EAAY,EAE7D,CAAC,EAAa,EAAa,OAAQ,EAAU,CAAC,CAGjD,IAAM,GAAA,EAAA,EAAA,aAEF,MAAM,KAAK,CAAE,OAAQ,EAAW,EAAG,EAAG,KAAO,CAC3C,KAAM,EAAa,IAAM,GACzB,SAAU,IAAM,GAAe,EAC/B,aAAc,IAAM,GAAe,CAAC,EAAa,IAAM,CAAC,GAAY,CAAC,GAAY,EAClF,EAAE,CACL,CAAC,EAAW,EAAc,EAAa,EAAW,EAAU,EAAS,CACtE,EAGD,EAAA,EAAA,eAAgB,CACV,EAAS,SAAW,IAAoB,IAAA,KAC1C,EAAS,QAAQ,MAAQ,IAE1B,CAAC,EAAgB,CAAC,EAGrB,EAAA,EAAA,eAAgB,CACV,GAAa,EAAS,SACxB,EAAS,QAAQ,OAAO,EAEzB,CAAC,EAAU,CAAC,CAEf,IAAM,EAAqB,GAA+B,CACxD,IAAI,EAAY,EAWhB,GATI,IACF,EAAY,EAAU,aAAa,EAGjC,IAAS,WACX,EAAY,EAAU,QAAQ,SAAU,GAAG,EAIzC,EACF,GAAI,CAMF,IAAI,EAAe,EAEd,EAAQ,WAAW,IAAI,GAC1B,EAAe,IAAI,EAAQ,IAE7B,IAAM,EAAQ,IAAI,OAAO,EAAa,CACtC,EAAY,EACT,MAAM,GAAG,CACT,OAAO,GAEC,EAAM,KAAK,EAAS,CAC3B,CACD,KAAK,GAAG,OACJ,EAAO,CAEd,QAAQ,MAAM,wCAAyC,EAAS,EAAM,CAI1E,OAAO,GAiOT,MA1BuC,CACrC,KAAM,EACN,WACA,eACA,OACA,WACA,WACA,YACA,aACA,cACA,YACA,SACA,eACA,cACA,QACA,aA3ByC,CACzC,MAAO,EACP,YACA,QACA,cACA,SACA,WACA,WACA,cACA,OACD,CAkBC,aApNyD,GAAK,CAC9D,GAAI,GAAY,EAAU,OAE1B,IAAM,EAAa,EAAE,OAAO,MAItB,EAHiB,EAAkB,EAAW,CAGpB,MAAM,EAAG,EAAU,CAG/C,GACF,EAAc,EAAS,CAIrB,IAAoB,IAAA,IACtB,EAAiB,EAAS,CAK5B,IAAM,EAAiB,KAAK,IAAI,EAAS,OAAQ,EAAY,EAAE,CAC3D,EAAS,SACX,EAAS,QAAQ,kBAAkB,EAAgB,EAAe,EA8LpE,cA1L4D,GAAK,CACjE,GAAI,GAAY,EAAU,OAG1B,IAAM,GACH,EAAE,SAAW,EAAE,UAAY,CAAC,IAAK,IAAK,IAAK,IAAI,CAAC,SAAS,EAAE,IAAI,aAAa,CAAC,CAGhF,GAAI,EAAW,OAAS,GAAK,EAAW,SAAS,EAAE,IAAI,EAAI,CAAC,EAAY,CACtE,EAAE,gBAAgB,CAElB,OAKF,GAD6B,EAAE,IAAI,SAAW,GAAK,CAAC,EAAE,SAAW,CAAC,EAAE,SAAW,CAAC,EAAE,QACtD,EAAa,SAAW,EAAW,CAC7D,EAAE,gBAAgB,CAGlB,IAAM,EAAgB,EAAkB,EAAE,IAAI,CAG9C,GAAI,EAAc,SAAW,EAC3B,OAIF,IAAM,EAAW,EAAa,MAAM,EAAG,EAAY,EAAE,CAAG,EAGpD,GACF,EAAc,EAAS,CAIrB,IAAoB,IAAA,IACtB,EAAiB,EAAS,CAI5B,IAAM,EAAiB,EAAY,EAC/B,EAAS,SACX,EAAS,QAAQ,kBAAkB,EAAgB,EAAe,CAGpE,OAGF,OAAQ,EAAE,IAAV,CACE,KAAK,EACH,EAAE,gBAAgB,CAClB,IAAM,EAAgB,EAAa,OACnC,GAAI,EAAgB,EAAG,CACrB,IAAM,EAAW,EAAa,MAAM,EAAG,EAAgB,EAAE,CAGrD,GACF,EAAc,EAAS,CAIrB,IAAoB,IAAA,IACtB,EAAiB,EAAS,CAK5B,IAAM,EAAiB,KAAK,IAAI,EAAG,EAAS,OAAO,CAC/C,EAAS,SACX,EAAS,QAAQ,kBAAkB,EAAgB,EAAe,CAGtE,MAEF,KAAK,EACL,KAAK,EAEH,EAAE,gBAAgB,CAClB,MAEF,KAAK,EACL,KAAK,EACH,EAAE,gBAAgB,CAClB,MAEF,KAAK,EACL,IAAK,IAEC,IAAS,UACX,EAAE,gBAAgB,CAEpB,MAEF,QACE,QA4FJ,WAxF0D,GAAK,CAC3D,IAEJ,EAAE,gBAAgB,CACd,EAAa,OAAS,GACxB,EAAE,cAAc,QAAQ,aAAc,EAAa,GAoFrD,YAhF2D,GAAK,CAChE,GAAI,GAAY,EAAU,OAE1B,EAAE,gBAAgB,CAElB,IAAM,EAAa,EAAE,cAAc,QAAQ,OAAO,CAElD,GAAI,CAAC,EAAY,OAGjB,IAAM,EADgB,EAAkB,EAAW,CACpB,MAAM,EAAG,EAAU,CAG9C,GACF,EAAc,EAAS,CAIrB,IAAoB,IAAA,IACtB,EAAiB,EAAS,CAK5B,IAAM,EAAiB,KAAK,IAAI,EAAS,OAAQ,EAAY,EAAE,CAC3D,EAAS,SACX,EAAS,QAAQ,kBAAkB,EAAgB,EAAe,EAuDpE,gBAnDwB,CAExB,GADA,EAAa,GAAK,CACd,EAAS,QAAS,CAEpB,IAAM,EAAiB,KAAK,IAAI,EAAa,OAAQ,EAAY,EAAE,CACnE,EAAS,QAAQ,kBAAkB,EAAgB,EAAe,GA+CpE,eA3CuB,CACvB,EAAa,GAAM,EA2CnB,gBAxCwB,CACpB,EAAS,SACX,EAAS,QAAQ,OAAO,EAuC1B,UACD,ECvZG,EAAc,GAAgC,CAClD,IAAI,EAAQ,EAkBZ,OAhBA,EAAA,SAAS,QAAQ,EAAU,GAAS,CAClC,IAAA,EAAA,EAAA,gBAAmB,EAAM,CAAE,CACzB,IAAM,EAAQ,EAAM,MAGlB,EAAM,OAAS,GACd,EAAM,MAAmC,cAAgB,gBAE1D,IACS,EAAM,WAEf,GAAS,EAAW,EAAM,SAAS,IAGvC,CAEK,GAOH,GAAqB,EAAqB,EAAqB,IAA2B,CAC9F,IAAI,EAAe,EAgCnB,MAAO,CA9BW,EAAA,SAAS,IAAI,EAAU,GAAS,CAChD,IAAA,EAAA,EAAA,gBAAmB,EAAM,CAAE,CACzB,IAAM,EAAQ,EAAM,MAEpB,GACE,EAAM,OAAS,GACd,EAAM,MAAmC,cAAgB,gBAC1D,CAEA,IAAM,EAAY,OAAO,EAAM,OAAU,SAAW,EAAM,MAAQ,IAElE,OAAA,EAAA,EAAA,cAAoB,EAA2C,CAC7D,GAAG,EACH,MAAO,EACR,CAAC,SACO,EAAM,SAAU,CAEzB,GAAM,CAAC,EAAmB,GAAa,EAAkB,EAAM,SAAU,EAAa,CAGtF,MAFA,GAAe,GAEf,EAAA,EAAA,cAAoB,EAAO,CACzB,GAAI,EAAM,MACV,SAAU,EACX,CAAuC,EAI5C,OAAO,GACP,CAEiB,EAAa,EA4FrB,GAAY,CACvB,UAAW,EACX,OAAO,OACP,MAAO,EACP,eAAe,GACf,gBACA,UAAU,GACV,SAAU,EAAe,GACzB,SAAU,EAAe,GACzB,YAAY,GACZ,eAAe,MACf,iBAAiB,GACjB,aAAa,CAAC,IAAK,IAAI,CACvB,UACA,YACA,cAAc,IACd,KAAM,EACN,YACA,WACA,GAAG,KACgB,CAEnB,IAAM,GAAA,EAAA,EAAA,aAA0B,CAC9B,GAAI,IAAkB,IAAA,GACpB,OAAO,EAGT,IAAM,EAAiB,EAAW,EAAS,CAG3C,OAAO,EAAiB,EAAI,EAFD,GAG1B,CAAC,EAAe,EAAS,CAAC,CAGvB,GAAA,EAAA,EAAA,aAAkC,CACtC,GAAM,CAAC,GAAa,EAAkB,EAAS,CAE/C,OAAO,GACN,CAAC,EAAS,CAAC,CAGR,CACJ,OACA,WACA,eACA,OACA,WACA,WACA,YACA,aACA,cACA,eACA,eACA,eACA,gBACA,aACA,cACA,cACA,aACA,cACA,WACE,EAAY,CACd,YACA,OACA,MAAO,EACP,eACA,gBACA,UACA,eACA,eACA,YACA,iBACA,aACA,UACA,cACA,WACD,CAAC,CAGI,EACJ,eAAgB,EAAU,EAAO,cAAuC,IAAA,GACpE,CAAE,aAAc,EAAG,GAAG,GAAe,EAcrC,EAXA,EACK,CAAE,kBAAmB,EAAS,CAGnC,EACK,CAAE,aAAc,EAAW,CAG7B,EAAE,CAKX,OACE,EAAA,EAAA,KAAC,EAAD,CAAiB,MAAO,YACtB,EAAA,EAAA,MAAC,MAAD,CACE,IAAK,EACL,uBAAqB,YACrB,KAAK,QACL,GAAI,EACJ,GAAK,EAAc,CAAE,mBAAoB,EAAa,CAAG,EAAE,CAC3D,WAAA,EAAA,EAAA,IACE,2EACA,CACE,qBAAsB,EACtB,iBAAkB,EACnB,CACD,EACD,CACD,QAAS,EACT,GAAI,WAfN,CAkBG,IACC,EAAA,EAAA,KAAC,QAAD,CACE,KAAK,SACC,OACN,MAAO,EACP,SAAU,EACV,gBAAe,EACf,eAAc,EACd,GAAI,EACJ,CAAA,EAGJ,EAAA,EAAA,KAAC,QAAD,CACE,IAAK,EACL,GAAI,EACJ,KAAM,IAAS,WAAa,WAAa,OACzC,MAAO,EACI,YACA,YACG,eACJ,WACA,WACD,UACE,YACX,GAAI,EACJ,GAAK,EAAc,CAAE,mBAAoB,EAAa,CAAG,EAAE,CAC3D,eAAc,EACd,SAAU,EACV,UAAW,EACX,OAAQ,EACR,QAAS,EACT,QAAS,EACT,OAAQ,EACR,UAAU,8GACV,SAAU,EACV,CAAA,CAED,EACG,GACU,CAAA,EAItB,EAAS,YAAc,WCpUvB,IAAa,GAAiB,CAAE,WAAU,YAAW,GAAG,MAEpD,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,eAAe,IAAa,GAAI,EAC7C,WACG,CAAA,CAIV,EAAc,YAAc,iBCR5B,IAAa,GAAqB,CAAE,YAAW,GAAG,MAE9C,EAAA,EAAA,KAAC,MAAD,CACE,UAAW,0DAA0D,GAAa,KAClF,GAAI,YAEJ,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,wCAA0C,CAAA,CACrD,CAAA,CAIV,EAAkB,YAAc,qBCVhC,IAAa,EAIT,OAAO,OAAO,EAAM,CACtB,MAAO,EACP,KAAM,EACN,UAAW,EACZ,CAAC,CAEF,EAAS,YAAc,WACvB,EAAc,YAAc,iBAC5B,EAAa,YAAc,gBAC3B,EAAkB,YAAc"}
@@ -146,40 +146,50 @@ var b = "Backspace", x = "ArrowLeft", S = "ArrowUp", C = "ArrowRight", w = "Arro
146
146
  let o = Math.min(a.length, e - 1);
147
147
  D.current && D.current.setSelectionRange(o, o);
148
148
  },
149
- handleKeyDown: (e) => {
149
+ handleKeyDown: (r) => {
150
150
  if (M || N) return;
151
- let r = (e.ctrlKey || e.metaKey) && [
151
+ let a = (r.ctrlKey || r.metaKey) && [
152
152
  "a",
153
153
  "c",
154
154
  "v",
155
155
  "x"
156
- ].includes(e.key.toLowerCase());
157
- if (g.length > 0 && g.includes(e.key) && !r) {
158
- e.preventDefault();
156
+ ].includes(r.key.toLowerCase());
157
+ if (g.length > 0 && g.includes(r.key) && !a) {
158
+ r.preventDefault();
159
159
  return;
160
160
  }
161
- switch (e.key) {
161
+ if (r.key.length === 1 && !r.ctrlKey && !r.metaKey && !r.altKey && G.length === e) {
162
+ r.preventDefault();
163
+ let t = J(r.key);
164
+ if (t.length === 0) return;
165
+ let a = G.slice(0, e - 1) + t;
166
+ i && i(a), n === void 0 && H(a);
167
+ let o = e - 1;
168
+ D.current && D.current.setSelectionRange(o, o);
169
+ return;
170
+ }
171
+ switch (r.key) {
162
172
  case b:
163
- e.preventDefault();
164
- let r = G.length;
165
- if (r > 0) {
166
- let e = G.slice(0, r - 1);
167
- i && i(e), n === void 0 && H(e);
168
- let t = Math.max(0, e.length);
169
- D.current && D.current.setSelectionRange(t, t);
173
+ r.preventDefault();
174
+ let e = G.length;
175
+ if (e > 0) {
176
+ let t = G.slice(0, e - 1);
177
+ i && i(t), n === void 0 && H(t);
178
+ let r = Math.max(0, t.length);
179
+ D.current && D.current.setSelectionRange(r, r);
170
180
  }
171
181
  break;
172
182
  case x:
173
183
  case C:
174
- e.preventDefault();
184
+ r.preventDefault();
175
185
  break;
176
186
  case S:
177
187
  case w:
178
- e.preventDefault();
188
+ r.preventDefault();
179
189
  break;
180
190
  case T:
181
191
  case "E":
182
- t === "number" && e.preventDefault();
192
+ t === "number" && r.preventDefault();
183
193
  break;
184
194
  default: break;
185
195
  }
@@ -264,7 +274,7 @@ var b = "Backspace", x = "ArrowLeft", S = "ArrowUp", C = "ArrowRight", w = "Arro
264
274
  placeholder: y,
265
275
  nameProp: b
266
276
  }), J = "aria-label" in C ? C["aria-label"] : void 0, { "aria-label": Y, ...X } = C, Z = q ? { "aria-labelledby": q } : J ? { "aria-label": J } : {};
267
- return /* @__PURE__ */ f(h.Provider, {
277
+ return /* @__PURE__ */ f(h, {
268
278
  value: z,
269
279
  children: /* @__PURE__ */ p("div", {
270
280
  ref: j,