{"version":3,"file":"ToggleGroup.cjs","names":[],"sources":["../../../src/components/ToggleGroup/ToggleGroup.tsx"],"sourcesContent":["import { createContext, useCallback, useContext, useMemo, useState } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./ToggleGroup.module.css\";\n\nexport type ToggleGroupType = \"single\" | \"multiple\";\n\ninterface ToggleGroupContextValue {\n    type: ToggleGroupType;\n    isSelected: (value: string) => boolean;\n    toggle: (value: string) => void;\n}\n\nconst ToggleGroupContext = createContext<ToggleGroupContextValue | null>(null);\n\nfunction useToggleGroupContext(): ToggleGroupContextValue {\n    const ctx = useContext(ToggleGroupContext);\n    if (!ctx) {\n        throw new Error(\"ToggleGroupItem must be used within a ToggleGroup\");\n    }\n    return ctx;\n}\n\nexport interface ToggleGroupProps extends HTMLAttributes<HTMLDivElement> {\n    /** Selection mode. `\"single\"` keeps one value; `\"multiple\"` keeps a set. Default `\"single\"`. */\n    type?: ToggleGroupType;\n    /** Controlled value — `string` for `single`, `string[]` for `multiple`. */\n    value?: string | string[];\n    /** Uncontrolled initial value. */\n    defaultValue?: string | string[];\n    /** Fired with the next value whenever the selection changes. */\n    onValueChange?: (value: string | string[]) => void;\n    children: ReactNode;\n}\n\nfunction normalizeArray(value: string | string[] | undefined): string[] {\n    if (value === undefined) return [];\n    return Array.isArray(value) ? value : [value];\n}\n\n/**\n * A set of {@link ToggleGroupItem}s that share selection state via context.\n *\n * In `single` mode the value is a `string` (empty string when nothing is\n * selected); in `multiple` mode it is a `string[]`. Works controlled (pass\n * `value` + `onValueChange`) or uncontrolled (pass `defaultValue`).\n *\n * @param props - {@link ToggleGroupProps}.\n * @returns A `role=\"group\"` container wrapping the items.\n */\nexport function ToggleGroup({\n    type = \"single\",\n    value,\n    defaultValue,\n    onValueChange,\n    className,\n    children,\n    ...props\n}: ToggleGroupProps) {\n    const isControlled = value !== undefined;\n    const [internalValue, setInternalValue] = useState<string[]>(() =>\n        normalizeArray(defaultValue),\n    );\n    const selected = isControlled ? normalizeArray(value) : internalValue;\n\n    const commit = useCallback(\n        (next: string[]): void => {\n            if (!isControlled) setInternalValue(next);\n            onValueChange?.(type === \"single\" ? (next[0] ?? \"\") : next);\n        },\n        [isControlled, onValueChange, type],\n    );\n\n    const toggle = useCallback(\n        (itemValue: string): void => {\n            const isOn = selected.includes(itemValue);\n            if (type === \"single\") {\n                commit(isOn ? [] : [itemValue]);\n            } else {\n                commit(isOn ? selected.filter((v) => v !== itemValue) : [...selected, itemValue]);\n            }\n        },\n        [selected, type, commit],\n    );\n\n    const ctx = useMemo<ToggleGroupContextValue>(\n        () => ({\n            type,\n            isSelected: (itemValue: string) => selected.includes(itemValue),\n            toggle,\n        }),\n        [type, selected, toggle],\n    );\n\n    return (\n        <ToggleGroupContext.Provider value={ctx}>\n            <div role=\"group\" className={cn(styles.group, className)} {...props}>\n                {children}\n            </div>\n        </ToggleGroupContext.Provider>\n    );\n}\n\nexport interface ToggleGroupItemProps extends Omit<HTMLAttributes<HTMLButtonElement>, \"onClick\"> {\n    /** Stable value identifying this item within the group. */\n    value: string;\n    /** Disables the item. */\n    disabled?: boolean;\n    children: ReactNode;\n}\n\n/**\n * A single selectable item inside a {@link ToggleGroup}. Reads and updates the\n * group's shared state through context.\n *\n * Icon-only items need an explicit `aria-label` (forwarded to the button):\n * an SVG child gives screen readers nothing to announce.\n *\n * @param props - {@link ToggleGroupItemProps}.\n * @returns A `role=\"button\"` element exposing its state via `aria-pressed`.\n */\nexport function ToggleGroupItem({\n    value,\n    disabled,\n    className,\n    children,\n    ...props\n}: ToggleGroupItemProps) {\n    const { isSelected, toggle } = useToggleGroupContext();\n    const selected = isSelected(value);\n\n    return (\n        <button\n            type=\"button\"\n            role=\"button\"\n            aria-pressed={selected}\n            disabled={disabled}\n            data-state={selected ? \"on\" : \"off\"}\n            className={cn(styles.item, selected && styles.selected, className)}\n            onClick={() => toggle(value)}\n            {...props}\n        >\n            {children}\n        </button>\n    );\n}\n"],"mappings":"kIAaA,IAAM,GAAA,EAAqB,EAAA,cAAA,CAA8C,IAAI,EAE7E,SAAS,GAAiD,CACtD,IAAM,GAAA,EAAM,EAAA,WAAA,CAAW,CAAkB,EACzC,GAAI,CAAC,EACD,MAAU,MAAM,mDAAmD,EAEvE,OAAO,CACX,CAcA,SAAS,EAAe,EAAgD,CAEpE,OADI,IAAU,IAAA,GAAkB,CAAC,EAC1B,MAAM,QAAQ,CAAK,EAAI,EAAQ,CAAC,CAAK,CAChD,CAYA,SAAgB,EAAY,CACxB,OAAO,SACP,QACA,eACA,gBACA,YACA,WACA,GAAG,GACc,CACjB,IAAM,EAAe,IAAU,IAAA,GACzB,CAAC,EAAe,IAAA,EAAoB,EAAA,SAAA,KACtC,EAAe,CAAY,CAC/B,EACM,EAAW,EAAe,EAAe,CAAK,EAAI,EAElD,GAAA,EAAS,EAAA,YAAA,CACV,GAAyB,CACjB,GAAc,EAAiB,CAAI,EACxC,IAAgB,IAAS,SAAY,EAAK,IAAM,GAAM,CAAI,CAC9D,EACA,CAAC,EAAc,EAAe,CAAI,CACtC,EAEM,GAAA,EAAS,EAAA,YAAA,CACV,GAA4B,CACzB,IAAM,EAAO,EAAS,SAAS,CAAS,EAEpC,EADA,IAAS,SACF,EAAO,CAAC,EAAI,CAAC,CAAS,EAEtB,EAAO,EAAS,OAAQ,GAAM,IAAM,CAAS,EAAI,CAAC,GAAG,EAAU,CAAS,CAAC,CAExF,EACA,CAAC,EAAU,EAAM,CAAM,CAC3B,EAEM,GAAA,EAAM,EAAA,QAAA,MACD,CACH,OACA,WAAa,GAAsB,EAAS,SAAS,CAAS,EAC9D,QACJ,GACA,CAAC,EAAM,EAAU,CAAM,CAC3B,EAEA,OACI,EAAA,EAAA,IAAA,CAAC,EAAmB,SAApB,CAA6B,MAAO,EAChC,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,KAAK,QAAQ,UAAW,EAAA,GAAG,EAAA,QAAO,MAAO,CAAS,EAAG,GAAI,EACzD,UACA,CAAA,CACoB,CAAA,CAErC,CAoBA,SAAgB,EAAgB,CAC5B,QACA,WACA,YACA,WACA,GAAG,GACkB,CACrB,GAAM,CAAE,aAAY,UAAW,EAAsB,EAC/C,EAAW,EAAW,CAAK,EAEjC,OACI,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,KAAK,SACL,KAAK,SACL,eAAc,EACJ,WACV,aAAY,EAAW,KAAO,MAC9B,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,GAAY,EAAA,QAAO,SAAU,CAAS,EACjE,YAAe,EAAO,CAAK,EAC3B,GAAI,EAEH,UACG,CAAA,CAEhB"}