diff --git a/src/uix/active-uix/id/index.ts b/src/uix/active-uix/id/index.ts new file mode 100644 index 000000000..4c8e40f3b --- /dev/null +++ b/src/uix/active-uix/id/index.ts @@ -0,0 +1,24 @@ +/** + * Process-unique client-side id counter. + * + * `useId()` returns the next value of a monotonic module-level counter — + * cheaper than `Date.now()` and, unlike a timestamp, collision-free. Use it + * for client-only ephemeral ids (list keys, generated handles). + * + * NOT for SSR / ARIA element ids derived from the component tree — those use + * soma's `createId`, which wraps Svelte's `$props.id()` for hydration-stable + * output. A global counter would desync between server and client renders. + * + * Lives in active-uix (not soma) so any UIX layer — soma, eidos, demos, + * apps — can mint ids without coupling to soma. Imported by subpath + * (`$active-uix/id`), mirroring `$active-uix/prefs`, so it never pulls the + * runtime barrel. The `soma-` prefix is the shared UIX id convention (same + * shape `createId` emits), not a marker of where this lives. + */ + +let counter = 0 + +export function useId(component = ''): string { + const id = ++counter + return component ? `soma-${component}-${id}` : `soma-${id}` +} diff --git a/src/uix/soma/SOMA_ARCHITECTURE.md b/src/uix/soma/SOMA_ARCHITECTURE.md index 0b39ea915..74bdc1ff8 100644 --- a/src/uix/soma/SOMA_ARCHITECTURE.md +++ b/src/uix/soma/SOMA_ARCHITECTURE.md @@ -838,7 +838,7 @@ src/uix/soma/ ├── keyboard/ ← KEYS, directional ├── dom/ ← DOM utilities, focus ├── css/ ← styleToString, cssToStyleObj -├── id/ ← createId, useId +├── id/ ← createId (useId → $active-uix/id) ├── types/ ← shared types + service interfaces ├── layers/ ← behavior layers (classes only) │ ├── presence.svelte.ts diff --git a/src/uix/soma/components/accordion/components/accordion-item.svelte b/src/uix/soma/components/accordion/components/accordion-item.svelte index ccc245efd..99e6068f4 100644 --- a/src/uix/soma/components/accordion/components/accordion-item.svelte +++ b/src/uix/soma/components/accordion/components/accordion-item.svelte @@ -4,7 +4,8 @@ writableActive } from '$libs/reactive'; import { mergeProps } from '../../../props'; - import { createId, useId } from '../../../id'; + import { createId } from '../../../id'; + import { useId } from '$active-uix/id'; import { AccordionItemProvider } from '../accordion-provider.svelte'; import type { AccordionItemProps } from '../types'; diff --git a/src/uix/soma/components/date-field/date-field-provider.svelte.ts b/src/uix/soma/components/date-field/date-field-provider.svelte.ts index 5422a5455..c6672c7f3 100644 --- a/src/uix/soma/components/date-field/date-field-provider.svelte.ts +++ b/src/uix/soma/components/date-field/date-field-provider.svelte.ts @@ -21,7 +21,7 @@ import type { } from '../../types'; import { KEYS, getDirectionalKeys } from '../../keyboard'; import { isNumberString } from '../../types/guards'; -import { useId } from '../../id'; +import { useId } from '$active-uix/id'; import { Soma } from '../../core/soma.svelte'; import { DateFormatter, diff --git a/src/uix/soma/components/internal/arrow.svelte b/src/uix/soma/components/internal/arrow.svelte index 41c6d91ca..23ab414c7 100644 --- a/src/uix/soma/components/internal/arrow.svelte +++ b/src/uix/soma/components/internal/arrow.svelte @@ -1,6 +1,6 @@