{"version":3,"names":["createContext","createMemo","createSignal","runWithOwner","untrack","useContext","readOption","SNAPSHOT_KEYS","snapshotKeys","MenuApiContext","useMenu","optional","ctx","Error","createMenu","options","open","Boolean","name","disabled","modal","activeIndex","setActiveIndex","ownedWrite","payload","setPayload","undefined","setOpen","next","details","d","reason","isCanceled","onOpenChange","api","Provider","props","children","MENU_SNAPSHOT_KEYS"],"sources":["create-menu.tsx"],"sourcesContent":["import type { JSX } from \"@solidjs/web\";\n/**\n * `createMenu` — headless primitive for the Menu compound.\n *\n * Owns the logical state surface only:\n *  - `open` — consumer-owned signal, read through the option accessor.\n *  - `activeIndex` — keyboard-highlighted item index.\n *  - `payload` — active trigger payload (for handle-driven workflows).\n *  - `setOpen` — pure event-emitter via `runWithOwner(null, ...)`.\n *\n * All DOM concerns (FloatingTree, floating-ui interaction hooks, focus trap,\n * portal, transition) stay in `<Menu.Root>`.\n */\nimport {\n\ttype Accessor,\n\tcreateContext,\n\tcreateMemo,\n\tcreateSignal,\n\trunWithOwner,\n\tuntrack,\n\tuseContext,\n} from \"solid-js\";\nimport { type MaybeAccessor, readOption } from \"../internals/maybe-accessor\";\nimport {\n\tSNAPSHOT_KEYS,\n\ttype Snapshottable,\n\tsnapshotKeys,\n} from \"../internals/observability/snapshot\";\nimport type {\n\tMenuRootChangeEventDetails,\n\tMenuRootChangeEventReason,\n} from \"./root/menu-root-context\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport type MenuChangeReason = MenuRootChangeEventReason;\n\nexport interface CreateMenuOptions<_Payload = unknown> {\n\t/**\n\t * Open state. Consumer-owned signal — the primitive reads through the\n\t * accessor and does NOT keep an internal copy.\n\t */\n\topen: MaybeAccessor<boolean>;\n\t/**\n\t * Whether the menu is disabled.\n\t * @default false\n\t */\n\tdisabled?: MaybeAccessor<boolean>;\n\t/**\n\t * Whether the menu is modal (top-level only; ignored for submenus).\n\t * @default true\n\t */\n\tmodal?: MaybeAccessor<boolean>;\n\t/**\n\t * Called via `runWithOwner(null, ...)` so consumer signal writes don't\n\t * trigger SIGNAL_WRITE_IN_OWNED_SCOPE.\n\t */\n\tonOpenChange?: (open: boolean, details: MenuRootChangeEventDetails) => void;\n}\n\nexport interface MenuApi<Payload = unknown> {\n\t/** Reactive accessor for the current open state. */\n\topen: Accessor<boolean>;\n\t/** Whether the menu is disabled. */\n\tdisabled: Accessor<boolean>;\n\t/** Whether the menu is in modal mode. */\n\tmodal: Accessor<boolean>;\n\t/** Keyboard-highlighted item index (null = none). */\n\tactiveIndex: Accessor<number | null>;\n\t/** Current payload for handle-driven workflows. */\n\tpayload: Accessor<Payload | undefined>;\n\n\t/**\n\t * Pure event-emitter — fires `onOpenChange` via `runWithOwner(null, ...)`.\n\t * The consumer owns the signal write.\n\t */\n\tsetOpen: (next: boolean, details?: MenuRootChangeEventDetails) => void;\n\t/** Update the highlighted item index. Internal coordination for nav hooks. */\n\tsetActiveIndex: (index: number | null) => void;\n\t/** Update the active payload. Internal coordination for handle-driven flow. */\n\tsetPayload: (payload: Payload | undefined) => void;\n\n\t/** Context provider — expose the api via `useMenu()`. */\n\tProvider: (props: { children: JSX.Element }) => JSX.Element;\n}\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nconst MenuApiContext = createContext<MenuApi<unknown> | null>(null);\n\n/**\n * Read the nearest {@link MenuApi}. Throws unless `optional` is true.\n */\nexport function useMenu<Payload = unknown>(): MenuApi<Payload>;\nexport function useMenu<Payload = unknown>(\n\toptional: true,\n): MenuApi<Payload> | null;\nexport function useMenu<Payload = unknown>(\n\toptional?: boolean,\n): MenuApi<Payload> | null {\n\tconst ctx = useContext(MenuApiContext);\n\tif (ctx == null && !optional) {\n\t\tthrow new Error(\"Base UI: useMenu() must be called inside a <m.Provider>.\");\n\t}\n\treturn ctx as MenuApi<Payload> | null;\n}\n\n// ---------------------------------------------------------------------------\n// Primitive\n// ---------------------------------------------------------------------------\n\n/**\n * Headless primitive for the Menu compound. Owns logical state — open,\n * disabled, modal, active item index, and payload. DOM concerns (floating-ui,\n * focus trap, portal, animation) live in `<Menu.Root>`.\n */\nexport function createMenu<Payload = unknown>(\n\toptions: CreateMenuOptions<Payload>,\n): MenuApi<Payload> {\n\tconst open = createMemo<boolean>(() => Boolean(readOption(options.open)), {\n\t\tname: \"menu.open\",\n\t});\n\n\tconst disabled = createMemo<boolean>(\n\t\t() => Boolean(readOption(options.disabled)),\n\t\t{ name: \"menu.disabled\" },\n\t);\n\n\tconst modal = createMemo<boolean>(() => readOption(options.modal) ?? true, {\n\t\tname: \"menu.modal\",\n\t});\n\n\t// Internal state — not consumer-owned but privately mutable.\n\tconst [activeIndex, setActiveIndex] = createSignal<number | null>(null, {\n\t\townedWrite: true,\n\t\tname: \"menu.activeIndex\",\n\t});\n\tconst [payload, setPayload] = createSignal<Payload | undefined>(undefined, {\n\t\townedWrite: true,\n\t\tname: \"menu.payload\",\n\t});\n\n\t// Pure event-emitter — escapes the reactive owner so consumer signal\n\t// writes inside onOpenChange don't trip SIGNAL_WRITE_IN_OWNED_SCOPE.\n\tconst setOpen = (\n\t\tnext: boolean,\n\t\tdetails?: MenuRootChangeEventDetails,\n\t): void => {\n\t\tif (untrack(disabled)) return;\n\t\tconst d =\n\t\t\tdetails ??\n\t\t\t({ reason: \"none\", isCanceled: false } as MenuRootChangeEventDetails);\n\t\trunWithOwner(null, () => options.onOpenChange?.(next, d));\n\t};\n\n\tconst api: MenuApi<Payload> = {\n\t\topen,\n\t\tdisabled,\n\t\tmodal,\n\t\tactiveIndex,\n\t\tpayload: payload as Accessor<Payload | undefined>,\n\t\tsetOpen,\n\t\tsetActiveIndex,\n\t\tsetPayload: setPayload as (payload: Payload | undefined) => void,\n\t\tProvider: (props) => (\n\t\t\t<MenuApiContext value={api as MenuApi<unknown>}>\n\t\t\t\t{props.children}\n\t\t\t</MenuApiContext>\n\t\t),\n\t};\n\n\t(api as MenuApi<Payload> & Snapshottable)[SNAPSHOT_KEYS] = MENU_SNAPSHOT_KEYS;\n\n\treturn api;\n}\n\nconst MENU_SNAPSHOT_KEYS = snapshotKeys<MenuApi>(\n\t\"open\",\n\t\"disabled\",\n\t\"modal\",\n\t\"activeIndex\",\n);\n"],"mappings":"AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAECA,aAAa,EACbC,UAAU,EACVC,YAAY,EACZC,YAAY,EACZC,OAAO,EACPC,UAAU,QACJ,UAAU;AACjB,SAA6BC,UAAU,QAAQ,6BAA6B;AAC5E,SACCC,aAAa,EAEbC,YAAY,QACN,qCAAqC;;AAM5C;AACA;AACA;;AAqDA;AACA;AACA;;AAEA,MAAMC,cAAc,GAAGT,aAAa,CAA0B,IAAI,CAAC;;AAEnE;AACA;AACA;;AAKA,OAAO,SAASU,OAAOA,CACtBC,QAAkB,EACQ;EAC1B,MAAMC,GAAG,GAAGP,UAAU,CAACI,cAAc,CAAC;EACtC,IAAIG,GAAG,IAAI,IAAI,IAAI,CAACD,QAAQ,EAAE;IAC7B,MAAM,IAAIE,KAAK,CAAC,0DAA0D,CAAC;EAC5E;EACA,OAAOD,GAAG;AACX;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASE,UAAUA,CACzBC,OAAmC,EAChB;EACnB,MAAMC,IAAI,GAAGf,UAAU,CAAU,MAAMgB,OAAO,CAACX,UAAU,CAACS,OAAO,CAACC,IAAI,CAAC,CAAC,EAAE;IACzEE,IAAI,EAAE;EACP,CAAC,CAAC;EAEF,MAAMC,QAAQ,GAAGlB,UAAU,CAC1B,MAAMgB,OAAO,CAACX,UAAU,CAACS,OAAO,CAACI,QAAQ,CAAC,CAAC,EAC3C;IAAED,IAAI,EAAE;EAAgB,CACzB,CAAC;EAED,MAAME,KAAK,GAAGnB,UAAU,CAAU,MAAMK,UAAU,CAACS,OAAO,CAACK,KAAK,CAAC,IAAI,IAAI,EAAE;IAC1EF,IAAI,EAAE;EACP,CAAC,CAAC;;EAEF;EACA,MAAM,CAACG,WAAW,EAAEC,cAAc,CAAC,GAAGpB,YAAY,CAAgB,IAAI,EAAE;IACvEqB,UAAU,EAAE,IAAI;IAChBL,IAAI,EAAE;EACP,CAAC,CAAC;EACF,MAAM,CAACM,OAAO,EAAEC,UAAU,CAAC,GAAGvB,YAAY,CAAsBwB,SAAS,EAAE;IAC1EH,UAAU,EAAE,IAAI;IAChBL,IAAI,EAAE;EACP,CAAC,CAAC;;EAEF;EACA;EACA,MAAMS,OAAO,GAAGA,CACfC,IAAa,EACbC,OAAoC,KAC1B;IACV,IAAIzB,OAAO,CAACe,QAAQ,CAAC,EAAE;IACvB,MAAMW,CAAC,GACND,OAAO,IACN;MAAEE,MAAM,EAAE,MAAM;MAAEC,UAAU,EAAE;IAAM,CAAgC;IACtE7B,YAAY,CAAC,IAAI,EAAE,MAAMY,OAAO,CAACkB,YAAY,GAAGL,IAAI,EAAEE,CAAC,CAAC,CAAC;EAC1D,CAAC;EAED,MAAMI,GAAqB,GAAG;IAC7BlB,IAAI;IACJG,QAAQ;IACRC,KAAK;IACLC,WAAW;IACXG,OAAO,EAAEA,OAAwC;IACjDG,OAAO;IACPL,cAAc;IACdG,UAAU,EAAEA,UAAoD;IAChEU,QAAQ,EAAGC,KAAK,IACf,CAAC,cAAc,CAAC,KAAK,CAAC,CAACF,GAAuB,CAAC;AAClD,IAAI,CAACE,KAAK,CAACC,QAAQ;AACnB,GAAG,EAAE,cAAc;EAElB,CAAC;EAEAH,GAAG,CAAsC3B,aAAa,CAAC,GAAG+B,kBAAkB;EAE7E,OAAOJ,GAAG;AACX;AAEA,MAAMI,kBAAkB,GAAG9B,YAAY,CACtC,MAAM,EACN,UAAU,EACV,OAAO,EACP,aACD,CAAC","ignoreList":[]}