{"version":3,"names":["createEffect","createSignal","untrack","createControlledState","options","initialControlled","controlled","initiallyControlled","undefined","initialDefault","default","stateLabel","state","internal","setInternal","name","ownedWrite","fallback","isControlled","console","error","readDefault","next","Object","is","value","setValue"],"sources":["create-controlled-state.ts"],"sourcesContent":["import { type Accessor, createEffect, createSignal, untrack } from \"solid-js\";\n\nexport interface CreateControlledStateOptions<T> {\n\t/**\n\t * Reactive read of the controlled prop, already resolved through\n\t * `readOption` where the prop is a `MaybeAccessor`. A resolved value of\n\t * `undefined` means \"uncontrolled\"; any other value (including `null`\n\t * and `false`) means the consumer owns the state.\n\t */\n\tcontrolled: Accessor<T | undefined>;\n\t/**\n\t * Reactive read of the matching `default*` prop. Read ONCE at creation\n\t * to seed the internal signal — later changes are ignored (and warned\n\t * about, mirroring React Base UI's `useControlled` dev warning).\n\t */\n\tdefault?: Accessor<T | undefined>;\n\t/**\n\t * Initial value when neither the controlled prop nor the `default*`\n\t * prop is provided (Base UI's destructuring default, e.g.\n\t * `defaultOpen = false`).\n\t */\n\tfallback: T;\n\t/** Component label for warnings, e.g. `\"<Dialog.Root>\"`. */\n\tname: string;\n\t/** State label for warnings, e.g. `\"open\"`, `\"checked\"`. @default \"value\" */\n\tstate?: string;\n}\n\n/**\n * Solid port of Base UI's controlled/uncontrolled state model.\n *\n * Mirrors two equivalent React Base UI mechanisms at once:\n * - `useControlled({ controlled, default })` (checkbox, select, tabs, …)\n * - the popup-store selector `state.openProp ?? state.open` plus\n *   `useControlledProp` (dialog, popover, menu, …)\n *\n * Contract:\n * - The read accessor returns the controlled prop whenever its resolved\n *   value is not `undefined`, otherwise the internal signal.\n * - The internal signal is seeded once from `default` (else `fallback`).\n * - The setter always writes the internal signal — harmless while\n *   controlled because the read prefers the prop (exactly like\n *   `DialogStore.setOpen` writing `state.open` behind `openProp`). The\n *   `onXChange` callback and any `eventDetails.isCanceled` gate stay at\n *   the component's `setX`, NOT here.\n * - Switching controlled <-> uncontrolled after creation warns, as does\n *   changing the `default*` prop while uncontrolled.\n */\nexport function createControlledState<T>(\n\toptions: CreateControlledStateOptions<T>,\n): [Accessor<T>, (next: T) => void] {\n\tconst initialControlled = untrack(options.controlled);\n\tconst initiallyControlled = initialControlled !== undefined;\n\tconst initialDefault = untrack(() => options.default?.());\n\tconst stateLabel = options.state ?? \"value\";\n\n\t// `T` is unconstrained and may itself be a function, so seed through the\n\t// functional-setter form to avoid the value/updater ambiguity in\n\t// `createSignal`'s overloads (same idiom as navigation-menu-root).\n\tconst [internal, setInternal] = createSignal<T | undefined>(undefined, {\n\t\tname: `${options.name}.${stateLabel}`,\n\t\townedWrite: true,\n\t});\n\tsetInternal(() =>\n\t\tinitialDefault !== undefined ? initialDefault : options.fallback,\n\t);\n\n\t// Warn on controlled <-> uncontrolled switches (Base UI dev warning;\n\t// quoin warns unconditionally, matching slider/floating-ui internals).\n\tcreateEffect(\n\t\t() => options.controlled() !== undefined,\n\t\t(isControlled) => {\n\t\t\tif (isControlled !== initiallyControlled) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`${options.name} is changing the ${\n\t\t\t\t\t\tinitiallyControlled ? \"\" : \"un\"\n\t\t\t\t\t}controlled ${stateLabel} state to be ${\n\t\t\t\t\t\tinitiallyControlled ? \"un\" : \"\"\n\t\t\t\t\t}controlled. Decide between controlled and uncontrolled for the lifetime of the component.`,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t);\n\n\tif (options.default) {\n\t\tconst readDefault = options.default;\n\t\tcreateEffect(\n\t\t\t() => readDefault(),\n\t\t\t(next) => {\n\t\t\t\tif (!initiallyControlled && !Object.is(next, initialDefault)) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`${options.name} is changing the default ${stateLabel} state of an uncontrolled component after initialization. The default is only read once — use the controlled ${stateLabel} prop instead.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t}\n\n\tconst value: Accessor<T> = () => {\n\t\tconst controlled = options.controlled();\n\t\t// The internal signal is seeded before first read, so the\n\t\t// `undefined` in its type never escapes.\n\t\treturn controlled !== undefined ? controlled : (internal() as T);\n\t};\n\n\tconst setValue = (next: T): void => {\n\t\tsetInternal(() => next);\n\t};\n\n\treturn [value, setValue];\n}\n"],"mappings":"AAAA,SAAwBA,YAAY,EAAEC,YAAY,EAAEC,OAAO,QAAQ,UAAU;AA4B7E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,qBAAqBA,CACpCC,OAAwC,EACL;EACnC,MAAMC,iBAAiB,GAAGH,OAAO,CAACE,OAAO,CAACE,UAAU,CAAC;EACrD,MAAMC,mBAAmB,GAAGF,iBAAiB,KAAKG,SAAS;EAC3D,MAAMC,cAAc,GAAGP,OAAO,CAAC,MAAME,OAAO,CAACM,OAAO,GAAG,CAAC,CAAC;EACzD,MAAMC,UAAU,GAAGP,OAAO,CAACQ,KAAK,IAAI,OAAO;;EAE3C;EACA;EACA;EACA,MAAM,CAACC,QAAQ,EAAEC,WAAW,CAAC,GAAGb,YAAY,CAAgBO,SAAS,EAAE;IACtEO,IAAI,EAAE,GAAGX,OAAO,CAACW,IAAI,IAAIJ,UAAU,EAAE;IACrCK,UAAU,EAAE;EACb,CAAC,CAAC;EACFF,WAAW,CAAC,MACXL,cAAc,KAAKD,SAAS,GAAGC,cAAc,GAAGL,OAAO,CAACa,QACzD,CAAC;;EAED;EACA;EACAjB,YAAY,CACX,MAAMI,OAAO,CAACE,UAAU,CAAC,CAAC,KAAKE,SAAS,EACvCU,YAAY,IAAK;IACjB,IAAIA,YAAY,KAAKX,mBAAmB,EAAE;MACzCY,OAAO,CAACC,KAAK,CACZ,GAAGhB,OAAO,CAACW,IAAI,oBACdR,mBAAmB,GAAG,EAAE,GAAG,IAAI,cAClBI,UAAU,gBACvBJ,mBAAmB,GAAG,IAAI,GAAG,EAAE,2FAEjC,CAAC;IACF;EACD,CACD,CAAC;EAED,IAAIH,OAAO,CAACM,OAAO,EAAE;IACpB,MAAMW,WAAW,GAAGjB,OAAO,CAACM,OAAO;IACnCV,YAAY,CACX,MAAMqB,WAAW,CAAC,CAAC,EAClBC,IAAI,IAAK;MACT,IAAI,CAACf,mBAAmB,IAAI,CAACgB,MAAM,CAACC,EAAE,CAACF,IAAI,EAAEb,cAAc,CAAC,EAAE;QAC7DU,OAAO,CAACC,KAAK,CACZ,GAAGhB,OAAO,CAACW,IAAI,4BAA4BJ,UAAU,gHAAgHA,UAAU,gBAChL,CAAC;MACF;IACD,CACD,CAAC;EACF;EAEA,MAAMc,KAAkB,GAAGA,CAAA,KAAM;IAChC,MAAMnB,UAAU,GAAGF,OAAO,CAACE,UAAU,CAAC,CAAC;IACvC;IACA;IACA,OAAOA,UAAU,KAAKE,SAAS,GAAGF,UAAU,GAAIO,QAAQ,CAAC,CAAO;EACjE,CAAC;EAED,MAAMa,QAAQ,GAAIJ,IAAO,IAAW;IACnCR,WAAW,CAAC,MAAMQ,IAAI,CAAC;EACxB,CAAC;EAED,OAAO,CAACG,KAAK,EAAEC,QAAQ,CAAC;AACzB","ignoreList":[]}