diff --git a/packages/core/src/primitives/create-register-id.ts b/packages/core/src/primitives/create-register-id.ts new file mode 100644 index 0000000..33484cd --- /dev/null +++ b/packages/core/src/primitives/create-register-id.ts @@ -0,0 +1,15 @@ +import type { Accessor } from "solid-js"; +import { createSignal } from "solid-js"; + +/** + * Creates a reactive slot for an element's ID. + * Child parts (e.g. Dialog.Title) call setId on mount and clear it on cleanup. + * Parent parts (e.g. Dialog.Content) read getId to set aria-labelledby etc. + */ +export function createRegisterId(): [ + Accessor, + (id: string | undefined) => void, +] { + const [id, setId] = createSignal(undefined); + return [id, setId]; +} diff --git a/packages/core/src/primitives/index.ts b/packages/core/src/primitives/index.ts new file mode 100644 index 0000000..74e489e --- /dev/null +++ b/packages/core/src/primitives/index.ts @@ -0,0 +1,5 @@ +export { createControllableSignal } from "./create-controllable-signal"; +export type { CreateControllableSignalOptions } from "./create-controllable-signal"; +export { createDisclosureState } from "./create-disclosure-state"; +export type { CreateDisclosureStateOptions, DisclosureState } from "./create-disclosure-state"; +export { createRegisterId } from "./create-register-id"; diff --git a/packages/core/tests/primitives/create-register-id.test.ts b/packages/core/tests/primitives/create-register-id.test.ts new file mode 100644 index 0000000..06ac35f --- /dev/null +++ b/packages/core/tests/primitives/create-register-id.test.ts @@ -0,0 +1,32 @@ +import { createRoot } from "solid-js"; +import { describe, expect, it } from "vitest"; +import { createRegisterId } from "../../src/primitives/create-register-id"; + +describe("createRegisterId", () => { + it("starts with undefined", () => { + createRoot((dispose) => { + const [getId] = createRegisterId(); + expect(getId()).toBeUndefined(); + dispose(); + }); + }); + + it("returns registered id after set", () => { + createRoot((dispose) => { + const [getId, setId] = createRegisterId(); + setId("my-id"); + expect(getId()).toBe("my-id"); + dispose(); + }); + }); + + it("returns undefined after clearing", () => { + createRoot((dispose) => { + const [getId, setId] = createRegisterId(); + setId("my-id"); + setId(undefined); + expect(getId()).toBeUndefined(); + dispose(); + }); + }); +});