@spark-ui/components 16.0.1 → 16.0.2

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.
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),u=require("class-variance-authority"),n=require("react"),$=require("../Slot-DQ8z2zsy.js"),z=require("@spark-ui/icons/AlertOutline"),V=require("@spark-ui/icons/Check"),w=require("@spark-ui/icons/WarningOutline"),I=require("../Icon-CF0W0LKr.js"),W=require("../label/index.js"),M=require("../FormFieldRequiredIndicator-CHfcoT2y.js"),N=n.createContext(null),j=":form-field",y=()=>{const s=n.useContext(N);if(!s)throw Error("useFormField must be used within a FormField provider");return s},E=({id:s,name:e,disabled:t=!1,readOnly:l=!1,state:o,isRequired:i,children:d})=>{const a=`${j}-label-${n.useId()}`,[c,m]=n.useState([]),F=c.length>0?c.join(" "):void 0,g=n.useCallback(x=>{m(h=>[...h,x])},[]),A=n.useCallback(x=>{m(h=>h.filter(T=>T!==x))},[]),L=n.useMemo(()=>({id:s,labelId:a,name:e,disabled:t,readOnly:l,state:o,isRequired:i,isInvalid:o==="error",description:F,onMessageIdAdd:g,onMessageIdRemove:A}),[s,a,e,t,l,F,o,i,g,A]);return r.jsx(N.Provider,{value:L,children:d})};E.displayName="FormFieldProvider";const O=({className:s,disabled:e=!1,readOnly:t=!1,name:l,state:o,isRequired:i=!1,asChild:d=!1,ref:a,...c})=>{const m=`${j}-${n.useId()}`,F=d?$.Slot:"div";return r.jsx(E,{id:m,name:l,isRequired:i,disabled:e,readOnly:t,state:o,children:r.jsx(F,{ref:a,"data-spark-component":"form-field",className:u.cx(s,"gap-sm flex flex-col"),...c})})};O.displayName="FormField";const f=({id:s,className:e,ref:t,...l})=>{const{onMessageIdAdd:o,onMessageIdRemove:i}=y(),d=`${j}-message-${n.useId()}`,a=s||d;return n.useEffect(()=>(o(a),()=>{i(a)}),[a,o,i]),r.jsx("span",{ref:t,id:a,"data-spark-component":"form-field-message",className:u.cx(e,"text-caption"),...l})};f.displayName="FormField.Message";const p=({className:s,state:e,children:t,ref:l,...o})=>y().state!==e?null:r.jsxs(f,{ref:l,"data-spark-component":"form-field-state-message",className:u.cx("gap-sm flex items-center",e==="error"?"text-error":"text-on-surface/dim-1",s),...o,children:[e==="alert"&&r.jsx(I.Icon,{size:"sm",children:r.jsx(w.WarningOutline,{})}),e==="error"&&r.jsx(I.Icon,{size:"sm",intent:"error",children:r.jsx(z.AlertOutline,{})}),e==="success"&&r.jsx(I.Icon,{size:"sm",children:r.jsx(V.Check,{})}),t]});p.displayName="FormField.StateMessage";const C=({ref:s,...e})=>r.jsx(p,{ref:s,"data-spark-component":"form-field-alert-message",state:"alert",...e});C.displayName="FormField.AlertMessage";const b=({className:s,value:e="",maxLength:t,description:l,liveAnnouncement:o,ref:i,...d})=>{const[a,c]=n.useState(e);return n.useEffect(()=>{const m=setTimeout(()=>{c(e)},1e3);return()=>clearTimeout(m)},[e]),r.jsxs("span",{className:"ml-auto self-start",children:[l&&r.jsx(f,{className:"default:sr-only",children:l}),r.jsx("span",{ref:i,"aria-hidden":!0,"data-spark-component":"form-field-characters-count",className:u.cx(s,"text-caption","text-neutral"),...d,children:`${e.length}/${t}`}),o&&r.jsx("span",{className:"sr-only","aria-live":"polite",children:o({remainingChars:t-a.length})})]})};b.displayName="FormField.CharactersCount";const P=()=>{const{id:s,name:e,description:t,disabled:l,readOnly:o,state:i,labelId:d,isInvalid:a,isRequired:c}=n.useContext(N)||{};return{id:s,name:e,description:t,disabled:l,readOnly:o,state:i,labelId:d,isInvalid:a,isRequired:c}},q=({children:s})=>{const e=P();return r.jsx(r.Fragment,{children:s(e)})};q.displayName="FormField.Control";const S=({ref:s,...e})=>r.jsx(p,{ref:s,"data-spark-component":"form-field-error-message",state:"error",...e});S.displayName="FormField.ErrorMessage";const v=({className:s,ref:e,...t})=>r.jsx(f,{ref:e,"data-spark-component":"form-field-helper-message",className:u.cx("text-on-surface/dim-1",s),...t});v.displayName="FormField.HelperMessage";const k=({htmlFor:s,className:e,children:t,requiredIndicator:l=r.jsx(M.FormFieldRequiredIndicator,{}),asChild:o,ref:i,...d})=>{const a=y(),{disabled:c,labelId:m,isRequired:F}=a,g=o?void 0:s||a.id;return r.jsx(W.Label,{ref:i,id:m,"data-spark-component":"form-field-label",htmlFor:g,className:u.cx(e,c?"text-on-surface/dim-3 pointer-events-none":void 0),asChild:o,...d,children:r.jsxs(r.Fragment,{children:[r.jsx($.Slottable,{children:t}),F&&l]})})};k.displayName="FormField.Label";const R=({ref:s,...e})=>r.jsx(p,{ref:s,"data-spark-component":"form-field-success-message",state:"success",...e});R.displayName="FormField.SuccessMessage";const H=Object.assign(O,{Label:k,Control:q,StateMessage:p,SuccessMessage:R,AlertMessage:C,ErrorMessage:S,HelperMessage:v,RequiredIndicator:M.FormFieldRequiredIndicator,CharactersCount:b});H.displayName="FormField";k.displayName="FormField.Label";q.displayName="FormField.Control";p.displayName="FormField.StateMessage";R.displayName="FormField.SuccessMessage";C.displayName="FormField.AlertMessage";S.displayName="FormField.ErrorMessage";v.displayName="FormField.HelperMessage";M.FormFieldRequiredIndicator.displayName="FormField.RequiredIndicator";b.displayName="FormField.CharactersCount";exports.FormField=H;exports.useFormFieldControl=P;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),u=require("class-variance-authority"),n=require("react"),$=require("../Slot-DQ8z2zsy.js"),z=require("@spark-ui/icons/AlertOutline"),V=require("@spark-ui/icons/Check"),w=require("@spark-ui/icons/WarningOutline"),I=require("../Icon-CF0W0LKr.js"),W=require("../label/index.js"),M=require("../FormFieldRequiredIndicator-CHfcoT2y.js"),N=n.createContext(null),j=":form-field",y=()=>{const s=n.useContext(N);if(!s)throw Error("useFormField must be used within a FormField provider");return s},E=({id:s,name:e,disabled:t=!1,readOnly:l=!1,state:o,isRequired:i,children:d})=>{const a=`${j}-label-${n.useId()}`,[c,m]=n.useState([]),F=c.length>0?c.join(" "):void 0,g=n.useCallback(x=>{m(h=>[...h,x])},[]),A=n.useCallback(x=>{m(h=>h.filter(T=>T!==x))},[]),L=n.useMemo(()=>({id:s,labelId:a,name:e,disabled:t,readOnly:l,state:o,isRequired:i,isInvalid:o==="error",description:F,onMessageIdAdd:g,onMessageIdRemove:A}),[s,a,e,t,l,F,o,i,g,A]);return r.jsx(N.Provider,{value:L,children:d})};E.displayName="FormFieldProvider";const O=({className:s,disabled:e=!1,readOnly:t=!1,name:l,state:o,isRequired:i=!1,asChild:d=!1,ref:a,...c})=>{const m=`${j}-${n.useId()}`,F=d?$.Slot:"div";return r.jsx(E,{id:m,name:l,isRequired:i,disabled:e,readOnly:t,state:o,children:r.jsx(F,{ref:a,"data-spark-component":"form-field",className:u.cx(s,"gap-md flex flex-col"),...c})})};O.displayName="FormField";const f=({id:s,className:e,ref:t,...l})=>{const{onMessageIdAdd:o,onMessageIdRemove:i}=y(),d=`${j}-message-${n.useId()}`,a=s||d;return n.useEffect(()=>(o(a),()=>{i(a)}),[a,o,i]),r.jsx("span",{ref:t,id:a,"data-spark-component":"form-field-message",className:u.cx(e,"text-caption"),...l})};f.displayName="FormField.Message";const p=({className:s,state:e,children:t,ref:l,...o})=>y().state!==e?null:r.jsxs(f,{ref:l,"data-spark-component":"form-field-state-message",className:u.cx("gap-sm flex items-center",e==="error"?"text-error":"text-on-surface/dim-1",s),...o,children:[e==="alert"&&r.jsx(I.Icon,{size:"sm",children:r.jsx(w.WarningOutline,{})}),e==="error"&&r.jsx(I.Icon,{size:"sm",intent:"error",children:r.jsx(z.AlertOutline,{})}),e==="success"&&r.jsx(I.Icon,{size:"sm",children:r.jsx(V.Check,{})}),t]});p.displayName="FormField.StateMessage";const C=({ref:s,...e})=>r.jsx(p,{ref:s,"data-spark-component":"form-field-alert-message",state:"alert",...e});C.displayName="FormField.AlertMessage";const b=({className:s,value:e="",maxLength:t,description:l,liveAnnouncement:o,ref:i,...d})=>{const[a,c]=n.useState(e);return n.useEffect(()=>{const m=setTimeout(()=>{c(e)},1e3);return()=>clearTimeout(m)},[e]),r.jsxs("span",{className:"ml-auto self-start",children:[l&&r.jsx(f,{className:"default:sr-only",children:l}),r.jsx("span",{ref:i,"aria-hidden":!0,"data-spark-component":"form-field-characters-count",className:u.cx(s,"text-caption","text-neutral"),...d,children:`${e.length}/${t}`}),o&&r.jsx("span",{className:"sr-only","aria-live":"polite",children:o({remainingChars:t-a.length})})]})};b.displayName="FormField.CharactersCount";const P=()=>{const{id:s,name:e,description:t,disabled:l,readOnly:o,state:i,labelId:d,isInvalid:a,isRequired:c}=n.useContext(N)||{};return{id:s,name:e,description:t,disabled:l,readOnly:o,state:i,labelId:d,isInvalid:a,isRequired:c}},q=({children:s})=>{const e=P();return r.jsx(r.Fragment,{children:s(e)})};q.displayName="FormField.Control";const S=({ref:s,...e})=>r.jsx(p,{ref:s,"data-spark-component":"form-field-error-message",state:"error",...e});S.displayName="FormField.ErrorMessage";const v=({className:s,ref:e,...t})=>r.jsx(f,{ref:e,"data-spark-component":"form-field-helper-message",className:u.cx("text-on-surface/dim-1",s),...t});v.displayName="FormField.HelperMessage";const k=({htmlFor:s,className:e,children:t,requiredIndicator:l=r.jsx(M.FormFieldRequiredIndicator,{}),asChild:o,ref:i,...d})=>{const a=y(),{disabled:c,labelId:m,isRequired:F}=a,g=o?void 0:s||a.id;return r.jsx(W.Label,{ref:i,id:m,"data-spark-component":"form-field-label",htmlFor:g,className:u.cx(e,c?"text-on-surface/dim-3 pointer-events-none":void 0),asChild:o,...d,children:r.jsxs(r.Fragment,{children:[r.jsx($.Slottable,{children:t}),F&&l]})})};k.displayName="FormField.Label";const R=({ref:s,...e})=>r.jsx(p,{ref:s,"data-spark-component":"form-field-success-message",state:"success",...e});R.displayName="FormField.SuccessMessage";const H=Object.assign(O,{Label:k,Control:q,StateMessage:p,SuccessMessage:R,AlertMessage:C,ErrorMessage:S,HelperMessage:v,RequiredIndicator:M.FormFieldRequiredIndicator,CharactersCount:b});H.displayName="FormField";k.displayName="FormField.Label";q.displayName="FormField.Control";p.displayName="FormField.StateMessage";R.displayName="FormField.SuccessMessage";C.displayName="FormField.AlertMessage";S.displayName="FormField.ErrorMessage";v.displayName="FormField.HelperMessage";M.FormFieldRequiredIndicator.displayName="FormField.RequiredIndicator";b.displayName="FormField.CharactersCount";exports.FormField=H;exports.useFormFieldControl=P;
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/form-field/FormFieldContext.tsx","../../src/form-field/FormFieldProvider.tsx","../../src/form-field/FormField.tsx","../../src/form-field/FormFieldMessage.tsx","../../src/form-field/FormFieldStateMessage.tsx","../../src/form-field/FormFieldAlertMessage.tsx","../../src/form-field/FormFieldCharactersCount.tsx","../../src/form-field/FormFieldControl.tsx","../../src/form-field/FormFieldErrorMessage.tsx","../../src/form-field/FormFieldHelperMessage.tsx","../../src/form-field/FormFieldLabel.tsx","../../src/form-field/FormFieldSuccessMessage.tsx","../../src/form-field/index.ts"],"sourcesContent":["import { createContext, useContext } from 'react'\n\nexport interface FormFieldContextState {\n /**\n * Generated id for the input component.\n */\n id: string\n /**\n * Generated id for the label component.\n */\n labelId?: string\n /**\n * The name of the input. Submitted with its owning form as part of a name/value pair.\n */\n name?: string\n /**\n * A set of ids separated by a space used to describe the input component given by a set of messages.\n */\n description?: string\n /**\n * Disables the field and its associated input\n */\n disabled?: boolean\n /**\n * Marks the field and its associated input as read only\n */\n readOnly?: boolean\n /**\n * The validation state of the input.\n */\n state?: 'error' | 'success' | 'alert'\n /**\n * If true, the form field will be invalid.\n */\n isInvalid?: boolean\n /**\n * If true, the form field will be required.\n */\n isRequired?: boolean\n /**\n * Callback used to store a descriptive message.\n */\n onMessageIdAdd: (id: string) => void\n /**\n * Callback used to remove a descriptive message.\n */\n onMessageIdRemove: (id: string) => void\n}\n\nexport const FormFieldContext = createContext<FormFieldContextState | null>(null)\n\nexport const ID_PREFIX = ':form-field'\n\nexport const useFormField = () => {\n const context = useContext(FormFieldContext)\n\n if (!context) {\n throw Error('useFormField must be used within a FormField provider')\n }\n\n return context\n}\n","import { ReactNode, useCallback, useId, useMemo, useState } from 'react'\n\nimport { FormFieldContext, FormFieldContextState, ID_PREFIX } from './FormFieldContext'\n\nexport interface FormFieldProviderProps\n extends Pick<\n FormFieldContextState,\n 'id' | 'name' | 'disabled' | 'readOnly' | 'state' | 'isRequired'\n > {\n children: ReactNode\n}\n\nexport const FormFieldProvider = ({\n id,\n name,\n disabled = false,\n readOnly = false,\n state,\n isRequired,\n children,\n}: FormFieldProviderProps) => {\n const labelId = `${ID_PREFIX}-label-${useId()}`\n const [messageIds, setMessageIds] = useState<string[]>([])\n const description = messageIds.length > 0 ? messageIds.join(' ') : undefined\n\n const handleMessageIdAdd = useCallback((msgId: string) => {\n setMessageIds(ids => [...ids, msgId])\n }, [])\n\n const handleMessageIdRemove = useCallback((msgId: string) => {\n setMessageIds(ids => ids.filter(current => current !== msgId))\n }, [])\n\n const value = useMemo(() => {\n const isInvalid = state === 'error'\n\n return {\n id,\n labelId,\n name,\n disabled,\n readOnly,\n state,\n isRequired,\n isInvalid,\n description,\n onMessageIdAdd: handleMessageIdAdd,\n onMessageIdRemove: handleMessageIdRemove,\n }\n }, [\n id,\n labelId,\n name,\n disabled,\n readOnly,\n description,\n state,\n isRequired,\n handleMessageIdAdd,\n handleMessageIdRemove,\n ])\n\n return <FormFieldContext.Provider value={value}>{children}</FormFieldContext.Provider>\n}\n\nFormFieldProvider.displayName = 'FormFieldProvider'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref, useId } from 'react'\n\nimport { Slot } from '../slot'\nimport { FormFieldContextState, ID_PREFIX } from './FormFieldContext'\nimport { FormFieldProvider } from './FormFieldProvider'\n\nexport interface FormFieldProps\n extends ComponentPropsWithoutRef<'div'>,\n Pick<FormFieldContextState, 'name' | 'state' | 'isRequired'> {\n /**\n * Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.\n */\n asChild?: boolean\n /**\n * When `true`, prevents the user from interacting.\n */\n disabled?: boolean\n /**\n * Sets the component as interactive or not.\n */\n readOnly?: boolean\n ref?: Ref<HTMLDivElement>\n}\n\nexport const FormField = ({\n className,\n disabled = false,\n readOnly = false,\n name,\n state,\n isRequired = false,\n asChild = false,\n ref,\n ...others\n}: FormFieldProps) => {\n const id = `${ID_PREFIX}-${useId()}`\n const Component = asChild ? Slot : 'div'\n\n return (\n <FormFieldProvider\n id={id}\n name={name}\n isRequired={isRequired}\n disabled={disabled}\n readOnly={readOnly}\n state={state}\n >\n <Component\n ref={ref}\n data-spark-component=\"form-field\"\n className={cx(className, 'gap-sm flex flex-col')}\n {...others}\n />\n </FormFieldProvider>\n )\n}\n\nFormField.displayName = 'FormField'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref, useEffect, useId } from 'react'\n\nimport { ID_PREFIX, useFormField } from './FormFieldContext'\n\nexport type FormFieldMessageProps = ComponentPropsWithoutRef<'span'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldMessage = ({\n id: idProp,\n className,\n ref,\n ...others\n}: FormFieldMessageProps) => {\n const { onMessageIdAdd, onMessageIdRemove } = useFormField()\n const currentId = `${ID_PREFIX}-message-${useId()}`\n const id = idProp || currentId\n\n useEffect(() => {\n onMessageIdAdd(id)\n\n return () => {\n onMessageIdRemove(id)\n }\n }, [id, onMessageIdAdd, onMessageIdRemove])\n\n return (\n <span\n ref={ref}\n id={id}\n data-spark-component=\"form-field-message\"\n className={cx(className, 'text-caption')}\n {...others}\n />\n )\n}\n\nFormFieldMessage.displayName = 'FormField.Message'\n","import { AlertOutline } from '@spark-ui/icons/AlertOutline'\nimport { Check } from '@spark-ui/icons/Check'\nimport { WarningOutline } from '@spark-ui/icons/WarningOutline'\nimport { cx } from 'class-variance-authority'\nimport { Ref } from 'react'\n\nimport { Icon } from '../icon'\nimport { useFormField } from './FormFieldContext'\nimport { FormFieldMessage, FormFieldMessageProps } from './FormFieldMessage'\n\nexport interface FormFieldStateMessageProps extends FormFieldMessageProps {\n state: 'error' | 'alert' | 'success'\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldStateMessage = ({\n className,\n state,\n children,\n ref,\n ...others\n}: FormFieldStateMessageProps) => {\n const field = useFormField()\n\n if (field.state !== state) {\n return null\n }\n\n return (\n <FormFieldMessage\n ref={ref}\n data-spark-component=\"form-field-state-message\"\n className={cx(\n 'gap-sm flex items-center',\n state === 'error' ? 'text-error' : 'text-on-surface/dim-1',\n className\n )}\n {...others}\n >\n {state === 'alert' && (\n <Icon size=\"sm\">\n <WarningOutline />\n </Icon>\n )}\n {state === 'error' && (\n <Icon size=\"sm\" intent=\"error\">\n <AlertOutline />\n </Icon>\n )}\n {state === 'success' && (\n <Icon size=\"sm\">\n <Check />\n </Icon>\n )}\n\n {children}\n </FormFieldMessage>\n )\n}\n\nFormFieldStateMessage.displayName = 'FormField.StateMessage'\n","import { Ref } from 'react'\n\nimport { FormFieldStateMessage, FormFieldStateMessageProps } from './FormFieldStateMessage'\n\nexport type FormFieldAlertMessageProps = Omit<FormFieldStateMessageProps, 'state'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldAlertMessage = ({ ref, ...props }: FormFieldAlertMessageProps) => {\n return (\n <FormFieldStateMessage\n ref={ref}\n data-spark-component=\"form-field-alert-message\"\n state=\"alert\"\n {...props}\n />\n )\n}\n\nFormFieldAlertMessage.displayName = 'FormField.AlertMessage'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref, useEffect, useState } from 'react'\n\nimport { FormFieldMessage } from './FormFieldMessage'\n\nexport type FormFieldCharactersCountProps = ComponentPropsWithoutRef<'span'> & {\n /**\n * This description is for the screen reader, read when the input is focused.\n */\n description?: string\n /**\n * The live announcement is for the screen read after a delay once the input value changes.\n */\n liveAnnouncement?: ({ remainingChars }: { remainingChars: number }) => string\n /**\n * Current value for the input this component belongs to.\n */\n value?: string\n /**\n * Maximum numeric value to be displayed.\n */\n maxLength: number\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldCharactersCount = ({\n className,\n value = '',\n maxLength,\n description,\n liveAnnouncement,\n ref,\n ...others\n}: FormFieldCharactersCountProps) => {\n const [throttledValue, setThrottledValue] = useState(value)\n\n /**\n * The value is throttled to avoid spamming the aria-live region (and consequently the screen reader).\n */\n useEffect(() => {\n const timeoutId = setTimeout(() => {\n setThrottledValue(value)\n }, 1000)\n\n return () => clearTimeout(timeoutId)\n }, [value])\n\n return (\n <span className=\"ml-auto self-start\">\n {description && (\n <FormFieldMessage className=\"default:sr-only\">{description}</FormFieldMessage>\n )}\n <span\n ref={ref}\n aria-hidden\n data-spark-component=\"form-field-characters-count\"\n className={cx(className, 'text-caption', 'text-neutral')}\n {...others}\n >\n {`${value.length}/${maxLength}`}\n </span>\n\n {liveAnnouncement && (\n <span className=\"sr-only\" aria-live=\"polite\">\n {liveAnnouncement({ remainingChars: maxLength - throttledValue.length })}\n </span>\n )}\n </span>\n )\n}\n\nFormFieldCharactersCount.displayName = 'FormField.CharactersCount'\n","import { ReactNode, useContext } from 'react'\n\nimport { FormFieldContext, FormFieldContextState } from './FormFieldContext'\n\ntype State = Partial<\n Pick<\n FormFieldContextState,\n | 'id'\n | 'name'\n | 'description'\n | 'labelId'\n | 'disabled'\n | 'readOnly'\n | 'state'\n | 'isInvalid'\n | 'isRequired'\n >\n>\n\nexport interface FormFieldControlProps {\n children: (state: State) => ReactNode\n}\n\nexport const useFormFieldControl = () => {\n const { id, name, description, disabled, readOnly, state, labelId, isInvalid, isRequired } =\n useContext(FormFieldContext) || {}\n\n return {\n id,\n name,\n description,\n disabled,\n readOnly,\n state,\n labelId,\n isInvalid,\n isRequired,\n } as State\n}\n\nexport const FormFieldControl = ({ children }: FormFieldControlProps) => {\n const props = useFormFieldControl()\n\n return <>{children(props)}</>\n}\n\nFormFieldControl.displayName = 'FormField.Control'\n","import { Ref } from 'react'\n\nimport { FormFieldStateMessage, FormFieldStateMessageProps } from './FormFieldStateMessage'\n\nexport type FormFieldErrorMessageProps = Omit<FormFieldStateMessageProps, 'state'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldErrorMessage = ({ ref, ...props }: FormFieldErrorMessageProps) => {\n return (\n <FormFieldStateMessage\n ref={ref}\n data-spark-component=\"form-field-error-message\"\n state=\"error\"\n {...props}\n />\n )\n}\n\nFormFieldErrorMessage.displayName = 'FormField.ErrorMessage'\n","import { cx } from 'class-variance-authority'\nimport { Ref } from 'react'\n\nimport { FormFieldMessage, FormFieldMessageProps } from './FormFieldMessage'\n\nexport type FormFieldHelperMessageProps = FormFieldMessageProps & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldHelperMessage = ({\n className,\n ref,\n ...others\n}: FormFieldHelperMessageProps) => {\n return (\n <FormFieldMessage\n ref={ref}\n data-spark-component=\"form-field-helper-message\"\n className={cx('text-on-surface/dim-1', className)}\n {...others}\n />\n )\n}\n\nFormFieldHelperMessage.displayName = 'FormField.HelperMessage'\n","import { cx } from 'class-variance-authority'\nimport { ReactNode, Ref } from 'react'\n\nimport { Label, LabelProps } from '../label'\nimport { Slottable } from '../slot'\nimport { useFormField } from './FormFieldContext'\nimport { FormFieldRequiredIndicator } from './FormFieldRequiredIndicator'\n\nexport interface FormFieldLabelProps extends LabelProps {\n /**\n * Element shown when the input is required inside the label.\n */\n requiredIndicator?: ReactNode\n ref?: Ref<HTMLLabelElement>\n}\n\nexport const FormFieldLabel = ({\n htmlFor: htmlForProp,\n className,\n children,\n requiredIndicator = <FormFieldRequiredIndicator />,\n asChild,\n ref,\n ...others\n}: FormFieldLabelProps) => {\n const control = useFormField()\n\n const { disabled, labelId, isRequired } = control\n const htmlFor = asChild ? undefined : htmlForProp || control.id\n\n return (\n <Label\n ref={ref}\n id={labelId}\n data-spark-component=\"form-field-label\"\n htmlFor={htmlFor}\n className={cx(className, disabled ? 'text-on-surface/dim-3 pointer-events-none' : undefined)}\n asChild={asChild}\n {...others}\n >\n <>\n <Slottable>{children}</Slottable>\n {isRequired && requiredIndicator}\n </>\n </Label>\n )\n}\n\nFormFieldLabel.displayName = 'FormField.Label'\n","import { Ref } from 'react'\n\nimport { FormFieldStateMessage, FormFieldStateMessageProps } from './FormFieldStateMessage'\n\nexport type FormFieldSuccessMessageProps = Omit<FormFieldStateMessageProps, 'state'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldSuccessMessage = ({ ref, ...props }: FormFieldSuccessMessageProps) => {\n return (\n <FormFieldStateMessage\n ref={ref}\n data-spark-component=\"form-field-success-message\"\n state=\"success\"\n {...props}\n />\n )\n}\n\nFormFieldSuccessMessage.displayName = 'FormField.SuccessMessage'\n","import { FormField as Root } from './FormField'\nimport { FormFieldAlertMessage } from './FormFieldAlertMessage'\nimport { FormFieldCharactersCount } from './FormFieldCharactersCount'\nimport { FormFieldControl } from './FormFieldControl'\nimport { FormFieldErrorMessage } from './FormFieldErrorMessage'\nimport { FormFieldHelperMessage } from './FormFieldHelperMessage'\nimport { FormFieldLabel } from './FormFieldLabel'\nimport { FormFieldRequiredIndicator } from './FormFieldRequiredIndicator'\nimport { FormFieldStateMessage } from './FormFieldStateMessage'\nimport { FormFieldSuccessMessage } from './FormFieldSuccessMessage'\n\nexport const FormField: typeof Root & {\n Label: typeof FormFieldLabel\n Control: typeof FormFieldControl\n StateMessage: typeof FormFieldStateMessage\n SuccessMessage: typeof FormFieldSuccessMessage\n AlertMessage: typeof FormFieldAlertMessage\n ErrorMessage: typeof FormFieldErrorMessage\n HelperMessage: typeof FormFieldHelperMessage\n RequiredIndicator: typeof FormFieldRequiredIndicator\n CharactersCount: typeof FormFieldCharactersCount\n} = Object.assign(Root, {\n Label: FormFieldLabel,\n Control: FormFieldControl,\n StateMessage: FormFieldStateMessage,\n SuccessMessage: FormFieldSuccessMessage,\n AlertMessage: FormFieldAlertMessage,\n ErrorMessage: FormFieldErrorMessage,\n HelperMessage: FormFieldHelperMessage,\n RequiredIndicator: FormFieldRequiredIndicator,\n CharactersCount: FormFieldCharactersCount,\n})\n\nFormField.displayName = 'FormField'\nFormFieldLabel.displayName = 'FormField.Label'\nFormFieldControl.displayName = 'FormField.Control'\nFormFieldStateMessage.displayName = 'FormField.StateMessage'\nFormFieldSuccessMessage.displayName = 'FormField.SuccessMessage'\nFormFieldAlertMessage.displayName = 'FormField.AlertMessage'\nFormFieldErrorMessage.displayName = 'FormField.ErrorMessage'\nFormFieldHelperMessage.displayName = 'FormField.HelperMessage'\nFormFieldRequiredIndicator.displayName = 'FormField.RequiredIndicator'\nFormFieldCharactersCount.displayName = 'FormField.CharactersCount'\n\nexport { type FormFieldProps } from './FormField'\nexport { type FormFieldStateMessageProps } from './FormFieldStateMessage'\nexport { type FormFieldControl, useFormFieldControl } from './FormFieldControl'\nexport { type FormFieldHelperMessageProps } from './FormFieldHelperMessage'\nexport { type FormFieldSuccessMessageProps } from './FormFieldSuccessMessage'\nexport { type FormFieldAlertMessageProps } from './FormFieldAlertMessage'\nexport { type FormFieldErrorMessageProps } from './FormFieldErrorMessage'\nexport { type FormFieldLabelProps } from './FormFieldLabel'\nexport { type FormFieldRequiredIndicatorProps } from './FormFieldRequiredIndicator'\nexport { type FormFieldCharactersCountProps } from './FormFieldCharactersCount'\n"],"names":["FormFieldContext","createContext","ID_PREFIX","useFormField","context","useContext","FormFieldProvider","id","name","disabled","readOnly","state","isRequired","children","labelId","useId","messageIds","setMessageIds","useState","description","handleMessageIdAdd","useCallback","msgId","ids","handleMessageIdRemove","current","value","useMemo","jsx","FormField","className","asChild","ref","others","Component","Slot","cx","FormFieldMessage","idProp","onMessageIdAdd","onMessageIdRemove","currentId","useEffect","FormFieldStateMessage","jsxs","Icon","WarningOutline","AlertOutline","Check","FormFieldAlertMessage","props","FormFieldCharactersCount","maxLength","liveAnnouncement","throttledValue","setThrottledValue","timeoutId","useFormFieldControl","isInvalid","FormFieldControl","Fragment","FormFieldErrorMessage","FormFieldHelperMessage","FormFieldLabel","htmlForProp","requiredIndicator","FormFieldRequiredIndicator","control","htmlFor","Label","Slottable","FormFieldSuccessMessage","Root"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/form-field/FormFieldContext.tsx","../../src/form-field/FormFieldProvider.tsx","../../src/form-field/FormField.tsx","../../src/form-field/FormFieldMessage.tsx","../../src/form-field/FormFieldStateMessage.tsx","../../src/form-field/FormFieldAlertMessage.tsx","../../src/form-field/FormFieldCharactersCount.tsx","../../src/form-field/FormFieldControl.tsx","../../src/form-field/FormFieldErrorMessage.tsx","../../src/form-field/FormFieldHelperMessage.tsx","../../src/form-field/FormFieldLabel.tsx","../../src/form-field/FormFieldSuccessMessage.tsx","../../src/form-field/index.ts"],"sourcesContent":["import { createContext, useContext } from 'react'\n\nexport interface FormFieldContextState {\n /**\n * Generated id for the input component.\n */\n id: string\n /**\n * Generated id for the label component.\n */\n labelId?: string\n /**\n * The name of the input. Submitted with its owning form as part of a name/value pair.\n */\n name?: string\n /**\n * A set of ids separated by a space used to describe the input component given by a set of messages.\n */\n description?: string\n /**\n * Disables the field and its associated input\n */\n disabled?: boolean\n /**\n * Marks the field and its associated input as read only\n */\n readOnly?: boolean\n /**\n * The validation state of the input.\n */\n state?: 'error' | 'success' | 'alert'\n /**\n * If true, the form field will be invalid.\n */\n isInvalid?: boolean\n /**\n * If true, the form field will be required.\n */\n isRequired?: boolean\n /**\n * Callback used to store a descriptive message.\n */\n onMessageIdAdd: (id: string) => void\n /**\n * Callback used to remove a descriptive message.\n */\n onMessageIdRemove: (id: string) => void\n}\n\nexport const FormFieldContext = createContext<FormFieldContextState | null>(null)\n\nexport const ID_PREFIX = ':form-field'\n\nexport const useFormField = () => {\n const context = useContext(FormFieldContext)\n\n if (!context) {\n throw Error('useFormField must be used within a FormField provider')\n }\n\n return context\n}\n","import { ReactNode, useCallback, useId, useMemo, useState } from 'react'\n\nimport { FormFieldContext, FormFieldContextState, ID_PREFIX } from './FormFieldContext'\n\nexport interface FormFieldProviderProps\n extends Pick<\n FormFieldContextState,\n 'id' | 'name' | 'disabled' | 'readOnly' | 'state' | 'isRequired'\n > {\n children: ReactNode\n}\n\nexport const FormFieldProvider = ({\n id,\n name,\n disabled = false,\n readOnly = false,\n state,\n isRequired,\n children,\n}: FormFieldProviderProps) => {\n const labelId = `${ID_PREFIX}-label-${useId()}`\n const [messageIds, setMessageIds] = useState<string[]>([])\n const description = messageIds.length > 0 ? messageIds.join(' ') : undefined\n\n const handleMessageIdAdd = useCallback((msgId: string) => {\n setMessageIds(ids => [...ids, msgId])\n }, [])\n\n const handleMessageIdRemove = useCallback((msgId: string) => {\n setMessageIds(ids => ids.filter(current => current !== msgId))\n }, [])\n\n const value = useMemo(() => {\n const isInvalid = state === 'error'\n\n return {\n id,\n labelId,\n name,\n disabled,\n readOnly,\n state,\n isRequired,\n isInvalid,\n description,\n onMessageIdAdd: handleMessageIdAdd,\n onMessageIdRemove: handleMessageIdRemove,\n }\n }, [\n id,\n labelId,\n name,\n disabled,\n readOnly,\n description,\n state,\n isRequired,\n handleMessageIdAdd,\n handleMessageIdRemove,\n ])\n\n return <FormFieldContext.Provider value={value}>{children}</FormFieldContext.Provider>\n}\n\nFormFieldProvider.displayName = 'FormFieldProvider'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref, useId } from 'react'\n\nimport { Slot } from '../slot'\nimport { FormFieldContextState, ID_PREFIX } from './FormFieldContext'\nimport { FormFieldProvider } from './FormFieldProvider'\n\nexport interface FormFieldProps\n extends ComponentPropsWithoutRef<'div'>,\n Pick<FormFieldContextState, 'name' | 'state' | 'isRequired'> {\n /**\n * Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.\n */\n asChild?: boolean\n /**\n * When `true`, prevents the user from interacting.\n */\n disabled?: boolean\n /**\n * Sets the component as interactive or not.\n */\n readOnly?: boolean\n ref?: Ref<HTMLDivElement>\n}\n\nexport const FormField = ({\n className,\n disabled = false,\n readOnly = false,\n name,\n state,\n isRequired = false,\n asChild = false,\n ref,\n ...others\n}: FormFieldProps) => {\n const id = `${ID_PREFIX}-${useId()}`\n const Component = asChild ? Slot : 'div'\n\n return (\n <FormFieldProvider\n id={id}\n name={name}\n isRequired={isRequired}\n disabled={disabled}\n readOnly={readOnly}\n state={state}\n >\n <Component\n ref={ref}\n data-spark-component=\"form-field\"\n className={cx(className, 'gap-md flex flex-col')}\n {...others}\n />\n </FormFieldProvider>\n )\n}\n\nFormField.displayName = 'FormField'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref, useEffect, useId } from 'react'\n\nimport { ID_PREFIX, useFormField } from './FormFieldContext'\n\nexport type FormFieldMessageProps = ComponentPropsWithoutRef<'span'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldMessage = ({\n id: idProp,\n className,\n ref,\n ...others\n}: FormFieldMessageProps) => {\n const { onMessageIdAdd, onMessageIdRemove } = useFormField()\n const currentId = `${ID_PREFIX}-message-${useId()}`\n const id = idProp || currentId\n\n useEffect(() => {\n onMessageIdAdd(id)\n\n return () => {\n onMessageIdRemove(id)\n }\n }, [id, onMessageIdAdd, onMessageIdRemove])\n\n return (\n <span\n ref={ref}\n id={id}\n data-spark-component=\"form-field-message\"\n className={cx(className, 'text-caption')}\n {...others}\n />\n )\n}\n\nFormFieldMessage.displayName = 'FormField.Message'\n","import { AlertOutline } from '@spark-ui/icons/AlertOutline'\nimport { Check } from '@spark-ui/icons/Check'\nimport { WarningOutline } from '@spark-ui/icons/WarningOutline'\nimport { cx } from 'class-variance-authority'\nimport { Ref } from 'react'\n\nimport { Icon } from '../icon'\nimport { useFormField } from './FormFieldContext'\nimport { FormFieldMessage, FormFieldMessageProps } from './FormFieldMessage'\n\nexport interface FormFieldStateMessageProps extends FormFieldMessageProps {\n state: 'error' | 'alert' | 'success'\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldStateMessage = ({\n className,\n state,\n children,\n ref,\n ...others\n}: FormFieldStateMessageProps) => {\n const field = useFormField()\n\n if (field.state !== state) {\n return null\n }\n\n return (\n <FormFieldMessage\n ref={ref}\n data-spark-component=\"form-field-state-message\"\n className={cx(\n 'gap-sm flex items-center',\n state === 'error' ? 'text-error' : 'text-on-surface/dim-1',\n className\n )}\n {...others}\n >\n {state === 'alert' && (\n <Icon size=\"sm\">\n <WarningOutline />\n </Icon>\n )}\n {state === 'error' && (\n <Icon size=\"sm\" intent=\"error\">\n <AlertOutline />\n </Icon>\n )}\n {state === 'success' && (\n <Icon size=\"sm\">\n <Check />\n </Icon>\n )}\n\n {children}\n </FormFieldMessage>\n )\n}\n\nFormFieldStateMessage.displayName = 'FormField.StateMessage'\n","import { Ref } from 'react'\n\nimport { FormFieldStateMessage, FormFieldStateMessageProps } from './FormFieldStateMessage'\n\nexport type FormFieldAlertMessageProps = Omit<FormFieldStateMessageProps, 'state'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldAlertMessage = ({ ref, ...props }: FormFieldAlertMessageProps) => {\n return (\n <FormFieldStateMessage\n ref={ref}\n data-spark-component=\"form-field-alert-message\"\n state=\"alert\"\n {...props}\n />\n )\n}\n\nFormFieldAlertMessage.displayName = 'FormField.AlertMessage'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref, useEffect, useState } from 'react'\n\nimport { FormFieldMessage } from './FormFieldMessage'\n\nexport type FormFieldCharactersCountProps = ComponentPropsWithoutRef<'span'> & {\n /**\n * This description is for the screen reader, read when the input is focused.\n */\n description?: string\n /**\n * The live announcement is for the screen read after a delay once the input value changes.\n */\n liveAnnouncement?: ({ remainingChars }: { remainingChars: number }) => string\n /**\n * Current value for the input this component belongs to.\n */\n value?: string\n /**\n * Maximum numeric value to be displayed.\n */\n maxLength: number\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldCharactersCount = ({\n className,\n value = '',\n maxLength,\n description,\n liveAnnouncement,\n ref,\n ...others\n}: FormFieldCharactersCountProps) => {\n const [throttledValue, setThrottledValue] = useState(value)\n\n /**\n * The value is throttled to avoid spamming the aria-live region (and consequently the screen reader).\n */\n useEffect(() => {\n const timeoutId = setTimeout(() => {\n setThrottledValue(value)\n }, 1000)\n\n return () => clearTimeout(timeoutId)\n }, [value])\n\n return (\n <span className=\"ml-auto self-start\">\n {description && (\n <FormFieldMessage className=\"default:sr-only\">{description}</FormFieldMessage>\n )}\n <span\n ref={ref}\n aria-hidden\n data-spark-component=\"form-field-characters-count\"\n className={cx(className, 'text-caption', 'text-neutral')}\n {...others}\n >\n {`${value.length}/${maxLength}`}\n </span>\n\n {liveAnnouncement && (\n <span className=\"sr-only\" aria-live=\"polite\">\n {liveAnnouncement({ remainingChars: maxLength - throttledValue.length })}\n </span>\n )}\n </span>\n )\n}\n\nFormFieldCharactersCount.displayName = 'FormField.CharactersCount'\n","import { ReactNode, useContext } from 'react'\n\nimport { FormFieldContext, FormFieldContextState } from './FormFieldContext'\n\ntype State = Partial<\n Pick<\n FormFieldContextState,\n | 'id'\n | 'name'\n | 'description'\n | 'labelId'\n | 'disabled'\n | 'readOnly'\n | 'state'\n | 'isInvalid'\n | 'isRequired'\n >\n>\n\nexport interface FormFieldControlProps {\n children: (state: State) => ReactNode\n}\n\nexport const useFormFieldControl = () => {\n const { id, name, description, disabled, readOnly, state, labelId, isInvalid, isRequired } =\n useContext(FormFieldContext) || {}\n\n return {\n id,\n name,\n description,\n disabled,\n readOnly,\n state,\n labelId,\n isInvalid,\n isRequired,\n } as State\n}\n\nexport const FormFieldControl = ({ children }: FormFieldControlProps) => {\n const props = useFormFieldControl()\n\n return <>{children(props)}</>\n}\n\nFormFieldControl.displayName = 'FormField.Control'\n","import { Ref } from 'react'\n\nimport { FormFieldStateMessage, FormFieldStateMessageProps } from './FormFieldStateMessage'\n\nexport type FormFieldErrorMessageProps = Omit<FormFieldStateMessageProps, 'state'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldErrorMessage = ({ ref, ...props }: FormFieldErrorMessageProps) => {\n return (\n <FormFieldStateMessage\n ref={ref}\n data-spark-component=\"form-field-error-message\"\n state=\"error\"\n {...props}\n />\n )\n}\n\nFormFieldErrorMessage.displayName = 'FormField.ErrorMessage'\n","import { cx } from 'class-variance-authority'\nimport { Ref } from 'react'\n\nimport { FormFieldMessage, FormFieldMessageProps } from './FormFieldMessage'\n\nexport type FormFieldHelperMessageProps = FormFieldMessageProps & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldHelperMessage = ({\n className,\n ref,\n ...others\n}: FormFieldHelperMessageProps) => {\n return (\n <FormFieldMessage\n ref={ref}\n data-spark-component=\"form-field-helper-message\"\n className={cx('text-on-surface/dim-1', className)}\n {...others}\n />\n )\n}\n\nFormFieldHelperMessage.displayName = 'FormField.HelperMessage'\n","import { cx } from 'class-variance-authority'\nimport { ReactNode, Ref } from 'react'\n\nimport { Label, LabelProps } from '../label'\nimport { Slottable } from '../slot'\nimport { useFormField } from './FormFieldContext'\nimport { FormFieldRequiredIndicator } from './FormFieldRequiredIndicator'\n\nexport interface FormFieldLabelProps extends LabelProps {\n /**\n * Element shown when the input is required inside the label.\n */\n requiredIndicator?: ReactNode\n ref?: Ref<HTMLLabelElement>\n}\n\nexport const FormFieldLabel = ({\n htmlFor: htmlForProp,\n className,\n children,\n requiredIndicator = <FormFieldRequiredIndicator />,\n asChild,\n ref,\n ...others\n}: FormFieldLabelProps) => {\n const control = useFormField()\n\n const { disabled, labelId, isRequired } = control\n const htmlFor = asChild ? undefined : htmlForProp || control.id\n\n return (\n <Label\n ref={ref}\n id={labelId}\n data-spark-component=\"form-field-label\"\n htmlFor={htmlFor}\n className={cx(className, disabled ? 'text-on-surface/dim-3 pointer-events-none' : undefined)}\n asChild={asChild}\n {...others}\n >\n <>\n <Slottable>{children}</Slottable>\n {isRequired && requiredIndicator}\n </>\n </Label>\n )\n}\n\nFormFieldLabel.displayName = 'FormField.Label'\n","import { Ref } from 'react'\n\nimport { FormFieldStateMessage, FormFieldStateMessageProps } from './FormFieldStateMessage'\n\nexport type FormFieldSuccessMessageProps = Omit<FormFieldStateMessageProps, 'state'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldSuccessMessage = ({ ref, ...props }: FormFieldSuccessMessageProps) => {\n return (\n <FormFieldStateMessage\n ref={ref}\n data-spark-component=\"form-field-success-message\"\n state=\"success\"\n {...props}\n />\n )\n}\n\nFormFieldSuccessMessage.displayName = 'FormField.SuccessMessage'\n","import { FormField as Root } from './FormField'\nimport { FormFieldAlertMessage } from './FormFieldAlertMessage'\nimport { FormFieldCharactersCount } from './FormFieldCharactersCount'\nimport { FormFieldControl } from './FormFieldControl'\nimport { FormFieldErrorMessage } from './FormFieldErrorMessage'\nimport { FormFieldHelperMessage } from './FormFieldHelperMessage'\nimport { FormFieldLabel } from './FormFieldLabel'\nimport { FormFieldRequiredIndicator } from './FormFieldRequiredIndicator'\nimport { FormFieldStateMessage } from './FormFieldStateMessage'\nimport { FormFieldSuccessMessage } from './FormFieldSuccessMessage'\n\nexport const FormField: typeof Root & {\n Label: typeof FormFieldLabel\n Control: typeof FormFieldControl\n StateMessage: typeof FormFieldStateMessage\n SuccessMessage: typeof FormFieldSuccessMessage\n AlertMessage: typeof FormFieldAlertMessage\n ErrorMessage: typeof FormFieldErrorMessage\n HelperMessage: typeof FormFieldHelperMessage\n RequiredIndicator: typeof FormFieldRequiredIndicator\n CharactersCount: typeof FormFieldCharactersCount\n} = Object.assign(Root, {\n Label: FormFieldLabel,\n Control: FormFieldControl,\n StateMessage: FormFieldStateMessage,\n SuccessMessage: FormFieldSuccessMessage,\n AlertMessage: FormFieldAlertMessage,\n ErrorMessage: FormFieldErrorMessage,\n HelperMessage: FormFieldHelperMessage,\n RequiredIndicator: FormFieldRequiredIndicator,\n CharactersCount: FormFieldCharactersCount,\n})\n\nFormField.displayName = 'FormField'\nFormFieldLabel.displayName = 'FormField.Label'\nFormFieldControl.displayName = 'FormField.Control'\nFormFieldStateMessage.displayName = 'FormField.StateMessage'\nFormFieldSuccessMessage.displayName = 'FormField.SuccessMessage'\nFormFieldAlertMessage.displayName = 'FormField.AlertMessage'\nFormFieldErrorMessage.displayName = 'FormField.ErrorMessage'\nFormFieldHelperMessage.displayName = 'FormField.HelperMessage'\nFormFieldRequiredIndicator.displayName = 'FormField.RequiredIndicator'\nFormFieldCharactersCount.displayName = 'FormField.CharactersCount'\n\nexport { type FormFieldProps } from './FormField'\nexport { type FormFieldStateMessageProps } from './FormFieldStateMessage'\nexport { type FormFieldControl, useFormFieldControl } from './FormFieldControl'\nexport { type FormFieldHelperMessageProps } from './FormFieldHelperMessage'\nexport { type FormFieldSuccessMessageProps } from './FormFieldSuccessMessage'\nexport { type FormFieldAlertMessageProps } from './FormFieldAlertMessage'\nexport { type FormFieldErrorMessageProps } from './FormFieldErrorMessage'\nexport { type FormFieldLabelProps } from './FormFieldLabel'\nexport { type FormFieldRequiredIndicatorProps } from './FormFieldRequiredIndicator'\nexport { type FormFieldCharactersCountProps } from './FormFieldCharactersCount'\n"],"names":["FormFieldContext","createContext","ID_PREFIX","useFormField","context","useContext","FormFieldProvider","id","name","disabled","readOnly","state","isRequired","children","labelId","useId","messageIds","setMessageIds","useState","description","handleMessageIdAdd","useCallback","msgId","ids","handleMessageIdRemove","current","value","useMemo","jsx","FormField","className","asChild","ref","others","Component","Slot","cx","FormFieldMessage","idProp","onMessageIdAdd","onMessageIdRemove","currentId","useEffect","FormFieldStateMessage","jsxs","Icon","WarningOutline","AlertOutline","Check","FormFieldAlertMessage","props","FormFieldCharactersCount","maxLength","liveAnnouncement","throttledValue","setThrottledValue","timeoutId","useFormFieldControl","isInvalid","FormFieldControl","Fragment","FormFieldErrorMessage","FormFieldHelperMessage","FormFieldLabel","htmlForProp","requiredIndicator","FormFieldRequiredIndicator","control","htmlFor","Label","Slottable","FormFieldSuccessMessage","Root"],"mappings":"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"}
@@ -79,7 +79,7 @@ const T = ({
79
79
  {
80
80
  ref: t,
81
81
  "data-spark-component": "form-field",
82
- className: c(s, "gap-sm flex flex-col"),
82
+ className: c(s, "gap-md flex flex-col"),
83
83
  ...n
84
84
  }
85
85
  )
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../src/form-field/FormFieldContext.tsx","../../src/form-field/FormFieldProvider.tsx","../../src/form-field/FormField.tsx","../../src/form-field/FormFieldMessage.tsx","../../src/form-field/FormFieldStateMessage.tsx","../../src/form-field/FormFieldAlertMessage.tsx","../../src/form-field/FormFieldCharactersCount.tsx","../../src/form-field/FormFieldControl.tsx","../../src/form-field/FormFieldErrorMessage.tsx","../../src/form-field/FormFieldHelperMessage.tsx","../../src/form-field/FormFieldLabel.tsx","../../src/form-field/FormFieldSuccessMessage.tsx","../../src/form-field/index.ts"],"sourcesContent":["import { createContext, useContext } from 'react'\n\nexport interface FormFieldContextState {\n /**\n * Generated id for the input component.\n */\n id: string\n /**\n * Generated id for the label component.\n */\n labelId?: string\n /**\n * The name of the input. Submitted with its owning form as part of a name/value pair.\n */\n name?: string\n /**\n * A set of ids separated by a space used to describe the input component given by a set of messages.\n */\n description?: string\n /**\n * Disables the field and its associated input\n */\n disabled?: boolean\n /**\n * Marks the field and its associated input as read only\n */\n readOnly?: boolean\n /**\n * The validation state of the input.\n */\n state?: 'error' | 'success' | 'alert'\n /**\n * If true, the form field will be invalid.\n */\n isInvalid?: boolean\n /**\n * If true, the form field will be required.\n */\n isRequired?: boolean\n /**\n * Callback used to store a descriptive message.\n */\n onMessageIdAdd: (id: string) => void\n /**\n * Callback used to remove a descriptive message.\n */\n onMessageIdRemove: (id: string) => void\n}\n\nexport const FormFieldContext = createContext<FormFieldContextState | null>(null)\n\nexport const ID_PREFIX = ':form-field'\n\nexport const useFormField = () => {\n const context = useContext(FormFieldContext)\n\n if (!context) {\n throw Error('useFormField must be used within a FormField provider')\n }\n\n return context\n}\n","import { ReactNode, useCallback, useId, useMemo, useState } from 'react'\n\nimport { FormFieldContext, FormFieldContextState, ID_PREFIX } from './FormFieldContext'\n\nexport interface FormFieldProviderProps\n extends Pick<\n FormFieldContextState,\n 'id' | 'name' | 'disabled' | 'readOnly' | 'state' | 'isRequired'\n > {\n children: ReactNode\n}\n\nexport const FormFieldProvider = ({\n id,\n name,\n disabled = false,\n readOnly = false,\n state,\n isRequired,\n children,\n}: FormFieldProviderProps) => {\n const labelId = `${ID_PREFIX}-label-${useId()}`\n const [messageIds, setMessageIds] = useState<string[]>([])\n const description = messageIds.length > 0 ? messageIds.join(' ') : undefined\n\n const handleMessageIdAdd = useCallback((msgId: string) => {\n setMessageIds(ids => [...ids, msgId])\n }, [])\n\n const handleMessageIdRemove = useCallback((msgId: string) => {\n setMessageIds(ids => ids.filter(current => current !== msgId))\n }, [])\n\n const value = useMemo(() => {\n const isInvalid = state === 'error'\n\n return {\n id,\n labelId,\n name,\n disabled,\n readOnly,\n state,\n isRequired,\n isInvalid,\n description,\n onMessageIdAdd: handleMessageIdAdd,\n onMessageIdRemove: handleMessageIdRemove,\n }\n }, [\n id,\n labelId,\n name,\n disabled,\n readOnly,\n description,\n state,\n isRequired,\n handleMessageIdAdd,\n handleMessageIdRemove,\n ])\n\n return <FormFieldContext.Provider value={value}>{children}</FormFieldContext.Provider>\n}\n\nFormFieldProvider.displayName = 'FormFieldProvider'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref, useId } from 'react'\n\nimport { Slot } from '../slot'\nimport { FormFieldContextState, ID_PREFIX } from './FormFieldContext'\nimport { FormFieldProvider } from './FormFieldProvider'\n\nexport interface FormFieldProps\n extends ComponentPropsWithoutRef<'div'>,\n Pick<FormFieldContextState, 'name' | 'state' | 'isRequired'> {\n /**\n * Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.\n */\n asChild?: boolean\n /**\n * When `true`, prevents the user from interacting.\n */\n disabled?: boolean\n /**\n * Sets the component as interactive or not.\n */\n readOnly?: boolean\n ref?: Ref<HTMLDivElement>\n}\n\nexport const FormField = ({\n className,\n disabled = false,\n readOnly = false,\n name,\n state,\n isRequired = false,\n asChild = false,\n ref,\n ...others\n}: FormFieldProps) => {\n const id = `${ID_PREFIX}-${useId()}`\n const Component = asChild ? Slot : 'div'\n\n return (\n <FormFieldProvider\n id={id}\n name={name}\n isRequired={isRequired}\n disabled={disabled}\n readOnly={readOnly}\n state={state}\n >\n <Component\n ref={ref}\n data-spark-component=\"form-field\"\n className={cx(className, 'gap-sm flex flex-col')}\n {...others}\n />\n </FormFieldProvider>\n )\n}\n\nFormField.displayName = 'FormField'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref, useEffect, useId } from 'react'\n\nimport { ID_PREFIX, useFormField } from './FormFieldContext'\n\nexport type FormFieldMessageProps = ComponentPropsWithoutRef<'span'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldMessage = ({\n id: idProp,\n className,\n ref,\n ...others\n}: FormFieldMessageProps) => {\n const { onMessageIdAdd, onMessageIdRemove } = useFormField()\n const currentId = `${ID_PREFIX}-message-${useId()}`\n const id = idProp || currentId\n\n useEffect(() => {\n onMessageIdAdd(id)\n\n return () => {\n onMessageIdRemove(id)\n }\n }, [id, onMessageIdAdd, onMessageIdRemove])\n\n return (\n <span\n ref={ref}\n id={id}\n data-spark-component=\"form-field-message\"\n className={cx(className, 'text-caption')}\n {...others}\n />\n )\n}\n\nFormFieldMessage.displayName = 'FormField.Message'\n","import { AlertOutline } from '@spark-ui/icons/AlertOutline'\nimport { Check } from '@spark-ui/icons/Check'\nimport { WarningOutline } from '@spark-ui/icons/WarningOutline'\nimport { cx } from 'class-variance-authority'\nimport { Ref } from 'react'\n\nimport { Icon } from '../icon'\nimport { useFormField } from './FormFieldContext'\nimport { FormFieldMessage, FormFieldMessageProps } from './FormFieldMessage'\n\nexport interface FormFieldStateMessageProps extends FormFieldMessageProps {\n state: 'error' | 'alert' | 'success'\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldStateMessage = ({\n className,\n state,\n children,\n ref,\n ...others\n}: FormFieldStateMessageProps) => {\n const field = useFormField()\n\n if (field.state !== state) {\n return null\n }\n\n return (\n <FormFieldMessage\n ref={ref}\n data-spark-component=\"form-field-state-message\"\n className={cx(\n 'gap-sm flex items-center',\n state === 'error' ? 'text-error' : 'text-on-surface/dim-1',\n className\n )}\n {...others}\n >\n {state === 'alert' && (\n <Icon size=\"sm\">\n <WarningOutline />\n </Icon>\n )}\n {state === 'error' && (\n <Icon size=\"sm\" intent=\"error\">\n <AlertOutline />\n </Icon>\n )}\n {state === 'success' && (\n <Icon size=\"sm\">\n <Check />\n </Icon>\n )}\n\n {children}\n </FormFieldMessage>\n )\n}\n\nFormFieldStateMessage.displayName = 'FormField.StateMessage'\n","import { Ref } from 'react'\n\nimport { FormFieldStateMessage, FormFieldStateMessageProps } from './FormFieldStateMessage'\n\nexport type FormFieldAlertMessageProps = Omit<FormFieldStateMessageProps, 'state'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldAlertMessage = ({ ref, ...props }: FormFieldAlertMessageProps) => {\n return (\n <FormFieldStateMessage\n ref={ref}\n data-spark-component=\"form-field-alert-message\"\n state=\"alert\"\n {...props}\n />\n )\n}\n\nFormFieldAlertMessage.displayName = 'FormField.AlertMessage'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref, useEffect, useState } from 'react'\n\nimport { FormFieldMessage } from './FormFieldMessage'\n\nexport type FormFieldCharactersCountProps = ComponentPropsWithoutRef<'span'> & {\n /**\n * This description is for the screen reader, read when the input is focused.\n */\n description?: string\n /**\n * The live announcement is for the screen read after a delay once the input value changes.\n */\n liveAnnouncement?: ({ remainingChars }: { remainingChars: number }) => string\n /**\n * Current value for the input this component belongs to.\n */\n value?: string\n /**\n * Maximum numeric value to be displayed.\n */\n maxLength: number\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldCharactersCount = ({\n className,\n value = '',\n maxLength,\n description,\n liveAnnouncement,\n ref,\n ...others\n}: FormFieldCharactersCountProps) => {\n const [throttledValue, setThrottledValue] = useState(value)\n\n /**\n * The value is throttled to avoid spamming the aria-live region (and consequently the screen reader).\n */\n useEffect(() => {\n const timeoutId = setTimeout(() => {\n setThrottledValue(value)\n }, 1000)\n\n return () => clearTimeout(timeoutId)\n }, [value])\n\n return (\n <span className=\"ml-auto self-start\">\n {description && (\n <FormFieldMessage className=\"default:sr-only\">{description}</FormFieldMessage>\n )}\n <span\n ref={ref}\n aria-hidden\n data-spark-component=\"form-field-characters-count\"\n className={cx(className, 'text-caption', 'text-neutral')}\n {...others}\n >\n {`${value.length}/${maxLength}`}\n </span>\n\n {liveAnnouncement && (\n <span className=\"sr-only\" aria-live=\"polite\">\n {liveAnnouncement({ remainingChars: maxLength - throttledValue.length })}\n </span>\n )}\n </span>\n )\n}\n\nFormFieldCharactersCount.displayName = 'FormField.CharactersCount'\n","import { ReactNode, useContext } from 'react'\n\nimport { FormFieldContext, FormFieldContextState } from './FormFieldContext'\n\ntype State = Partial<\n Pick<\n FormFieldContextState,\n | 'id'\n | 'name'\n | 'description'\n | 'labelId'\n | 'disabled'\n | 'readOnly'\n | 'state'\n | 'isInvalid'\n | 'isRequired'\n >\n>\n\nexport interface FormFieldControlProps {\n children: (state: State) => ReactNode\n}\n\nexport const useFormFieldControl = () => {\n const { id, name, description, disabled, readOnly, state, labelId, isInvalid, isRequired } =\n useContext(FormFieldContext) || {}\n\n return {\n id,\n name,\n description,\n disabled,\n readOnly,\n state,\n labelId,\n isInvalid,\n isRequired,\n } as State\n}\n\nexport const FormFieldControl = ({ children }: FormFieldControlProps) => {\n const props = useFormFieldControl()\n\n return <>{children(props)}</>\n}\n\nFormFieldControl.displayName = 'FormField.Control'\n","import { Ref } from 'react'\n\nimport { FormFieldStateMessage, FormFieldStateMessageProps } from './FormFieldStateMessage'\n\nexport type FormFieldErrorMessageProps = Omit<FormFieldStateMessageProps, 'state'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldErrorMessage = ({ ref, ...props }: FormFieldErrorMessageProps) => {\n return (\n <FormFieldStateMessage\n ref={ref}\n data-spark-component=\"form-field-error-message\"\n state=\"error\"\n {...props}\n />\n )\n}\n\nFormFieldErrorMessage.displayName = 'FormField.ErrorMessage'\n","import { cx } from 'class-variance-authority'\nimport { Ref } from 'react'\n\nimport { FormFieldMessage, FormFieldMessageProps } from './FormFieldMessage'\n\nexport type FormFieldHelperMessageProps = FormFieldMessageProps & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldHelperMessage = ({\n className,\n ref,\n ...others\n}: FormFieldHelperMessageProps) => {\n return (\n <FormFieldMessage\n ref={ref}\n data-spark-component=\"form-field-helper-message\"\n className={cx('text-on-surface/dim-1', className)}\n {...others}\n />\n )\n}\n\nFormFieldHelperMessage.displayName = 'FormField.HelperMessage'\n","import { cx } from 'class-variance-authority'\nimport { ReactNode, Ref } from 'react'\n\nimport { Label, LabelProps } from '../label'\nimport { Slottable } from '../slot'\nimport { useFormField } from './FormFieldContext'\nimport { FormFieldRequiredIndicator } from './FormFieldRequiredIndicator'\n\nexport interface FormFieldLabelProps extends LabelProps {\n /**\n * Element shown when the input is required inside the label.\n */\n requiredIndicator?: ReactNode\n ref?: Ref<HTMLLabelElement>\n}\n\nexport const FormFieldLabel = ({\n htmlFor: htmlForProp,\n className,\n children,\n requiredIndicator = <FormFieldRequiredIndicator />,\n asChild,\n ref,\n ...others\n}: FormFieldLabelProps) => {\n const control = useFormField()\n\n const { disabled, labelId, isRequired } = control\n const htmlFor = asChild ? undefined : htmlForProp || control.id\n\n return (\n <Label\n ref={ref}\n id={labelId}\n data-spark-component=\"form-field-label\"\n htmlFor={htmlFor}\n className={cx(className, disabled ? 'text-on-surface/dim-3 pointer-events-none' : undefined)}\n asChild={asChild}\n {...others}\n >\n <>\n <Slottable>{children}</Slottable>\n {isRequired && requiredIndicator}\n </>\n </Label>\n )\n}\n\nFormFieldLabel.displayName = 'FormField.Label'\n","import { Ref } from 'react'\n\nimport { FormFieldStateMessage, FormFieldStateMessageProps } from './FormFieldStateMessage'\n\nexport type FormFieldSuccessMessageProps = Omit<FormFieldStateMessageProps, 'state'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldSuccessMessage = ({ ref, ...props }: FormFieldSuccessMessageProps) => {\n return (\n <FormFieldStateMessage\n ref={ref}\n data-spark-component=\"form-field-success-message\"\n state=\"success\"\n {...props}\n />\n )\n}\n\nFormFieldSuccessMessage.displayName = 'FormField.SuccessMessage'\n","import { FormField as Root } from './FormField'\nimport { FormFieldAlertMessage } from './FormFieldAlertMessage'\nimport { FormFieldCharactersCount } from './FormFieldCharactersCount'\nimport { FormFieldControl } from './FormFieldControl'\nimport { FormFieldErrorMessage } from './FormFieldErrorMessage'\nimport { FormFieldHelperMessage } from './FormFieldHelperMessage'\nimport { FormFieldLabel } from './FormFieldLabel'\nimport { FormFieldRequiredIndicator } from './FormFieldRequiredIndicator'\nimport { FormFieldStateMessage } from './FormFieldStateMessage'\nimport { FormFieldSuccessMessage } from './FormFieldSuccessMessage'\n\nexport const FormField: typeof Root & {\n Label: typeof FormFieldLabel\n Control: typeof FormFieldControl\n StateMessage: typeof FormFieldStateMessage\n SuccessMessage: typeof FormFieldSuccessMessage\n AlertMessage: typeof FormFieldAlertMessage\n ErrorMessage: typeof FormFieldErrorMessage\n HelperMessage: typeof FormFieldHelperMessage\n RequiredIndicator: typeof FormFieldRequiredIndicator\n CharactersCount: typeof FormFieldCharactersCount\n} = Object.assign(Root, {\n Label: FormFieldLabel,\n Control: FormFieldControl,\n StateMessage: FormFieldStateMessage,\n SuccessMessage: FormFieldSuccessMessage,\n AlertMessage: FormFieldAlertMessage,\n ErrorMessage: FormFieldErrorMessage,\n HelperMessage: FormFieldHelperMessage,\n RequiredIndicator: FormFieldRequiredIndicator,\n CharactersCount: FormFieldCharactersCount,\n})\n\nFormField.displayName = 'FormField'\nFormFieldLabel.displayName = 'FormField.Label'\nFormFieldControl.displayName = 'FormField.Control'\nFormFieldStateMessage.displayName = 'FormField.StateMessage'\nFormFieldSuccessMessage.displayName = 'FormField.SuccessMessage'\nFormFieldAlertMessage.displayName = 'FormField.AlertMessage'\nFormFieldErrorMessage.displayName = 'FormField.ErrorMessage'\nFormFieldHelperMessage.displayName = 'FormField.HelperMessage'\nFormFieldRequiredIndicator.displayName = 'FormField.RequiredIndicator'\nFormFieldCharactersCount.displayName = 'FormField.CharactersCount'\n\nexport { type FormFieldProps } from './FormField'\nexport { type FormFieldStateMessageProps } from './FormFieldStateMessage'\nexport { type FormFieldControl, useFormFieldControl } from './FormFieldControl'\nexport { type FormFieldHelperMessageProps } from './FormFieldHelperMessage'\nexport { type FormFieldSuccessMessageProps } from './FormFieldSuccessMessage'\nexport { type FormFieldAlertMessageProps } from './FormFieldAlertMessage'\nexport { type FormFieldErrorMessageProps } from './FormFieldErrorMessage'\nexport { type FormFieldLabelProps } from './FormFieldLabel'\nexport { type FormFieldRequiredIndicatorProps } from './FormFieldRequiredIndicator'\nexport { type FormFieldCharactersCountProps } from './FormFieldCharactersCount'\n"],"names":["FormFieldContext","createContext","ID_PREFIX","useFormField","context","useContext","FormFieldProvider","id","name","disabled","readOnly","state","isRequired","children","labelId","useId","messageIds","setMessageIds","useState","description","handleMessageIdAdd","useCallback","msgId","ids","handleMessageIdRemove","current","value","useMemo","jsx","FormField","className","asChild","ref","others","Slot","cx","FormFieldMessage","idProp","onMessageIdAdd","onMessageIdRemove","currentId","useEffect","FormFieldStateMessage","jsxs","Icon","WarningOutline","AlertOutline","Check","FormFieldAlertMessage","props","FormFieldCharactersCount","maxLength","liveAnnouncement","throttledValue","setThrottledValue","timeoutId","useFormFieldControl","isInvalid","FormFieldControl","Fragment","FormFieldErrorMessage","FormFieldHelperMessage","FormFieldLabel","htmlForProp","requiredIndicator","FormFieldRequiredIndicator","control","htmlFor","Label","Slottable","FormFieldSuccessMessage","Root"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../../src/form-field/FormFieldContext.tsx","../../src/form-field/FormFieldProvider.tsx","../../src/form-field/FormField.tsx","../../src/form-field/FormFieldMessage.tsx","../../src/form-field/FormFieldStateMessage.tsx","../../src/form-field/FormFieldAlertMessage.tsx","../../src/form-field/FormFieldCharactersCount.tsx","../../src/form-field/FormFieldControl.tsx","../../src/form-field/FormFieldErrorMessage.tsx","../../src/form-field/FormFieldHelperMessage.tsx","../../src/form-field/FormFieldLabel.tsx","../../src/form-field/FormFieldSuccessMessage.tsx","../../src/form-field/index.ts"],"sourcesContent":["import { createContext, useContext } from 'react'\n\nexport interface FormFieldContextState {\n /**\n * Generated id for the input component.\n */\n id: string\n /**\n * Generated id for the label component.\n */\n labelId?: string\n /**\n * The name of the input. Submitted with its owning form as part of a name/value pair.\n */\n name?: string\n /**\n * A set of ids separated by a space used to describe the input component given by a set of messages.\n */\n description?: string\n /**\n * Disables the field and its associated input\n */\n disabled?: boolean\n /**\n * Marks the field and its associated input as read only\n */\n readOnly?: boolean\n /**\n * The validation state of the input.\n */\n state?: 'error' | 'success' | 'alert'\n /**\n * If true, the form field will be invalid.\n */\n isInvalid?: boolean\n /**\n * If true, the form field will be required.\n */\n isRequired?: boolean\n /**\n * Callback used to store a descriptive message.\n */\n onMessageIdAdd: (id: string) => void\n /**\n * Callback used to remove a descriptive message.\n */\n onMessageIdRemove: (id: string) => void\n}\n\nexport const FormFieldContext = createContext<FormFieldContextState | null>(null)\n\nexport const ID_PREFIX = ':form-field'\n\nexport const useFormField = () => {\n const context = useContext(FormFieldContext)\n\n if (!context) {\n throw Error('useFormField must be used within a FormField provider')\n }\n\n return context\n}\n","import { ReactNode, useCallback, useId, useMemo, useState } from 'react'\n\nimport { FormFieldContext, FormFieldContextState, ID_PREFIX } from './FormFieldContext'\n\nexport interface FormFieldProviderProps\n extends Pick<\n FormFieldContextState,\n 'id' | 'name' | 'disabled' | 'readOnly' | 'state' | 'isRequired'\n > {\n children: ReactNode\n}\n\nexport const FormFieldProvider = ({\n id,\n name,\n disabled = false,\n readOnly = false,\n state,\n isRequired,\n children,\n}: FormFieldProviderProps) => {\n const labelId = `${ID_PREFIX}-label-${useId()}`\n const [messageIds, setMessageIds] = useState<string[]>([])\n const description = messageIds.length > 0 ? messageIds.join(' ') : undefined\n\n const handleMessageIdAdd = useCallback((msgId: string) => {\n setMessageIds(ids => [...ids, msgId])\n }, [])\n\n const handleMessageIdRemove = useCallback((msgId: string) => {\n setMessageIds(ids => ids.filter(current => current !== msgId))\n }, [])\n\n const value = useMemo(() => {\n const isInvalid = state === 'error'\n\n return {\n id,\n labelId,\n name,\n disabled,\n readOnly,\n state,\n isRequired,\n isInvalid,\n description,\n onMessageIdAdd: handleMessageIdAdd,\n onMessageIdRemove: handleMessageIdRemove,\n }\n }, [\n id,\n labelId,\n name,\n disabled,\n readOnly,\n description,\n state,\n isRequired,\n handleMessageIdAdd,\n handleMessageIdRemove,\n ])\n\n return <FormFieldContext.Provider value={value}>{children}</FormFieldContext.Provider>\n}\n\nFormFieldProvider.displayName = 'FormFieldProvider'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref, useId } from 'react'\n\nimport { Slot } from '../slot'\nimport { FormFieldContextState, ID_PREFIX } from './FormFieldContext'\nimport { FormFieldProvider } from './FormFieldProvider'\n\nexport interface FormFieldProps\n extends ComponentPropsWithoutRef<'div'>,\n Pick<FormFieldContextState, 'name' | 'state' | 'isRequired'> {\n /**\n * Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.\n */\n asChild?: boolean\n /**\n * When `true`, prevents the user from interacting.\n */\n disabled?: boolean\n /**\n * Sets the component as interactive or not.\n */\n readOnly?: boolean\n ref?: Ref<HTMLDivElement>\n}\n\nexport const FormField = ({\n className,\n disabled = false,\n readOnly = false,\n name,\n state,\n isRequired = false,\n asChild = false,\n ref,\n ...others\n}: FormFieldProps) => {\n const id = `${ID_PREFIX}-${useId()}`\n const Component = asChild ? Slot : 'div'\n\n return (\n <FormFieldProvider\n id={id}\n name={name}\n isRequired={isRequired}\n disabled={disabled}\n readOnly={readOnly}\n state={state}\n >\n <Component\n ref={ref}\n data-spark-component=\"form-field\"\n className={cx(className, 'gap-md flex flex-col')}\n {...others}\n />\n </FormFieldProvider>\n )\n}\n\nFormField.displayName = 'FormField'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref, useEffect, useId } from 'react'\n\nimport { ID_PREFIX, useFormField } from './FormFieldContext'\n\nexport type FormFieldMessageProps = ComponentPropsWithoutRef<'span'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldMessage = ({\n id: idProp,\n className,\n ref,\n ...others\n}: FormFieldMessageProps) => {\n const { onMessageIdAdd, onMessageIdRemove } = useFormField()\n const currentId = `${ID_PREFIX}-message-${useId()}`\n const id = idProp || currentId\n\n useEffect(() => {\n onMessageIdAdd(id)\n\n return () => {\n onMessageIdRemove(id)\n }\n }, [id, onMessageIdAdd, onMessageIdRemove])\n\n return (\n <span\n ref={ref}\n id={id}\n data-spark-component=\"form-field-message\"\n className={cx(className, 'text-caption')}\n {...others}\n />\n )\n}\n\nFormFieldMessage.displayName = 'FormField.Message'\n","import { AlertOutline } from '@spark-ui/icons/AlertOutline'\nimport { Check } from '@spark-ui/icons/Check'\nimport { WarningOutline } from '@spark-ui/icons/WarningOutline'\nimport { cx } from 'class-variance-authority'\nimport { Ref } from 'react'\n\nimport { Icon } from '../icon'\nimport { useFormField } from './FormFieldContext'\nimport { FormFieldMessage, FormFieldMessageProps } from './FormFieldMessage'\n\nexport interface FormFieldStateMessageProps extends FormFieldMessageProps {\n state: 'error' | 'alert' | 'success'\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldStateMessage = ({\n className,\n state,\n children,\n ref,\n ...others\n}: FormFieldStateMessageProps) => {\n const field = useFormField()\n\n if (field.state !== state) {\n return null\n }\n\n return (\n <FormFieldMessage\n ref={ref}\n data-spark-component=\"form-field-state-message\"\n className={cx(\n 'gap-sm flex items-center',\n state === 'error' ? 'text-error' : 'text-on-surface/dim-1',\n className\n )}\n {...others}\n >\n {state === 'alert' && (\n <Icon size=\"sm\">\n <WarningOutline />\n </Icon>\n )}\n {state === 'error' && (\n <Icon size=\"sm\" intent=\"error\">\n <AlertOutline />\n </Icon>\n )}\n {state === 'success' && (\n <Icon size=\"sm\">\n <Check />\n </Icon>\n )}\n\n {children}\n </FormFieldMessage>\n )\n}\n\nFormFieldStateMessage.displayName = 'FormField.StateMessage'\n","import { Ref } from 'react'\n\nimport { FormFieldStateMessage, FormFieldStateMessageProps } from './FormFieldStateMessage'\n\nexport type FormFieldAlertMessageProps = Omit<FormFieldStateMessageProps, 'state'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldAlertMessage = ({ ref, ...props }: FormFieldAlertMessageProps) => {\n return (\n <FormFieldStateMessage\n ref={ref}\n data-spark-component=\"form-field-alert-message\"\n state=\"alert\"\n {...props}\n />\n )\n}\n\nFormFieldAlertMessage.displayName = 'FormField.AlertMessage'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref, useEffect, useState } from 'react'\n\nimport { FormFieldMessage } from './FormFieldMessage'\n\nexport type FormFieldCharactersCountProps = ComponentPropsWithoutRef<'span'> & {\n /**\n * This description is for the screen reader, read when the input is focused.\n */\n description?: string\n /**\n * The live announcement is for the screen read after a delay once the input value changes.\n */\n liveAnnouncement?: ({ remainingChars }: { remainingChars: number }) => string\n /**\n * Current value for the input this component belongs to.\n */\n value?: string\n /**\n * Maximum numeric value to be displayed.\n */\n maxLength: number\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldCharactersCount = ({\n className,\n value = '',\n maxLength,\n description,\n liveAnnouncement,\n ref,\n ...others\n}: FormFieldCharactersCountProps) => {\n const [throttledValue, setThrottledValue] = useState(value)\n\n /**\n * The value is throttled to avoid spamming the aria-live region (and consequently the screen reader).\n */\n useEffect(() => {\n const timeoutId = setTimeout(() => {\n setThrottledValue(value)\n }, 1000)\n\n return () => clearTimeout(timeoutId)\n }, [value])\n\n return (\n <span className=\"ml-auto self-start\">\n {description && (\n <FormFieldMessage className=\"default:sr-only\">{description}</FormFieldMessage>\n )}\n <span\n ref={ref}\n aria-hidden\n data-spark-component=\"form-field-characters-count\"\n className={cx(className, 'text-caption', 'text-neutral')}\n {...others}\n >\n {`${value.length}/${maxLength}`}\n </span>\n\n {liveAnnouncement && (\n <span className=\"sr-only\" aria-live=\"polite\">\n {liveAnnouncement({ remainingChars: maxLength - throttledValue.length })}\n </span>\n )}\n </span>\n )\n}\n\nFormFieldCharactersCount.displayName = 'FormField.CharactersCount'\n","import { ReactNode, useContext } from 'react'\n\nimport { FormFieldContext, FormFieldContextState } from './FormFieldContext'\n\ntype State = Partial<\n Pick<\n FormFieldContextState,\n | 'id'\n | 'name'\n | 'description'\n | 'labelId'\n | 'disabled'\n | 'readOnly'\n | 'state'\n | 'isInvalid'\n | 'isRequired'\n >\n>\n\nexport interface FormFieldControlProps {\n children: (state: State) => ReactNode\n}\n\nexport const useFormFieldControl = () => {\n const { id, name, description, disabled, readOnly, state, labelId, isInvalid, isRequired } =\n useContext(FormFieldContext) || {}\n\n return {\n id,\n name,\n description,\n disabled,\n readOnly,\n state,\n labelId,\n isInvalid,\n isRequired,\n } as State\n}\n\nexport const FormFieldControl = ({ children }: FormFieldControlProps) => {\n const props = useFormFieldControl()\n\n return <>{children(props)}</>\n}\n\nFormFieldControl.displayName = 'FormField.Control'\n","import { Ref } from 'react'\n\nimport { FormFieldStateMessage, FormFieldStateMessageProps } from './FormFieldStateMessage'\n\nexport type FormFieldErrorMessageProps = Omit<FormFieldStateMessageProps, 'state'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldErrorMessage = ({ ref, ...props }: FormFieldErrorMessageProps) => {\n return (\n <FormFieldStateMessage\n ref={ref}\n data-spark-component=\"form-field-error-message\"\n state=\"error\"\n {...props}\n />\n )\n}\n\nFormFieldErrorMessage.displayName = 'FormField.ErrorMessage'\n","import { cx } from 'class-variance-authority'\nimport { Ref } from 'react'\n\nimport { FormFieldMessage, FormFieldMessageProps } from './FormFieldMessage'\n\nexport type FormFieldHelperMessageProps = FormFieldMessageProps & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldHelperMessage = ({\n className,\n ref,\n ...others\n}: FormFieldHelperMessageProps) => {\n return (\n <FormFieldMessage\n ref={ref}\n data-spark-component=\"form-field-helper-message\"\n className={cx('text-on-surface/dim-1', className)}\n {...others}\n />\n )\n}\n\nFormFieldHelperMessage.displayName = 'FormField.HelperMessage'\n","import { cx } from 'class-variance-authority'\nimport { ReactNode, Ref } from 'react'\n\nimport { Label, LabelProps } from '../label'\nimport { Slottable } from '../slot'\nimport { useFormField } from './FormFieldContext'\nimport { FormFieldRequiredIndicator } from './FormFieldRequiredIndicator'\n\nexport interface FormFieldLabelProps extends LabelProps {\n /**\n * Element shown when the input is required inside the label.\n */\n requiredIndicator?: ReactNode\n ref?: Ref<HTMLLabelElement>\n}\n\nexport const FormFieldLabel = ({\n htmlFor: htmlForProp,\n className,\n children,\n requiredIndicator = <FormFieldRequiredIndicator />,\n asChild,\n ref,\n ...others\n}: FormFieldLabelProps) => {\n const control = useFormField()\n\n const { disabled, labelId, isRequired } = control\n const htmlFor = asChild ? undefined : htmlForProp || control.id\n\n return (\n <Label\n ref={ref}\n id={labelId}\n data-spark-component=\"form-field-label\"\n htmlFor={htmlFor}\n className={cx(className, disabled ? 'text-on-surface/dim-3 pointer-events-none' : undefined)}\n asChild={asChild}\n {...others}\n >\n <>\n <Slottable>{children}</Slottable>\n {isRequired && requiredIndicator}\n </>\n </Label>\n )\n}\n\nFormFieldLabel.displayName = 'FormField.Label'\n","import { Ref } from 'react'\n\nimport { FormFieldStateMessage, FormFieldStateMessageProps } from './FormFieldStateMessage'\n\nexport type FormFieldSuccessMessageProps = Omit<FormFieldStateMessageProps, 'state'> & {\n ref?: Ref<HTMLSpanElement>\n}\n\nexport const FormFieldSuccessMessage = ({ ref, ...props }: FormFieldSuccessMessageProps) => {\n return (\n <FormFieldStateMessage\n ref={ref}\n data-spark-component=\"form-field-success-message\"\n state=\"success\"\n {...props}\n />\n )\n}\n\nFormFieldSuccessMessage.displayName = 'FormField.SuccessMessage'\n","import { FormField as Root } from './FormField'\nimport { FormFieldAlertMessage } from './FormFieldAlertMessage'\nimport { FormFieldCharactersCount } from './FormFieldCharactersCount'\nimport { FormFieldControl } from './FormFieldControl'\nimport { FormFieldErrorMessage } from './FormFieldErrorMessage'\nimport { FormFieldHelperMessage } from './FormFieldHelperMessage'\nimport { FormFieldLabel } from './FormFieldLabel'\nimport { FormFieldRequiredIndicator } from './FormFieldRequiredIndicator'\nimport { FormFieldStateMessage } from './FormFieldStateMessage'\nimport { FormFieldSuccessMessage } from './FormFieldSuccessMessage'\n\nexport const FormField: typeof Root & {\n Label: typeof FormFieldLabel\n Control: typeof FormFieldControl\n StateMessage: typeof FormFieldStateMessage\n SuccessMessage: typeof FormFieldSuccessMessage\n AlertMessage: typeof FormFieldAlertMessage\n ErrorMessage: typeof FormFieldErrorMessage\n HelperMessage: typeof FormFieldHelperMessage\n RequiredIndicator: typeof FormFieldRequiredIndicator\n CharactersCount: typeof FormFieldCharactersCount\n} = Object.assign(Root, {\n Label: FormFieldLabel,\n Control: FormFieldControl,\n StateMessage: FormFieldStateMessage,\n SuccessMessage: FormFieldSuccessMessage,\n AlertMessage: FormFieldAlertMessage,\n ErrorMessage: FormFieldErrorMessage,\n HelperMessage: FormFieldHelperMessage,\n RequiredIndicator: FormFieldRequiredIndicator,\n CharactersCount: FormFieldCharactersCount,\n})\n\nFormField.displayName = 'FormField'\nFormFieldLabel.displayName = 'FormField.Label'\nFormFieldControl.displayName = 'FormField.Control'\nFormFieldStateMessage.displayName = 'FormField.StateMessage'\nFormFieldSuccessMessage.displayName = 'FormField.SuccessMessage'\nFormFieldAlertMessage.displayName = 'FormField.AlertMessage'\nFormFieldErrorMessage.displayName = 'FormField.ErrorMessage'\nFormFieldHelperMessage.displayName = 'FormField.HelperMessage'\nFormFieldRequiredIndicator.displayName = 'FormField.RequiredIndicator'\nFormFieldCharactersCount.displayName = 'FormField.CharactersCount'\n\nexport { type FormFieldProps } from './FormField'\nexport { type FormFieldStateMessageProps } from './FormFieldStateMessage'\nexport { type FormFieldControl, useFormFieldControl } from './FormFieldControl'\nexport { type FormFieldHelperMessageProps } from './FormFieldHelperMessage'\nexport { type FormFieldSuccessMessageProps } from './FormFieldSuccessMessage'\nexport { type FormFieldAlertMessageProps } from './FormFieldAlertMessage'\nexport { type FormFieldErrorMessageProps } from './FormFieldErrorMessage'\nexport { type FormFieldLabelProps } from './FormFieldLabel'\nexport { type FormFieldRequiredIndicatorProps } from './FormFieldRequiredIndicator'\nexport { type FormFieldCharactersCountProps } from './FormFieldCharactersCount'\n"],"names":["FormFieldContext","createContext","ID_PREFIX","useFormField","context","useContext","FormFieldProvider","id","name","disabled","readOnly","state","isRequired","children","labelId","useId","messageIds","setMessageIds","useState","description","handleMessageIdAdd","useCallback","msgId","ids","handleMessageIdRemove","current","value","useMemo","jsx","FormField","className","asChild","ref","others","Slot","cx","FormFieldMessage","idProp","onMessageIdAdd","onMessageIdRemove","currentId","useEffect","FormFieldStateMessage","jsxs","Icon","WarningOutline","AlertOutline","Check","FormFieldAlertMessage","props","FormFieldCharactersCount","maxLength","liveAnnouncement","throttledValue","setThrottledValue","timeoutId","useFormFieldControl","isInvalid","FormFieldControl","Fragment","FormFieldErrorMessage","FormFieldHelperMessage","FormFieldLabel","htmlForProp","requiredIndicator","FormFieldRequiredIndicator","control","htmlFor","Label","Slottable","FormFieldSuccessMessage","Root"],"mappings":";;;;;;;;;;AAiDO,MAAMA,IAAmBC,EAA4C,IAAI,GAEnEC,IAAY,eAEZC,IAAe,MAAM;AAChC,QAAMC,IAAUC,EAAWL,CAAgB;AAE3C,MAAI,CAACI;AACH,UAAM,MAAM,uDAAuD;AAGrE,SAAOA;AACT,GCjDaE,IAAoB,CAAC;AAAA,EAChC,IAAAC;AAAA,EACA,MAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,UAAAC,IAAW;AAAA,EACX,OAAAC;AAAA,EACA,YAAAC;AAAA,EACA,UAAAC;AACF,MAA8B;AAC5B,QAAMC,IAAU,GAAGZ,CAAS,UAAUa,GAAO,IACvC,CAACC,GAAYC,CAAa,IAAIC,EAAmB,CAAA,CAAE,GACnDC,IAAcH,EAAW,SAAS,IAAIA,EAAW,KAAK,GAAG,IAAI,QAE7DI,IAAqBC,EAAY,CAACC,MAAkB;AACxD,IAAAL,EAAc,CAAAM,MAAO,CAAC,GAAGA,GAAKD,CAAK,CAAC;AAAA,EACtC,GAAG,CAAA,CAAE,GAECE,IAAwBH,EAAY,CAACC,MAAkB;AAC3D,IAAAL,EAAc,OAAOM,EAAI,OAAO,CAAAE,MAAWA,MAAYH,CAAK,CAAC;AAAA,EAC/D,GAAG,CAAA,CAAE,GAECI,IAAQC,EAAQ,OAGb;AAAA,IACL,IAAApB;AAAA,IACA,SAAAO;AAAA,IACA,MAAAN;AAAA,IACA,UAAAC;AAAA,IACA,UAAAC;AAAA,IACA,OAAAC;AAAA,IACA,YAAAC;AAAA,IACA,WAVgBD,MAAU;AAAA,IAW1B,aAAAQ;AAAA,IACA,gBAAgBC;AAAA,IAChB,mBAAmBI;AAAA,EAAA,IAEpB;AAAA,IACDjB;AAAA,IACAO;AAAA,IACAN;AAAA,IACAC;AAAA,IACAC;AAAA,IACAS;AAAA,IACAR;AAAA,IACAC;AAAA,IACAQ;AAAA,IACAI;AAAA,EAAA,CACD;AAED,SAAO,gBAAAI,EAAC5B,EAAiB,UAAjB,EAA0B,OAAA0B,GAAe,UAAAb,EAAA,CAAS;AAC5D;AAEAP,EAAkB,cAAc;ACxCzB,MAAMuB,IAAY,CAAC;AAAA,EACxB,WAAAC;AAAA,EACA,UAAArB,IAAW;AAAA,EACX,UAAAC,IAAW;AAAA,EACX,MAAAF;AAAA,EACA,OAAAG;AAAA,EACA,YAAAC,IAAa;AAAA,EACb,SAAAmB,IAAU;AAAA,EACV,KAAAC;AAAA,EACA,GAAGC;AACL,MAAsB;AACpB,QAAM1B,IAAK,GAAGL,CAAS,IAAIa,GAAO;AAGlC,SACE,gBAAAa;AAAA,IAACtB;AAAA,IAAA;AAAA,MACC,IAAAC;AAAA,MACA,MAAAC;AAAA,MACA,YAAAI;AAAA,MACA,UAAAH;AAAA,MACA,UAAAC;AAAA,MACA,OAAAC;AAAA,MAEA,UAAA,gBAAAiB;AAAA,QAXcG,IAAUG,IAAO;AAAA,QAW9B;AAAA,UACC,KAAAF;AAAA,UACA,wBAAqB;AAAA,UACrB,WAAWG,EAAGL,GAAW,sBAAsB;AAAA,UAC9C,GAAGG;AAAA,QAAA;AAAA,MAAA;AAAA,IACN;AAAA,EAAA;AAGN;AAEAJ,EAAU,cAAc;ACjDjB,MAAMO,IAAmB,CAAC;AAAA,EAC/B,IAAIC;AAAA,EACJ,WAAAP;AAAA,EACA,KAAAE;AAAA,EACA,GAAGC;AACL,MAA6B;AAC3B,QAAM,EAAE,gBAAAK,GAAgB,mBAAAC,EAAA,IAAsBpC,EAAA,GACxCqC,IAAY,GAAGtC,CAAS,YAAYa,GAAO,IAC3CR,IAAK8B,KAAUG;AAErB,SAAAC,EAAU,OACRH,EAAe/B,CAAE,GAEV,MAAM;AACX,IAAAgC,EAAkBhC,CAAE;AAAA,EACtB,IACC,CAACA,GAAI+B,GAAgBC,CAAiB,CAAC,GAGxC,gBAAAX;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAI;AAAA,MACA,IAAAzB;AAAA,MACA,wBAAqB;AAAA,MACrB,WAAW4B,EAAGL,GAAW,cAAc;AAAA,MACtC,GAAGG;AAAA,IAAA;AAAA,EAAA;AAGV;AAEAG,EAAiB,cAAc;ACvBxB,MAAMM,IAAwB,CAAC;AAAA,EACpC,WAAAZ;AAAA,EACA,OAAAnB;AAAA,EACA,UAAAE;AAAA,EACA,KAAAmB;AAAA,EACA,GAAGC;AACL,MACgB9B,EAAA,EAEJ,UAAUQ,IACX,OAIP,gBAAAgC;AAAA,EAACP;AAAA,EAAA;AAAA,IACC,KAAAJ;AAAA,IACA,wBAAqB;AAAA,IACrB,WAAWG;AAAA,MACT;AAAA,MACAxB,MAAU,UAAU,eAAe;AAAA,MACnCmB;AAAA,IAAA;AAAA,IAED,GAAGG;AAAA,IAEH,UAAA;AAAA,MAAAtB,MAAU,WACT,gBAAAiB,EAACgB,GAAA,EAAK,MAAK,MACT,UAAA,gBAAAhB,EAACiB,KAAe,EAAA,CAClB;AAAA,MAEDlC,MAAU,WACT,gBAAAiB,EAACgB,GAAA,EAAK,MAAK,MAAK,QAAO,SACrB,UAAA,gBAAAhB,EAACkB,GAAA,CAAA,CAAa,EAAA,CAChB;AAAA,MAEDnC,MAAU,aACT,gBAAAiB,EAACgB,GAAA,EAAK,MAAK,MACT,UAAA,gBAAAhB,EAACmB,KAAM,EAAA,CACT;AAAA,MAGDlC;AAAA,IAAA;AAAA,EAAA;AAAA;AAKP6B,EAAsB,cAAc;ACpD7B,MAAMM,IAAwB,CAAC,EAAE,KAAAhB,GAAK,GAAGiB,QAE5C,gBAAArB;AAAA,EAACc;AAAA,EAAA;AAAA,IACC,KAAAV;AAAA,IACA,wBAAqB;AAAA,IACrB,OAAM;AAAA,IACL,GAAGiB;AAAA,EAAA;AAAA;AAKVD,EAAsB,cAAc;ACM7B,MAAME,IAA2B,CAAC;AAAA,EACvC,WAAApB;AAAA,EACA,OAAAJ,IAAQ;AAAA,EACR,WAAAyB;AAAA,EACA,aAAAhC;AAAA,EACA,kBAAAiC;AAAA,EACA,KAAApB;AAAA,EACA,GAAGC;AACL,MAAqC;AACnC,QAAM,CAACoB,GAAgBC,CAAiB,IAAIpC,EAASQ,CAAK;AAK1D,SAAAe,EAAU,MAAM;AACd,UAAMc,IAAY,WAAW,MAAM;AACjC,MAAAD,EAAkB5B,CAAK;AAAA,IACzB,GAAG,GAAI;AAEP,WAAO,MAAM,aAAa6B,CAAS;AAAA,EACrC,GAAG,CAAC7B,CAAK,CAAC,GAGR,gBAAAiB,EAAC,QAAA,EAAK,WAAU,sBACb,UAAA;AAAA,IAAAxB,KACC,gBAAAS,EAACQ,GAAA,EAAiB,WAAU,mBAAmB,UAAAjB,GAAY;AAAA,IAE7D,gBAAAS;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAI;AAAA,QACA,eAAW;AAAA,QACX,wBAAqB;AAAA,QACrB,WAAWG,EAAGL,GAAW,gBAAgB,cAAc;AAAA,QACtD,GAAGG;AAAA,QAEH,UAAA,GAAGP,EAAM,MAAM,IAAIyB,CAAS;AAAA,MAAA;AAAA,IAAA;AAAA,IAG9BC,KACC,gBAAAxB,EAAC,QAAA,EAAK,WAAU,WAAU,aAAU,UACjC,UAAAwB,EAAiB,EAAE,gBAAgBD,IAAYE,EAAe,OAAA,CAAQ,EAAA,CACzE;AAAA,EAAA,GAEJ;AAEJ;AAEAH,EAAyB,cAAc;AChDhC,MAAMM,IAAsB,MAAM;AACvC,QAAM,EAAE,IAAAjD,GAAI,MAAAC,GAAM,aAAAW,GAAa,UAAAV,GAAU,UAAAC,GAAU,OAAAC,GAAO,SAAAG,GAAS,WAAA2C,GAAW,YAAA7C,EAAA,IAC5EP,EAAWL,CAAgB,KAAK,CAAA;AAElC,SAAO;AAAA,IACL,IAAAO;AAAA,IACA,MAAAC;AAAA,IACA,aAAAW;AAAA,IACA,UAAAV;AAAA,IACA,UAAAC;AAAA,IACA,OAAAC;AAAA,IACA,SAAAG;AAAA,IACA,WAAA2C;AAAA,IACA,YAAA7C;AAAA,EAAA;AAEJ,GAEa8C,IAAmB,CAAC,EAAE,UAAA7C,QAAsC;AACvE,QAAMoC,IAAQO,EAAA;AAEd,SAAO,gBAAA5B,EAAA+B,GAAA,EAAG,UAAA9C,EAASoC,CAAK,GAAE;AAC5B;AAEAS,EAAiB,cAAc;ACtCxB,MAAME,IAAwB,CAAC,EAAE,KAAA5B,GAAK,GAAGiB,QAE5C,gBAAArB;AAAA,EAACc;AAAA,EAAA;AAAA,IACC,KAAAV;AAAA,IACA,wBAAqB;AAAA,IACrB,OAAM;AAAA,IACL,GAAGiB;AAAA,EAAA;AAAA;AAKVW,EAAsB,cAAc;ACV7B,MAAMC,IAAyB,CAAC;AAAA,EACrC,WAAA/B;AAAA,EACA,KAAAE;AAAA,EACA,GAAGC;AACL,MAEI,gBAAAL;AAAA,EAACQ;AAAA,EAAA;AAAA,IACC,KAAAJ;AAAA,IACA,wBAAqB;AAAA,IACrB,WAAWG,EAAG,yBAAyBL,CAAS;AAAA,IAC/C,GAAGG;AAAA,EAAA;AAAA;AAKV4B,EAAuB,cAAc;ACR9B,MAAMC,IAAiB,CAAC;AAAA,EAC7B,SAASC;AAAA,EACT,WAAAjC;AAAA,EACA,UAAAjB;AAAA,EACA,mBAAAmD,sBAAqBC,GAAA,EAA2B;AAAA,EAChD,SAAAlC;AAAA,EACA,KAAAC;AAAA,EACA,GAAGC;AACL,MAA2B;AACzB,QAAMiC,IAAU/D,EAAA,GAEV,EAAE,UAAAM,GAAU,SAAAK,GAAS,YAAAF,EAAA,IAAesD,GACpCC,IAAUpC,IAAU,SAAYgC,KAAeG,EAAQ;AAE7D,SACE,gBAAAtC;AAAA,IAACwC;AAAA,IAAA;AAAA,MACC,KAAApC;AAAA,MACA,IAAIlB;AAAA,MACJ,wBAAqB;AAAA,MACrB,SAAAqD;AAAA,MACA,WAAWhC,EAAGL,GAAWrB,IAAW,8CAA8C,MAAS;AAAA,MAC3F,SAAAsB;AAAA,MACC,GAAGE;AAAA,MAEJ,UAAA,gBAAAU,EAAAgB,GAAA,EACE,UAAA;AAAA,QAAA,gBAAA/B,EAACyC,KAAW,UAAAxD,GAAS;AAAA,QACpBD,KAAcoD;AAAA,MAAA,EAAA,CACjB;AAAA,IAAA;AAAA,EAAA;AAGN;AAEAF,EAAe,cAAc;ACxCtB,MAAMQ,IAA0B,CAAC,EAAE,KAAAtC,GAAK,GAAGiB,QAE9C,gBAAArB;AAAA,EAACc;AAAA,EAAA;AAAA,IACC,KAAAV;AAAA,IACA,wBAAqB;AAAA,IACrB,OAAM;AAAA,IACL,GAAGiB;AAAA,EAAA;AAAA;AAKVqB,EAAwB,cAAc;ACR/B,MAAMzC,IAUT,OAAO,OAAO0C,GAAM;AAAA,EACtB,OAAOT;AAAA,EACP,SAASJ;AAAA,EACT,cAAchB;AAAA,EACd,gBAAgB4B;AAAA,EAChB,cAActB;AAAA,EACd,cAAcY;AAAA,EACd,eAAeC;AAAA,EACf,mBAAmBI;AAAA,EACnB,iBAAiBf;AACnB,CAAC;AAEDrB,EAAU,cAAc;AACxBiC,EAAe,cAAc;AAC7BJ,EAAiB,cAAc;AAC/BhB,EAAsB,cAAc;AACpC4B,EAAwB,cAAc;AACtCtB,EAAsB,cAAc;AACpCY,EAAsB,cAAc;AACpCC,EAAuB,cAAc;AACrCI,EAA2B,cAAc;AACzCf,EAAyB,cAAc;"}
@@ -32,6 +32,11 @@ export interface InputOTPProps extends Omit<ComponentPropsWithoutRef<'div'>, 'on
32
32
  * @default false
33
33
  */
34
34
  disabled?: boolean;
35
+ /**
36
+ * Whether the input is read-only (value visible but not editable)
37
+ * @default false
38
+ */
39
+ readOnly?: boolean;
35
40
  /**
36
41
  * Whether to auto-focus the input
37
42
  * @default false
@@ -80,6 +85,6 @@ export interface InputOTPProps extends Omit<ComponentPropsWithoutRef<'div'>, 'on
80
85
  ref?: Ref<HTMLDivElement>;
81
86
  }
82
87
  export declare const InputOTP: {
83
- ({ maxLength: maxLengthProp, type, value: controlledValue, defaultValue, onValueChange, isValid, disabled: disabledProp, autoFocus, autoComplete, forceUppercase, filterKeys, pattern, inputMode, placeholder, name: nameProp, className, children, ...others }: InputOTPProps): import("react/jsx-runtime").JSX.Element;
88
+ ({ maxLength: maxLengthProp, type, value: controlledValue, defaultValue, onValueChange, isValid, disabled: disabledProp, readOnly: readOnlyProp, autoFocus, autoComplete, forceUppercase, filterKeys, pattern, inputMode, placeholder, name: nameProp, className, children, ...others }: InputOTPProps): import("react/jsx-runtime").JSX.Element;
84
89
  displayName: string;
85
90
  };
@@ -9,6 +9,7 @@ export interface InputOTPContextValue {
9
9
  activeIndex: number;
10
10
  intent: 'neutral' | 'success' | 'alert' | 'error';
11
11
  disabled: boolean;
12
+ readOnly: boolean;
12
13
  placeholder?: string;
13
14
  type: 'text' | 'number' | 'password' | 'tel';
14
15
  }
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("react/jsx-runtime"),H=require("class-variance-authority"),a=require("react"),oe=require("@spark-ui/components/form-field"),ce=require("../Icon-CF0W0LKr.js"),le=require("@spark-ui/icons/Minus"),L=a.createContext(null),ue=()=>{const e=a.useContext(L);if(!e)throw new Error("InputOTP components must be used within InputOTP");return e};H.cva(["relative","inline-flex","items-center","gap-sm"]);const X=H.cva(["relative","border-sm first:rounded-l-lg last:rounded-r-lg","size-sz-44","text-center text-body-1","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"],{variants:{intent:{neutral:["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"}}),de=X,j=({index:e,className:i,...t})=>{const c=ue(),s=e??0,u=c.slots[s];if(!u)return null;const{char:b,isActive:x,hasFakeCaret:y}=u,I=!b&&!y&&c.placeholder;return f.jsxs("div",{className:X({intent:c.intent,className:i}),"data-active":x,"data-disabled":c.disabled,"data-valid":c.intent!=="error",...t,children:[f.jsx("span",{className:I?"text-on-surface/dim-3":"",children:c.type==="password"&&b?"•":b||(!y&&c.placeholder?c.placeholder:"")}),y&&f.jsx("span",{className:"pointer-events-none absolute inset-0 flex items-center justify-center","aria-hidden":"true",children:f.jsx("span",{className:"bg-on-surface animate-standalone-caret-blink h-sz-24 w-px"})})]})};j.displayName="InputOTP.Slot";const pe="Backspace",fe="ArrowLeft",be="ArrowUp",me="ArrowRight",ve="ArrowDown",xe="e",Ie=({maxLength:e,type:i,value:t,defaultValue:c,onValueChange:s,isValid:u,disabledProp:b,autoFocus:x,forceUppercase:y,filterKeys:T,pattern:I,placeholder:C,nameProp:V})=>{const G=a.useId(),r=a.useRef(null),z=a.useRef(null),l=oe.useFormFieldControl(),O=l.id??G,D=V??l.name,h=l.disabled??b,_=l.isInvalid??!u,B=l.isRequired??!1,W=l.labelId,k=l.description,S=l.state,w=["success","alert","error"].includes(S??"")?S:_?"error":"neutral",P=t!==void 0?t:c,M=y?P.toUpperCase():P,[U,R]=a.useState(M),[E,F]=a.useState(!1),d=t!==void 0?t:U,m=Math.min(d.length,e-1);a.useEffect(()=>{r.current&&r.current.setSelectionRange(m,m)},[m,d.length,e]);const q=a.useMemo(()=>Array.from({length:e},(o,n)=>({char:d[n]||"",isActive:n===m&&E,hasFakeCaret:n===m&&!d[n]&&!h&&E})),[e,d,m,E,h]);a.useEffect(()=>{r.current&&t!==void 0&&(r.current.value=t)},[t]),a.useEffect(()=>{x&&r.current&&r.current.focus()},[x]);const N=o=>{let n=o;if(y&&(n=n.toUpperCase()),i==="number"&&(n=n.replace(/[^\d]/g,"")),I)try{let v=I;I.startsWith("^")||(v=`^${I}$`);const p=new RegExp(v);n=n.split("").filter(g=>p.test(g)).join("")}catch(v){console.error("Invalid pattern provided to InputOTP:",I,v)}return n};return{uuid:O,inputRef:r,containerRef:z,name:D,disabled:h,isInvalid:_,isRequired:B,description:k,maxLength:e,intent:w,currentValue:d,activeIndex:m,slots:q,contextValue:{value:d,maxLength:e,slots:q,activeIndex:m,intent:w,disabled:h,placeholder:C,type:i},handleChange:o=>{if(h)return;const n=o.target.value,p=N(n).slice(0,e);s&&s(p),t===void 0&&R(p);const g=Math.min(p.length,e-1);r.current&&r.current.setSelectionRange(g,g)},handleKeyDown:o=>{if(!h){if(T.length>0&&T.includes(o.key)){o.preventDefault();return}switch(o.key){case pe:o.preventDefault();const n=d.length;if(n>0){const v=d.slice(0,n-1);s&&s(v),t===void 0&&R(v);const p=Math.max(0,v.length);r.current&&r.current.setSelectionRange(p,p)}break;case fe:case me:o.preventDefault();break;case be:case ve:o.preventDefault();break;case xe:case"E":i==="number"&&o.preventDefault();break}}},handlePaste:o=>{if(h)return;o.preventDefault();const n=o.clipboardData.getData("text");if(!n)return;const p=N(n).slice(0,e);s&&s(p),t===void 0&&R(p);const g=Math.min(p.length,e-1);r.current&&r.current.setSelectionRange(g,g)},handleFocus:()=>{if(F(!0),r.current){const o=Math.min(d.length,e-1);r.current.setSelectionRange(o,o)}},handleBlur:()=>{F(!1)},handleClick:()=>{r.current&&r.current.focus()},labelId:W}},ee=e=>{let i=0;return a.Children.forEach(e,t=>{if(a.isValidElement(t)){const c=t.props;t.type===j||t.type?.displayName==="InputOTP.Slot"?i++:c.children&&(i+=ee(c.children))}}),i},te=(e,i=0)=>{let t=i;return[a.Children.map(e,s=>{if(a.isValidElement(s)){const u=s.props;if(s.type===j||s.type?.displayName==="InputOTP.Slot"){const b=typeof u.index=="number"?u.index:t++;return a.cloneElement(s,{...u,index:b})}else if(u.children){const[b,x]=te(u.children,t);return t=x,a.cloneElement(s,{...s.props,children:b})}}return s}),t]},ne=({maxLength:e,type:i="text",value:t,defaultValue:c="",onValueChange:s,isValid:u=!0,disabled:b=!1,autoFocus:x=!1,autoComplete:y="off",forceUppercase:T=!1,filterKeys:I=["-","."],pattern:C,inputMode:V,placeholder:G="",name:r,className:z,children:l,...O})=>{const D=a.useMemo(()=>{if(e!==void 0)return e;const A=ee(l);return A>0?A:4},[e,l]),h=a.useMemo(()=>{const[A]=te(l);return A},[l]),{uuid:_,inputRef:B,containerRef:W,name:k,disabled:S,isInvalid:Y,isRequired:w,description:P,currentValue:M,contextValue:U,handleChange:R,handleKeyDown:E,handlePaste:F,handleFocus:d,handleBlur:m,handleClick:q,labelId:N}=Ie({maxLength:D,type:i,value:t,defaultValue:c,onValueChange:s,isValid:u,disabledProp:b,autoFocus:x,forceUppercase:T,filterKeys:I,pattern:C,placeholder:G,nameProp:r}),$="aria-label"in O?O["aria-label"]:void 0,{"aria-label":re,...Z}=O,K=N?{"aria-labelledby":N}:$?{"aria-label":$}:{};return f.jsx(L.Provider,{value:U,children:f.jsxs("div",{ref:W,"data-spark-component":"input-otp",role:"group",...K,...P?{"aria-describedby":P}:{},className:H.cx("gap-md relative inline-flex items-center",S?"cursor-not-allowed":"cursor-text",z),onClick:q,...Z,children:[k&&f.jsx("input",{type:"hidden",name:k,value:M,required:w,"aria-required":w,"aria-invalid":Y,...K}),f.jsx("input",{ref:B,id:_,type:i==="password"?"password":"text",value:M,maxLength:D,autoFocus:x,autoComplete:y,disabled:S,pattern:C,inputMode:V,...K,...P?{"aria-describedby":P}:{},"aria-invalid":Y,onChange:R,onKeyDown:E,onPaste:F,onFocus:d,onBlur:m,className:"bg-success z-raised absolute inset-0 m-0 p-0 opacity-0 disabled:cursor-not-allowed",tabIndex:0}),h]})})};ne.displayName="InputOTP";const J=({children:e,className:i,...t})=>f.jsx("div",{className:`inline-flex [&>*:not(:first-child)]:-ml-px ${i||""}`,...t,children:e});J.displayName="InputOTP.Group";const Q=({className:e,...i})=>f.jsx("div",{className:`text-on-surface flex items-center justify-center ${e||""}`,...i,children:f.jsx(ce.Icon,{size:"md",children:f.jsx(le.Minus,{})})});Q.displayName="InputOTP.Separator";const se=Object.assign(ne,{Group:J,Slot:j,Separator:Q});se.displayName="InputOTP";J.displayName="InputOTP.Group";j.displayName="InputOTP.Slot";Q.displayName="InputOTP.Separator";exports.InputOTP=se;exports.inputOTPSlotStyles=X;exports.inputOTPStyles=de;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=require("react/jsx-runtime"),L=require("class-variance-authority"),o=require("react"),ue=require("@spark-ui/components/form-field"),ne=o.createContext(null),de=()=>{const e=o.useContext(ne);if(!e)throw new Error("InputOTP components must be used within InputOTP");return e};L.cva(["relative","inline-flex","items-center","gap-sm"]);const Q=L.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"}}),pe=Q,D=({index:e,className:i,...t})=>{const c=de(),r=e??0,p=c.slots[r];if(!p)return null;const{char:f,isActive:O,hasFakeCaret:y}=p,P=!f,w=P&&!y&&c.placeholder,h=r===c.activeIndex;return b.jsxs("div",{className:Q({intent:c.intent,className:i}),"data-active":O,"data-disabled":c.disabled,"data-readonly":c.readOnly,"data-filled":!P,"data-focus-target":h,"data-valid":c.intent!=="error",...t,children:[b.jsx("span",{className:w?"text-on-surface/dim-3":"",children:c.type==="password"&&f?"•":f||(!y&&c.placeholder?c.placeholder:"")}),y&&b.jsx("span",{className:"pointer-events-none absolute inset-0 flex items-center justify-center","aria-hidden":"true",children:b.jsx("span",{className:"bg-on-surface animate-standalone-caret-blink h-sz-24 w-sz-2"})})]})};D.displayName="InputOTP.Slot";const fe="Backspace",be="ArrowLeft",ve="ArrowUp",me="ArrowRight",xe="ArrowDown",ye="e",he=({maxLength:e,type:i,value:t,defaultValue:c,onValueChange:r,isValid:p,disabledProp:f,readOnlyProp:O,autoFocus:y,forceUppercase:P,filterKeys:w,pattern:h,placeholder:j,nameProp:B})=>{const W=o.useId(),s=o.useRef(null),Y=o.useRef(null),l=ue.useFormFieldControl(),S=l.id??W,k=B??l.name,v=l.disabled??f,I=l.readOnly??O,_=l.isInvalid??!p,U=l.isRequired??!1,F=l.labelId,K=l.description,R=l.state,E=["success","alert","error"].includes(R??"")?R:_?"error":"neutral",T=t!==void 0?t:c,M=P?T.toUpperCase():T,[H,N]=o.useState(M),[A,q]=o.useState(!1),u=t!==void 0?t:H,m=Math.min(u.length,e-1);o.useEffect(()=>{s.current&&s.current.setSelectionRange(m,m)},[m,u.length,e]);const V=o.useMemo(()=>Array.from({length:e},(n,a)=>({char:u[a]||"",isActive:a===m&&A,hasFakeCaret:a===m&&!u[a]&&!v&&!I&&A})),[e,u,m,A,v,I]);o.useEffect(()=>{s.current&&t!==void 0&&(s.current.value=t)},[t]),o.useEffect(()=>{y&&s.current&&s.current.focus()},[y]);const z=n=>{let a=n;if(P&&(a=a.toUpperCase()),i==="number"&&(a=a.replace(/[^\d]/g,"")),h)try{let g=h;h.startsWith("^")||(g=`^${h}$`);const d=new RegExp(g);a=a.split("").filter(x=>d.test(x)).join("")}catch(g){console.error("Invalid pattern provided to InputOTP:",h,g)}return a};return{uuid:S,inputRef:s,containerRef:Y,name:k,disabled:v,readOnly:I,isInvalid:_,isRequired:U,description:K,maxLength:e,intent:E,currentValue:u,activeIndex:m,slots:V,contextValue:{value:u,maxLength:e,slots:V,activeIndex:m,intent:E,disabled:v,readOnly:I,placeholder:j,type:i},handleChange:n=>{if(v||I)return;const a=n.target.value,d=z(a).slice(0,e);r&&r(d),t===void 0&&N(d);const x=Math.min(d.length,e-1);s.current&&s.current.setSelectionRange(x,x)},handleKeyDown:n=>{if(v||I)return;const a=(n.ctrlKey||n.metaKey)&&["a","c","v","x"].includes(n.key.toLowerCase());if(w.length>0&&w.includes(n.key)&&!a){n.preventDefault();return}switch(n.key){case fe:n.preventDefault();const g=u.length;if(g>0){const d=u.slice(0,g-1);r&&r(d),t===void 0&&N(d);const x=Math.max(0,d.length);s.current&&s.current.setSelectionRange(x,x)}break;case be:case me:n.preventDefault();break;case ve:case xe:n.preventDefault();break;case ye:case"E":i==="number"&&n.preventDefault();break}},handleCopy:n=>{v||(n.preventDefault(),u.length>0&&n.clipboardData.setData("text/plain",u))},handlePaste:n=>{if(v||I)return;n.preventDefault();const a=n.clipboardData.getData("text");if(!a)return;const d=z(a).slice(0,e);r&&r(d),t===void 0&&N(d);const x=Math.min(d.length,e-1);s.current&&s.current.setSelectionRange(x,x)},handleFocus:()=>{if(q(!0),s.current){const n=Math.min(u.length,e-1);s.current.setSelectionRange(n,n)}},handleBlur:()=>{q(!1)},handleClick:()=>{s.current&&s.current.focus()},labelId:F}},re=e=>{let i=0;return o.Children.forEach(e,t=>{if(o.isValidElement(t)){const c=t.props;t.type===D||t.type?.displayName==="InputOTP.Slot"?i++:c.children&&(i+=re(c.children))}}),i},se=(e,i=0)=>{let t=i;return[o.Children.map(e,r=>{if(o.isValidElement(r)){const p=r.props;if(r.type===D||r.type?.displayName==="InputOTP.Slot"){const f=typeof p.index=="number"?p.index:t++;return o.cloneElement(r,{...p,index:f})}else if(p.children){const[f,O]=se(p.children,t);return t=O,o.cloneElement(r,{...r.props,children:f})}}return r}),t]},ae=({maxLength:e,type:i="text",value:t,defaultValue:c="",onValueChange:r,isValid:p=!0,disabled:f=!1,readOnly:O=!1,autoFocus:y=!1,autoComplete:P="off",forceUppercase:w=!1,filterKeys:h=["-","."],pattern:j,inputMode:B,placeholder:W="-",name:s,className:Y,children:l,...S})=>{const k=o.useMemo(()=>{if(e!==void 0)return e;const C=re(l);return C>0?C:4},[e,l]),v=o.useMemo(()=>{const[C]=se(l);return C},[l]),{uuid:I,inputRef:_,containerRef:U,name:F,disabled:K,readOnly:R,isInvalid:$,isRequired:E,description:T,currentValue:M,contextValue:H,handleChange:N,handleKeyDown:A,handleCopy:q,handlePaste:u,handleFocus:m,handleBlur:V,handleClick:z,labelId:X}=he({maxLength:k,type:i,value:t,defaultValue:c,onValueChange:r,isValid:p,disabledProp:f,readOnlyProp:O,autoFocus:y,forceUppercase:w,filterKeys:h,pattern:j,placeholder:W,nameProp:s}),J="aria-label"in S?S["aria-label"]:void 0,{"aria-label":ie,...te}=S,G=X?{"aria-labelledby":X}:J?{"aria-label":J}:{};return b.jsx(ne.Provider,{value:H,children:b.jsxs("div",{ref:U,"data-spark-component":"input-otp",role:"group",...G,...T?{"aria-describedby":T}:{},className:L.cx("group gap-md relative inline-flex w-fit items-center default:cursor-text",{"cursor-not-allowed":K,"cursor-default":R},Y),onClick:z,...te,children:[F&&b.jsx("input",{type:"hidden",name:F,value:M,required:E,"aria-required":E,"aria-invalid":$,...G}),b.jsx("input",{ref:_,id:I,type:i==="password"?"password":"text",value:M,maxLength:k,autoFocus:y,autoComplete:P,disabled:K,readOnly:R,pattern:j,inputMode:B,...G,...T?{"aria-describedby":T}:{},"aria-invalid":$,onChange:N,onKeyDown:A,onCopy:q,onPaste:u,onFocus:m,onBlur:V,className:"bg-success z-raised absolute inset-0 m-0 p-0 opacity-0 read-only:cursor-default disabled:cursor-not-allowed",tabIndex:0}),v]})})};ae.displayName="InputOTP";const Z=({children:e,className:i,...t})=>b.jsx("div",{className:`gap-md flex ${i}`,...t,children:e});Z.displayName="InputOTP.Group";const ee=({className:e,...i})=>b.jsx("div",{className:`text-on-surface/dim-3 flex items-center justify-center ${e||""}`,...i,children:b.jsx("div",{className:"h-sz-4 w-sz-8 bg-outline rounded-full"})});ee.displayName="InputOTP.Separator";const oe=Object.assign(ae,{Group:Z,Slot:D,Separator:ee});oe.displayName="InputOTP";Z.displayName="InputOTP.Group";D.displayName="InputOTP.Slot";ee.displayName="InputOTP.Separator";exports.InputOTP=oe;exports.inputOTPSlotStyles=Q;exports.inputOTPStyles=pe;
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","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 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',\n 'border-sm first:rounded-l-lg last:rounded-r-lg',\n 'size-sz-44',\n 'text-center text-body-1',\n 'text-on-surface',\n 'outline-hidden',\n 'transition-colors',\n 'flex items-center justify-center',\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\n 'data-[active=true]:border-focus',\n // 'data-[active=true]:ring-focus',\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 ],\n {\n variants: {\n /**\n * Color scheme of the slot\n */\n intent: {\n neutral: ['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\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 return (\n <div\n className={inputOTPSlotStyles({\n intent: context.intent,\n className,\n })}\n data-active={isActive}\n data-disabled={context.disabled}\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-px\" />\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 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 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 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 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 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 && isFocused,\n })),\n [maxLength, currentValue, activeIndex, isFocused, disabled]\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) 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) return\n\n // Filter keys\n if (filterKeys.length > 0 && filterKeys.includes(e.key)) {\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 handlePaste: ClipboardEventHandler<HTMLInputElement> = e => {\n if (disabled) 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 placeholder,\n type,\n }\n\n const returnValue: UseInputOTPReturn = {\n uuid: id,\n inputRef,\n containerRef,\n name,\n disabled,\n isInvalid,\n isRequired,\n description,\n maxLength,\n intent,\n currentValue,\n activeIndex,\n slots,\n contextValue,\n handleChange,\n handleKeyDown,\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\n extends Omit<ComponentPropsWithoutRef<'div'>, 'onChange' | 'inputMode'> {\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 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 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 isInvalid,\n isRequired,\n description,\n currentValue,\n contextValue,\n handleChange,\n handleKeyDown,\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 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 'gap-md relative inline-flex items-center',\n disabled ? 'cursor-not-allowed' : 'cursor-text',\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 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 onPaste={handlePaste}\n onFocus={handleFocus}\n onBlur={handleBlur}\n className=\"bg-success z-raised absolute inset-0 m-0 p-0 opacity-0 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\nexport const InputOTPGroup = ({ children, className, ...props }: InputOTPGroupProps) => {\n return (\n <div className={`inline-flex [&>*:not(:first-child)]:-ml-px ${className || ''}`} {...props}>\n {children}\n </div>\n )\n}\n\nInputOTPGroup.displayName = 'InputOTP.Group'\n","import { Icon } from '@spark-ui/components/icon'\nimport { Minus } from '@spark-ui/icons/Minus'\nimport { ComponentPropsWithoutRef } from 'react'\n\nexport interface InputOTPSeparatorProps extends ComponentPropsWithoutRef<'div'> {}\n\nexport const InputOTPSeparator = ({ className, ...props }: InputOTPSeparatorProps) => {\n return (\n <div\n className={`text-on-surface flex items-center justify-center ${className || ''}`}\n {...props}\n >\n <Icon size=\"md\">\n <Minus />\n </Icon>\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\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"],"names":["InputOTPContext","createContext","useInputOTPContext","context","useContext","cva","inputOTPSlotStyles","inputOTPStyles","InputOTPSlot","indexProp","className","props","index","slot","char","isActive","hasFakeCaret","isPlaceholder","jsxs","jsx","BACKSPACE_KEY","LEFT_ARROW_KEY","UP_ARROW_KEY","RIGHT_ARROW_KEY","DOWN_ARROW_KEY","E_KEY","useInputOTP","maxLength","type","controlledValue","defaultValue","onValueChange","isValid","disabledProp","autoFocus","forceUppercase","filterKeys","pattern","placeholder","nameProp","uuid","useId","inputRef","useRef","containerRef","field","useFormFieldControl","id","name","disabled","isInvalid","isRequired","labelId","description","fieldState","intent","initialValue","processedValue","internalValue","setInternalValue","useState","isFocused","setIsFocused","currentValue","activeIndex","useEffect","slots","useMemo","_","i","processInputValue","inputValue","processed","regexPattern","regex","currChar","error","e","newValue","newActiveIndex","currentLength","pastedText","cursorPosition","countSlots","children","count","Children","child","isValidElement","assignSlotIndexes","startIndex","currentIndex","slotIndex","cloneElement","processedChildren","nextIndex","InputOTP","maxLengthProp","autoComplete","inputMode","others","detectedLength","contextValue","handleChange","handleKeyDown","handlePaste","handleFocus","handleBlur","handleClick","ariaLabel","restOthers","accessibleNameProps","cx","InputOTPGroup","InputOTPSeparator","Icon","Minus","Root"],"mappings":"kSAiBaA,EAAkBC,EAAAA,cAA2C,IAAI,EAEjEC,GAAqB,IAAM,CACtC,MAAMC,EAAUC,EAAAA,WAAWJ,CAAe,EAC1C,GAAI,CAACG,EACH,MAAM,IAAI,MAAM,kDAAkD,EAGpE,OAAOA,CACT,ECxBuCE,EAAAA,IAAI,CAAC,WAAY,cAAe,eAAgB,QAAQ,CAAC,EAEzF,MAAMC,EAAqBD,EAAAA,IAChC,CAEE,WACA,iDACA,aACA,0BACA,kBACA,iBACA,oBACA,mCAEA,4BACA,gCACA,8BAEA,kCAGA,yCAEA,0CACA,sCACA,2CACA,4CAAA,EAEF,CACE,SAAU,CAIR,OAAQ,CACN,QAAS,CAAC,2BAA2B,EACrC,QAAS,CAAC,+DAA+D,EACzE,MAAO,CAAC,yDAAyD,EACjE,MAAO,CAAC,yDAAyD,CAAA,CACnE,EAEF,gBAAiB,CACf,OAAQ,SAAA,CACV,CAEJ,EAKaE,GAAiBD,ECtCjBE,EAAe,CAAC,CAAE,MAAOC,EAAW,UAAAC,EAAW,GAAGC,KAA+B,CAC5F,MAAMR,EAAUD,GAAA,EAGVU,EAAQH,GAAa,EACrBI,EAAOV,EAAQ,MAAMS,CAAK,EAEhC,GAAI,CAACC,EACH,OAAO,KAGT,KAAM,CAAE,KAAAC,EAAM,SAAAC,EAAU,aAAAC,CAAA,EAAiBH,EAEnCI,EADU,CAACH,GACgB,CAACE,GAAgBb,EAAQ,YAE1D,OACEe,EAAAA,KAAC,MAAA,CACC,UAAWZ,EAAmB,CAC5B,OAAQH,EAAQ,OAChB,UAAAO,CAAA,CACD,EACD,cAAaK,EACb,gBAAeZ,EAAQ,SACvB,aAAYA,EAAQ,SAAW,QAC9B,GAAGQ,EAEJ,SAAA,CAAAQ,MAAC,QAAK,UAAWF,EAAgB,wBAA0B,GACxD,WAAQ,OAAS,YAAcH,EAC5B,IACAA,IAAS,CAACE,GAAgBb,EAAQ,YAAcA,EAAQ,YAAc,IAC5E,EACCa,GACCG,EAAAA,IAAC,OAAA,CACC,UAAU,wEACV,cAAY,OAEZ,SAAAA,EAAAA,IAAC,OAAA,CAAK,UAAU,2DAAA,CAA4D,CAAA,CAAA,CAC9E,CAAA,CAAA,CAIR,EAEAX,EAAa,YAAc,gBCzC3B,MAAMY,GAAgB,YAChBC,GAAiB,YACjBC,GAAe,UACfC,GAAkB,aAClBC,GAAiB,YACjBC,GAAQ,IA8CDC,GAAc,CAAC,CAC1B,UAAAC,EACA,KAAAC,EACA,MAAOC,EACP,aAAAC,EACA,cAAAC,EACA,QAAAC,EACA,aAAAC,EACA,UAAAC,EACA,eAAAC,EACA,WAAAC,EACA,QAAAC,EACA,YAAAC,EACA,SAAAC,CACF,IAA2C,CACzC,MAAMC,EAAOC,EAAAA,MAAA,EACPC,EAAWC,EAAAA,OAAyB,IAAI,EACxCC,EAAeD,EAAAA,OAAuB,IAAI,EAG1CE,EAAQC,GAAAA,oBAAA,EAIRC,EAAKF,EAAM,IAAML,EACjBQ,EAAOT,GAAYM,EAAM,KACzBI,EAAWJ,EAAM,UAAYZ,EAC7BiB,EAAYL,EAAM,WAAa,CAACb,EAChCmB,EAAaN,EAAM,YAAc,GACjCO,EAAUP,EAAM,QAChBQ,EAAcR,EAAM,YACpBS,EAAaT,EAAM,MAiBnBU,EAZA,CAAC,UAAW,QAAS,OAAO,EAAE,SAASD,GAAc,EAAE,EAClDA,EAILJ,EACK,QAGF,UAMHM,EAAe3B,IAAoB,OAAYA,EAAkBC,EACjE2B,EAAiBtB,EAAiBqB,EAAa,YAAA,EAAgBA,EAE/D,CAACE,EAAeC,CAAgB,EAAIC,EAAAA,SAAiBH,CAAc,EACnE,CAACI,EAAWC,CAAY,EAAIF,EAAAA,SAAkB,EAAK,EAGnDG,EAAelC,IAAoB,OAAYA,EAAkB6B,EAGjEM,EAAc,KAAK,IAAID,EAAa,OAAQpC,EAAY,CAAC,EAG/DsC,EAAAA,UAAU,IAAM,CACVvB,EAAS,SACXA,EAAS,QAAQ,kBAAkBsB,EAAaA,CAAW,CAE/D,EAAG,CAACA,EAAaD,EAAa,OAAQpC,CAAS,CAAC,EAGhD,MAAMuC,EAAQC,EAAAA,QACZ,IACE,MAAM,KAAK,CAAE,OAAQxC,GAAa,CAACyC,EAAGC,KAAO,CAC3C,KAAMN,EAAaM,CAAC,GAAK,GACzB,SAAUA,IAAML,GAAeH,EAC/B,aAAcQ,IAAML,GAAe,CAACD,EAAaM,CAAC,GAAK,CAACpB,GAAYY,CAAA,EACpE,EACJ,CAAClC,EAAWoC,EAAcC,EAAaH,EAAWZ,CAAQ,CAAA,EAI5DgB,EAAAA,UAAU,IAAM,CACVvB,EAAS,SAAWb,IAAoB,SAC1Ca,EAAS,QAAQ,MAAQb,EAE7B,EAAG,CAACA,CAAe,CAAC,EAGpBoC,EAAAA,UAAU,IAAM,CACV/B,GAAaQ,EAAS,SACxBA,EAAS,QAAQ,MAAA,CAErB,EAAG,CAACR,CAAS,CAAC,EAEd,MAAMoC,EAAqBC,GAA+B,CACxD,IAAIC,EAAYD,EAWhB,GATIpC,IACFqC,EAAYA,EAAU,YAAA,GAGpB5C,IAAS,WACX4C,EAAYA,EAAU,QAAQ,SAAU,EAAE,GAIxCnC,EACF,GAAI,CAMF,IAAIoC,EAAepC,EAEdA,EAAQ,WAAW,GAAG,IACzBoC,EAAe,IAAIpC,CAAO,KAE5B,MAAMqC,EAAQ,IAAI,OAAOD,CAAY,EACrCD,EAAYA,EACT,MAAM,EAAE,EACR,OAAOG,GAECD,EAAM,KAAKC,CAAQ,CAC3B,EACA,KAAK,EAAE,CACZ,OAASC,EAAO,CAEd,QAAQ,MAAM,wCAAyCvC,EAASuC,CAAK,CACvE,CAGF,OAAOJ,CACT,EA6KA,MAxBuC,CACrC,KAAMzB,EACN,SAAAL,EACA,aAAAE,EACA,KAAAI,EACA,SAAAC,EACA,UAAAC,EACA,WAAAC,EACA,YAAAE,EACA,UAAA1B,EACA,OAAA4B,EACA,aAAAQ,EACA,YAAAC,EACA,MAAAE,EACA,aAzByC,CACzC,MAAOH,EACP,UAAApC,EACA,MAAAuC,EACA,YAAAF,EACA,OAAAT,EACA,SAAAN,EACA,YAAAX,EACA,KAAAV,CAAA,EAkBA,aAlKyDiD,GAAK,CAC9D,GAAI5B,EAAU,OAEd,MAAMsB,EAAaM,EAAE,OAAO,MAItBC,EAHiBR,EAAkBC,CAAU,EAGnB,MAAM,EAAG5C,CAAS,EAG9CI,GACFA,EAAc+C,CAAQ,EAIpBjD,IAAoB,QACtB8B,EAAiBmB,CAAQ,EAK3B,MAAMC,EAAiB,KAAK,IAAID,EAAS,OAAQnD,EAAY,CAAC,EAC1De,EAAS,SACXA,EAAS,QAAQ,kBAAkBqC,EAAgBA,CAAc,CAErE,EA0IE,cAxI4DF,GAAK,CACjE,GAAI,CAAA5B,EAGJ,IAAIb,EAAW,OAAS,GAAKA,EAAW,SAASyC,EAAE,GAAG,EAAG,CACvDA,EAAE,eAAA,EAEF,MACF,CAEA,OAAQA,EAAE,IAAA,CACR,KAAKzD,GACHyD,EAAE,eAAA,EACF,MAAMG,EAAgBjB,EAAa,OACnC,GAAIiB,EAAgB,EAAG,CACrB,MAAMF,EAAWf,EAAa,MAAM,EAAGiB,EAAgB,CAAC,EAGpDjD,GACFA,EAAc+C,CAAQ,EAIpBjD,IAAoB,QACtB8B,EAAiBmB,CAAQ,EAK3B,MAAMC,EAAiB,KAAK,IAAI,EAAGD,EAAS,MAAM,EAC9CpC,EAAS,SACXA,EAAS,QAAQ,kBAAkBqC,EAAgBA,CAAc,CAErE,CACA,MAEF,KAAK1D,GACL,KAAKE,GAEHsD,EAAE,eAAA,EACF,MAEF,KAAKvD,GACL,KAAKE,GACHqD,EAAE,eAAA,EACF,MAEF,KAAKpD,GACL,IAAK,IAECG,IAAS,UACXiD,EAAE,eAAA,EAEJ,KAGA,EAEN,EA+EE,YA7E2DA,GAAK,CAChE,GAAI5B,EAAU,OAEd4B,EAAE,eAAA,EAEF,MAAMI,EAAaJ,EAAE,cAAc,QAAQ,MAAM,EAEjD,GAAI,CAACI,EAAY,OAGjB,MAAMH,EADgBR,EAAkBW,CAAU,EACnB,MAAM,EAAGtD,CAAS,EAG7CI,GACFA,EAAc+C,CAAQ,EAIpBjD,IAAoB,QACtB8B,EAAiBmB,CAAQ,EAK3B,MAAMC,EAAiB,KAAK,IAAID,EAAS,OAAQnD,EAAY,CAAC,EAC1De,EAAS,SACXA,EAAS,QAAQ,kBAAkBqC,EAAgBA,CAAc,CAErE,EAkDE,YAhDkB,IAAM,CAExB,GADAjB,EAAa,EAAI,EACbpB,EAAS,QAAS,CAEpB,MAAMwC,EAAiB,KAAK,IAAInB,EAAa,OAAQpC,EAAY,CAAC,EAClEe,EAAS,QAAQ,kBAAkBwC,EAAgBA,CAAc,CACnE,CACF,EA0CE,WAxCiB,IAAM,CACvBpB,EAAa,EAAK,CACpB,EAuCE,YArCkB,IAAM,CACpBpB,EAAS,SACXA,EAAS,QAAQ,MAAA,CAErB,EAkCE,QAAAU,CAAA,CAIJ,EClWM+B,GAAcC,GAAgC,CAClD,IAAIC,EAAQ,EAEZC,OAAAA,EAAAA,SAAS,QAAQF,EAAUG,GAAS,CAClC,GAAIC,EAAAA,eAAeD,CAAK,EAAG,CACzB,MAAM5E,EAAQ4E,EAAM,MAGlBA,EAAM,OAAS/E,GACd+E,EAAM,MAAmC,cAAgB,gBAE1DF,IACS1E,EAAM,WAEf0E,GAASF,GAAWxE,EAAM,QAAQ,EAEtC,CACF,CAAC,EAEM0E,CACT,EAMMI,GAAoB,CAACL,EAAqBM,EAAqB,IAA2B,CAC9F,IAAIC,EAAeD,EAgCnB,MAAO,CA9BWJ,EAAAA,SAAS,IAAIF,EAAUG,GAAS,CAChD,GAAIC,EAAAA,eAAeD,CAAK,EAAG,CACzB,MAAM5E,EAAQ4E,EAAM,MAEpB,GACEA,EAAM,OAAS/E,GACd+E,EAAM,MAAmC,cAAgB,gBAC1D,CAEA,MAAMK,EAAY,OAAOjF,EAAM,OAAU,SAAWA,EAAM,MAAQgF,IAElE,OAAOE,EAAAA,aAAaN,EAA2C,CAC7D,GAAG5E,EACH,MAAOiF,CAAA,CACR,CACH,SAAWjF,EAAM,SAAU,CAEzB,KAAM,CAACmF,EAAmBC,CAAS,EAAIN,GAAkB9E,EAAM,SAAUgF,CAAY,EACrF,OAAAA,EAAeI,EAERF,EAAAA,aAAaN,EAAO,CACzB,GAAIA,EAAM,MACV,SAAUO,CAAA,CAC2B,CACzC,CACF,CAEA,OAAOP,CACT,CAAC,EAEkBI,CAAY,CACjC,EAoFaK,GAAW,CAAC,CACvB,UAAWC,EACX,KAAArE,EAAO,OACP,MAAOC,EACP,aAAAC,EAAe,GACf,cAAAC,EACA,QAAAC,EAAU,GACV,SAAUC,EAAe,GACzB,UAAAC,EAAY,GACZ,aAAAgE,EAAe,MACf,eAAA/D,EAAiB,GACjB,WAAAC,EAAa,CAAC,IAAK,GAAG,EACtB,QAAAC,EACA,UAAA8D,EACA,YAAA7D,EAAc,GACd,KAAMC,EACN,UAAA7B,EACA,SAAA0E,EACA,GAAGgB,CACL,IAAqB,CAEnB,MAAMzE,EAAYwC,EAAAA,QAAQ,IAAM,CAC9B,GAAI8B,IAAkB,OACpB,OAAOA,EAGT,MAAMI,EAAiBlB,GAAWC,CAAQ,EAG1C,OAAOiB,EAAiB,EAAIA,EAFD,CAG7B,EAAG,CAACJ,EAAeb,CAAQ,CAAC,EAGtBU,EAAoB3B,EAAAA,QAAQ,IAAM,CACtC,KAAM,CAACK,CAAS,EAAIiB,GAAkBL,CAAQ,EAE9C,OAAOZ,CACT,EAAG,CAACY,CAAQ,CAAC,EAGP,CACJ,KAAA5C,EACA,SAAAE,EACA,aAAAE,EACA,KAAAI,EACA,SAAAC,EACA,UAAAC,EACA,WAAAC,EACA,YAAAE,EACA,aAAAU,EACA,aAAAuC,EACA,aAAAC,EACA,cAAAC,EACA,YAAAC,EACA,YAAAC,EACA,WAAAC,EACA,YAAAC,EACA,QAAAxD,CAAA,EACE1B,GAAY,CACd,UAAAC,EACA,KAAAC,EACA,MAAOC,EACP,aAAAC,EACA,cAAAC,EACA,QAAAC,EACA,aAAAC,EACA,UAAAC,EACA,eAAAC,EACA,WAAAC,EACA,QAAAC,EACA,YAAAC,EACA,SAAAC,CAAA,CACD,EAGKsE,EACJ,eAAgBT,EAAUA,EAAO,YAAY,EAA2B,OACpE,CAAE,aAAchC,GAAG,GAAG0C,GAAeV,EAcrCW,EAXA3D,EACK,CAAE,kBAAmBA,CAAA,EAG1ByD,EACK,CAAE,aAAcA,CAAA,EAGlB,CAAA,EAKT,OACE1F,EAAAA,IAACnB,EAAgB,SAAhB,CAAyB,MAAOsG,EAC/B,SAAApF,EAAAA,KAAC,MAAA,CACC,IAAK0B,EACL,uBAAqB,YACrB,KAAK,QACJ,GAAGmE,EACH,GAAI1D,EAAc,CAAE,mBAAoBA,CAAA,EAAgB,CAAA,EACzD,UAAW2D,EAAAA,GACT,2CACA/D,EAAW,qBAAuB,cAClCvC,CAAA,EAEF,QAASkG,EACR,GAAGE,EAGH,SAAA,CAAA9D,GACC7B,EAAAA,IAAC,QAAA,CACC,KAAK,SACL,KAAA6B,EACA,MAAOe,EACP,SAAUZ,EACV,gBAAeA,EACf,eAAcD,EACb,GAAG6D,CAAA,CAAA,EAIR5F,EAAAA,IAAC,QAAA,CACC,IAAKuB,EACL,GAAIF,EACJ,KAAMZ,IAAS,WAAa,WAAa,OACzC,MAAOmC,EACP,UAAApC,EACA,UAAAO,EACA,aAAAgE,EACA,SAAAjD,EACA,QAAAZ,EACA,UAAA8D,EACC,GAAGY,EACH,GAAI1D,EAAc,CAAE,mBAAoBA,CAAA,EAAgB,CAAA,EACzD,eAAcH,EACd,SAAUqD,EACV,UAAWC,EACX,QAASC,EACT,QAASC,EACT,OAAQC,EACR,UAAU,qFACV,SAAU,CAAA,CAAA,EAGXb,CAAA,CAAA,CAAA,EAEL,CAEJ,EAEAE,GAAS,YAAc,WCvThB,MAAMiB,EAAgB,CAAC,CAAE,SAAA7B,EAAU,UAAA1E,EAAW,GAAGC,KAEpDQ,MAAC,OAAI,UAAW,8CAA8CT,GAAa,EAAE,GAAK,GAAGC,EAClF,SAAAyE,CAAA,CACH,EAIJ6B,EAAc,YAAc,iBCNrB,MAAMC,EAAoB,CAAC,CAAE,UAAAxG,EAAW,GAAGC,KAE9CQ,EAAAA,IAAC,MAAA,CACC,UAAW,oDAAoDT,GAAa,EAAE,GAC7E,GAAGC,EAEJ,eAACwG,GAAAA,KAAA,CAAK,KAAK,KACT,SAAAhG,EAAAA,IAACiG,WAAM,CAAA,CACT,CAAA,CAAA,EAKNF,EAAkB,YAAc,qBCdzB,MAAMlB,GAIT,OAAO,OAAOqB,GAAM,CACtB,MAAOJ,EACP,KAAMzG,EACN,UAAW0G,CACb,CAAC,EAEDlB,GAAS,YAAc,WACvBiB,EAAc,YAAc,iBAC5BzG,EAAa,YAAc,gBAC3B0G,EAAkB,YAAc"}
1
+ {"version":3,"file":"index.js","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\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\n extends Omit<ComponentPropsWithoutRef<'div'>, 'onChange' | 'inputMode'> {\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\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\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\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"],"names":["InputOTPContext","createContext","useInputOTPContext","context","useContext","cva","inputOTPSlotStyles","inputOTPStyles","InputOTPSlot","indexProp","className","props","index","slot","char","isActive","hasFakeCaret","isEmpty","isPlaceholder","isFocusTarget","jsxs","jsx","BACKSPACE_KEY","LEFT_ARROW_KEY","UP_ARROW_KEY","RIGHT_ARROW_KEY","DOWN_ARROW_KEY","E_KEY","useInputOTP","maxLength","type","controlledValue","defaultValue","onValueChange","isValid","disabledProp","readOnlyProp","autoFocus","forceUppercase","filterKeys","pattern","placeholder","nameProp","uuid","useId","inputRef","useRef","containerRef","field","useFormFieldControl","id","name","disabled","readOnly","isInvalid","isRequired","labelId","description","fieldState","intent","initialValue","processedValue","internalValue","setInternalValue","useState","isFocused","setIsFocused","currentValue","activeIndex","useEffect","slots","useMemo","_","i","processInputValue","inputValue","processed","regexPattern","regex","currChar","error","e","newValue","newActiveIndex","isShortcut","currentLength","pastedText","cursorPosition","countSlots","children","count","Children","child","isValidElement","assignSlotIndexes","startIndex","currentIndex","slotIndex","cloneElement","processedChildren","nextIndex","InputOTP","maxLengthProp","autoComplete","inputMode","others","detectedLength","contextValue","handleChange","handleKeyDown","handleCopy","handlePaste","handleFocus","handleBlur","handleClick","ariaLabel","restOthers","accessibleNameProps","cx","InputOTPGroup","InputOTPSeparator","Root"],"mappings":"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"}