{"version":3,"names":["read","value","useEnhancedClickHandler","handler","options","lastClickInteractionType","isDisabled","disabled","onPointerDown","event","defaultPrevented","pointerType","onClick","ev","detail"],"sources":["use-enhanced-click-handler.ts"],"sourcesContent":["import type { PropsLike } from \"./merge-props-n\";\n\n/**\n * Cross-browser pointer-type a click originated from.\n *\n * Mirrors the string union in Base UI React's\n * `@base-ui/utils/useEnhancedClickHandler` — empty string means \"unknown\"\n * (no prior `pointerdown` was observed and the underlying `MouseEvent`\n * didn't surface a `pointerType`).\n */\nexport type InteractionType = \"mouse\" | \"touch\" | \"pen\" | \"keyboard\" | \"\";\n\n/**\n * Accessor-or-value. Every gate on the handler may be supplied as a plain\n * value or a Solid accessor so consumers can thread reactive inputs without\n * materializing a memo.\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\nexport interface UseEnhancedClickHandlerOptions {\n\t/**\n\t * When `true` the produced handlers short-circuit: neither the pointer\n\t * snapshot nor the consumer callback runs. Defaults to `false`.\n\t */\n\tdisabled?: MaybeAccessor<boolean | undefined> | undefined;\n}\n\n/**\n * Minimal shape we need off incoming click / pointerdown events. Both Solid's\n * JSX events and the raw DOM events satisfy this.\n */\ninterface ClickLike {\n\tdefaultPrevented?: boolean;\n\t/** `detail === 0` on a click event indicates keyboard activation. */\n\tdetail?: number;\n\t/** Present on Chrome/Edge `PointerEvent`s that bubble up as click. */\n\tpointerType?: string;\n}\n\ninterface PointerDownLike {\n\tdefaultPrevented?: boolean;\n\tpointerType?: string;\n}\n\n/**\n * Port of Base UI React's `useEnhancedClickHandler`. Returns a pair of\n * handlers (`onClick`, `onPointerDown`) that cooperate to derive the\n * interaction type of a click:\n *\n * - Chromium reports `pointerType` directly on the click event — we use it.\n * - WebKit / Gecko emit a plain `MouseEvent` on click; we fall back to the\n *   pointer type captured on the most recent `pointerdown`.\n * - Keyboard activation is detected via `event.detail === 0`.\n *\n * The returned object is shaped so consumers can hand it straight to\n * `mergePropsN` without further massaging. Solid 2 notes:\n *\n * - Handlers are created once per consumer; they read `options.disabled`\n *   at call time, so reactive accessors are picked up without recreating\n *   the primitive.\n * - Unlike the React version, the consumer handler is NOT memoized — Solid\n *   components don't re-run, so there is no identity churn to guard\n *   against. Callers are responsible for wrapping a changing consumer\n *   callback in `createStableCallback` if they need a stable identity.\n */\nexport function useEnhancedClickHandler(\n\thandler: (\n\t\tevent: MouseEvent | PointerEvent,\n\t\tinteractionType: InteractionType,\n\t) => void,\n\toptions: UseEnhancedClickHandlerOptions = {},\n): PropsLike {\n\t// Closure-captured latch for the most recent pointerdown pointerType.\n\t// Cleared after each click is observed so a stale value from a previous\n\t// interaction can't leak into a keyboard-activated click.\n\tlet lastClickInteractionType: InteractionType = \"\";\n\n\tconst isDisabled = (): boolean => read(options.disabled) === true;\n\n\tfunction onPointerDown(event: PointerEvent): void {\n\t\tif (event.defaultPrevented) return;\n\t\tif (isDisabled()) return;\n\t\tconst pointerType = (event as PointerDownLike).pointerType as\n\t\t\t| InteractionType\n\t\t\t| undefined;\n\t\tlastClickInteractionType = pointerType ?? \"\";\n\t\thandler(event, lastClickInteractionType);\n\t}\n\n\tfunction onClick(event: MouseEvent | PointerEvent): void {\n\t\tif (isDisabled()) return;\n\t\tconst ev = event as ClickLike;\n\t\t// `detail === 0` is the portable signal for \"this click was\n\t\t// synthesized from a keyboard activation\" (Enter/Space on a\n\t\t// focused button). It's set by the browser, not us.\n\t\tif (ev.detail === 0) {\n\t\t\thandler(event, \"keyboard\");\n\t\t\tlastClickInteractionType = \"\";\n\t\t\treturn;\n\t\t}\n\t\tif (typeof ev.pointerType === \"string\") {\n\t\t\thandler(event, ev.pointerType as InteractionType);\n\t\t} else {\n\t\t\thandler(event, lastClickInteractionType);\n\t\t}\n\t\tlastClickInteractionType = \"\";\n\t}\n\n\t// Plain object: consumers splat this into a merge array. Writing the\n\t// keys directly keeps the resulting identity inspectable at consumer\n\t// test boundaries — `mergePropsN` chains `on*` handlers regardless.\n\treturn { onClick, onPointerDown } as PropsLike;\n}\n"],"mappings":"AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;;AAGA,SAASA,IAAIA,CAAIC,KAAmC,EAAiB;EACpE,OAAO,OAAOA,KAAK,KAAK,UAAU,GAAIA,KAAK,CAAa,CAAC,GAAGA,KAAK;AAClE;;AAUA;AACA;AACA;AACA;;AAcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,uBAAuBA,CACtCC,OAGS,EACTC,OAAuC,GAAG,CAAC,CAAC,EAChC;EACZ;EACA;EACA;EACA,IAAIC,wBAAyC,GAAG,EAAE;EAElD,MAAMC,UAAU,GAAGA,CAAA,KAAeN,IAAI,CAACI,OAAO,CAACG,QAAQ,CAAC,KAAK,IAAI;EAEjE,SAASC,aAAaA,CAACC,KAAmB,EAAQ;IACjD,IAAIA,KAAK,CAACC,gBAAgB,EAAE;IAC5B,IAAIJ,UAAU,CAAC,CAAC,EAAE;IAClB,MAAMK,WAAW,GAAIF,KAAK,CAAqBE,WAEnC;IACZN,wBAAwB,GAAGM,WAAW,IAAI,EAAE;IAC5CR,OAAO,CAACM,KAAK,EAAEJ,wBAAwB,CAAC;EACzC;EAEA,SAASO,OAAOA,CAACH,KAAgC,EAAQ;IACxD,IAAIH,UAAU,CAAC,CAAC,EAAE;IAClB,MAAMO,EAAE,GAAGJ,KAAkB;IAC7B;IACA;IACA;IACA,IAAII,EAAE,CAACC,MAAM,KAAK,CAAC,EAAE;MACpBX,OAAO,CAACM,KAAK,EAAE,UAAU,CAAC;MAC1BJ,wBAAwB,GAAG,EAAE;MAC7B;IACD;IACA,IAAI,OAAOQ,EAAE,CAACF,WAAW,KAAK,QAAQ,EAAE;MACvCR,OAAO,CAACM,KAAK,EAAEI,EAAE,CAACF,WAA8B,CAAC;IAClD,CAAC,MAAM;MACNR,OAAO,CAACM,KAAK,EAAEJ,wBAAwB,CAAC;IACzC;IACAA,wBAAwB,GAAG,EAAE;EAC9B;;EAEA;EACA;EACA;EACA,OAAO;IAAEO,OAAO;IAAEJ;EAAc,CAAC;AAClC","ignoreList":[]}