{"version":3,"names":["read","value","useFocusableWhenDisabled","options","disabled","focusableWhenDisabled","composite","tabIndexOption","tabIndex","isNativeButton","onKeyDown","event","key","preventDefault","props","Object","defineProperties","create","enumerable","configurable","get","undefined","native","isDisabled","fwd","isFocusableComposite","isNonFocusableComposite"],"sources":["use-focusable-when-disabled.ts"],"sourcesContent":["import type { PropsLike } from \"./merge-props-n\";\n\ntype MaybeAccessor<T> = T | (() => T);\n\nfunction read<T>(value: MaybeAccessor<T> | undefined): T | undefined {\n\treturn typeof value === \"function\" ? (value as () => T)() : value;\n}\n\n/**\n * Minimal event shape we need for our `onKeyDown` swallow. Covers both Solid\n * JSX events and raw DOM `KeyboardEvent`s.\n */\ninterface KeyDownLike {\n\tkey?: string;\n\tpreventDefault?: () => void;\n}\n\nexport interface UseFocusableWhenDisabledOptions {\n\t/**\n\t * Whether the component should remain focusable while disabled.\n\t * - `true` on a native button emits `aria-disabled` and clears the native\n\t *   `disabled` attr so the browser doesn't skip it in the tab order.\n\t * - `false` on a composite item skips `aria-disabled` entirely (and keeps\n\t *   native `disabled` on native buttons).\n\t *\n\t * Left unset, composite items are focusable by default (React parity).\n\t */\n\tfocusableWhenDisabled?: MaybeAccessor<boolean | undefined> | undefined;\n\t/**\n\t * The disabled state of the component. Coerced through `read()` so either\n\t * a plain `boolean` or a `() => boolean` accessor is fine.\n\t */\n\tdisabled: MaybeAccessor<boolean | undefined>;\n\t/**\n\t * `true` when the component is an item in a composite widget. In that\n\t * case `tabIndex` is managed externally and we skip it in the returned\n\t * props bag.\n\t * @default false\n\t */\n\tcomposite?: MaybeAccessor<boolean | undefined> | undefined;\n\t/**\n\t * Explicit `tabIndex` override. Only consulted when `composite` is false.\n\t * @default 0\n\t */\n\ttabIndex?: MaybeAccessor<number | undefined> | undefined;\n\t/**\n\t * `true` when the rendered element is a real `<button>`. On native\n\t * buttons we mirror the React version: swallow the native `disabled`\n\t * attr when `focusableWhenDisabled` wins, and emit `aria-disabled` so\n\t * AT still announces the state.\n\t * @default true\n\t */\n\tisNativeButton?: MaybeAccessor<boolean | undefined> | undefined;\n}\n\nexport interface UseFocusableWhenDisabledReturn {\n\t/**\n\t * A reactive props source to pass into a `mergePropsN` / `renderElement`\n\t * chain. Backed by getters so accessor-based inputs stay live.\n\t */\n\tprops: PropsLike;\n}\n\n/**\n * Port of Base UI React's `useFocusableWhenDisabled`\n * (`packages/react/src/utils/useFocusableWhenDisabled.ts`). Produces the\n * narrow set of overrides that let a disabled button-like element remain\n * focusable when the consumer opts in.\n *\n * Solid 2 notes:\n *\n * - Every input may be an accessor. Reads happen inside getters / handlers,\n *   so there is no top-level reactive read in the primitive's body.\n * - ARIA boolean attributes surface as the literal `\"true\"` / `\"false\"`\n *   strings (RFC 07) rather than native booleans, matching how `useButton`\n *   already serializes them.\n * - The returned props are a plain proxy-shaped object — splice it into a\n *   `params.props` array and `mergePropsN` handles the rest. Handlers\n *   compose right-to-left with any consumer keybindings.\n */\nexport function useFocusableWhenDisabled(\n\toptions: UseFocusableWhenDisabledOptions,\n): UseFocusableWhenDisabledReturn {\n\tconst disabled = (): boolean => read(options.disabled) === true;\n\tconst focusableWhenDisabled = (): boolean | undefined =>\n\t\tread(options.focusableWhenDisabled);\n\tconst composite = (): boolean => read(options.composite) === true;\n\tconst tabIndexOption = (): number => read(options.tabIndex) ?? 0;\n\tconst isNativeButton = (): boolean => read(options.isNativeButton) ?? true;\n\n\t// React parity: on native disabled + focusableWhenDisabled, swallow Tab\n\t// so the consumer can't accidentally cancel its own tab-navigation, but\n\t// preventDefault on every other key so activation keys don't fire.\n\tfunction onKeyDown(event: KeyDownLike): void {\n\t\tif (!disabled()) return;\n\t\tif (!focusableWhenDisabled()) return;\n\t\tif (event.key === \"Tab\") return;\n\t\tevent.preventDefault?.();\n\t}\n\n\tconst props: PropsLike = Object.defineProperties(\n\t\tObject.create(null) as PropsLike,\n\t\t{\n\t\t\tonKeyDown: {\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t\tvalue: onKeyDown,\n\t\t\t},\n\t\t\ttabIndex: {\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t\tget: () => {\n\t\t\t\t\t// Composite items delegate tab-order to their parent — skip.\n\t\t\t\t\tif (composite()) return undefined;\n\t\t\t\t\tconst native = isNativeButton();\n\t\t\t\t\tconst isDisabled = disabled();\n\t\t\t\t\tif (!native && isDisabled) {\n\t\t\t\t\t\treturn focusableWhenDisabled() ? tabIndexOption() : -1;\n\t\t\t\t\t}\n\t\t\t\t\treturn tabIndexOption();\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"aria-disabled\": {\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t\t// Per Solid 2 RFC 07: ARIA pseudo-boolean attrs take a literal\n\t\t\t\t// string (not raw boolean), so screen readers see the expected\n\t\t\t\t// \"true\"/\"false\" value.\n\t\t\t\tget: () => {\n\t\t\t\t\tconst native = isNativeButton();\n\t\t\t\t\tconst isDisabled = disabled();\n\t\t\t\t\tconst fwd = focusableWhenDisabled();\n\t\t\t\t\tconst isFocusableComposite = composite() && fwd !== false;\n\t\t\t\t\tif (\n\t\t\t\t\t\t(native && (fwd || isFocusableComposite)) ||\n\t\t\t\t\t\t(!native && isDisabled)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn isDisabled ? \"true\" : \"false\";\n\t\t\t\t\t}\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t},\n\t\t\tdisabled: {\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t\t// Native path only: when focusableWhenDisabled kicks in we\n\t\t\t\t// clear the native `disabled` attr (so the element still\n\t\t\t\t// participates in the tab order). Non-focusable composite\n\t\t\t\t// items keep the attr so the browser can render the visual\n\t\t\t\t// disabled affordance.\n\t\t\t\tget: () => {\n\t\t\t\t\tif (!isNativeButton()) return undefined;\n\t\t\t\t\tconst fwd = focusableWhenDisabled();\n\t\t\t\t\tconst isNonFocusableComposite = composite() && fwd === false;\n\t\t\t\t\tif (!fwd || isNonFocusableComposite) {\n\t\t\t\t\t\treturn disabled();\n\t\t\t\t\t}\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t);\n\n\treturn { props };\n}\n"],"mappings":"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","ignoreList":[]}