You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/uix/soma/components/dialog/dialog-provider.svelte.ts

479 lines
16 KiB

soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
import { Provider, context, type ProviderOpts, type WithRefOpts } from '../../provider';
import { boolToEmptyStrOrUndef, getDataOpenClosed } from '../../attrs';
import {
readableActive,
state,
type Active,
type ActiveProps,
type StateProps
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
} from '../../reactive';
import type { OnChangeFn, SomaMouseEvent } from '../../types';
import { Soma } from '../../core/soma.svelte';
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
import { watch } from 'runed';
import { untrack } from 'svelte';
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
import { Presence } from '../../layers/presence.svelte';
import { FocusScope } from '../../layers/focus-scope.svelte';
import { Dismissal, type DismissalBehavior } from '../../layers/dismissal.svelte';
import { ScrollLock } from '../../layers/scroll-lock.svelte';
import { TextSelection } from '../../layers/text-selection.svelte';
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
morfo: cross-layer contract + 14 new WAI-ARIA components + Dialog wired Morfo (src/uix/morfo/): machine-readable contract of a component's public DOM surface, shared between soma/sema/eidos. Shape v5 consolidated across three independent AI reviews (Gemini, Grok, ChatGPT) plus Sema alignment. Types, sium-based validator with cross-field invariants, dialog.ts as the first canonical morfo with data-last-action for Sema-causal exits, 7 passing unit tests. createAttrs(morfo) and registerContract(morfo) now consume a Morfo — legacy inline signature removed. Dialog provider refactored to derive parts + data contract from dialogMorfo. The other 65 soma components need porting (svelte-check lists them) — tracked work. Tooling: scripts/smoke-check.mjs — Playwright smoke over 65 soma demo routes scripts/morfo-check.ts — validates emitted DOM vs morfo scripts/morfo-vocabulary-check.ts — canonical vocabulary consistency npm run smoke / morfo:check / morfo:vocabulary WAI-ARIA APG components added (100% APG coverage now): Announce, Avatar, Clipboard, DragDrop, Feed, GridList, Meter, Progress, SearchField, TagGroup, TreeGrid + Table.RowDetail/Trigger (detail panel pattern; hierarchical Table rows deprecated — use TreeGrid instead). air: Link, Banner. Sema prep: src/uix/sema/sema_pre.md documents the semantic layer's DOM requirements. Morfo already provides everything Sema needs (data-last-action patterns, transition markers, enumerable state values, cross-component consistency). Sema implementation deferred. COMPONENT_GUIDE updated: items 37-39 (translation namespace grep, DOM topology vs .require() audit, npm run smoke is part of done) + A34 rule with incident log. WAI-ARIA pattern listed as soma membership criterion. Pagination translation bug fixed (soma.pagination.page -> idlangref PAGINATION_LANGS.PAGE). Table demo namespace fix (soma.table.* -> components.table.*). Avatar demo now offline-safe (SVG data URL). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
import { dialogMorfo } from '../../../morfo/components/dialog';
uix: consolidate DOM + relocate morfo runtime to its layer Three architectural cleanups in one cut: 1. **morfo runtime relocates to its own layer.** The MorfoRuntime + the pure morfo→attrs resolver (and their tests) move from `src/uix/soma/morfo/` → `src/uix/morfo/`. They were never soma-specific — they interpret a morfo declaration on behalf of any consumer. Soma was just the only consumer at the time. The new barrel at `$uix/morfo` re-exports `createMorfoRuntime`, `MorfoRuntime`, `MorfoRuntimeSources`, `RegisterPartOpts`, `SourceMap`, `SemanticEmitter`, `TriggerOptions`, plus the resolver helpers (`findMorfoPart`, `resolvePartAttrs`, `shouldEmitMorfoEntry`, etc.). 2. **`src/uix/adom/` is gone.** The runtime pieces (`createActiveDom`, `BodyScrollLock`, `DOMContext`, `RovingFocusGroup`, viewport) all live at `$adom` (`src/arts/adom/`) which is the canonical ecosystem-level ActiveDom. The `apply.ts` types and helpers (`DomAttrValue`, `applyChange`, `removeAttrs`, `StructuralChange`) live in `$libs/dom` and are re-exported from `$adom`. The 4 last `$uix/adom` import sites updated to `$adom`. 3. **`src/uix/soma/dom/` is gone.** The 14 utilities (`isBrowser`, `getDocument`, `isHTMLElement`, focus + tabbable helpers, etc.) all exist as a superset in `$libs/dom`. The 12 soma consumers updated their imports from `'../dom'` / `'$soma/dom'` → `'$libs/dom'`. No functional change — purely import-path consolidation. `src/uix/active-uix/` is preserved as an empty placeholder for the future cross-layer composition class that will set up morfo + soma + sema + eidos together. The relocated runtime now imports cleanly: - `ActiveDom`, `DomAttrValue` ← `$adom` - `EngineSemantic`, sema helpers ← `$uix/sema` - `Active`, `State` ← `$libs/reactive` (was `$soma/reactive`) - `createAttrs` ← `$soma/attrs` (cross-layer; createAttrs is morfo logic that lives in soma for now — slated for relocation in a follow-up) - `attachRef`, `RefAttachment` ← `$soma/provider/...` (idem) Verified: vitest 14 files / 197 tests, smoke 68/68, morfo-check 66/66.
5 months ago
import { createMorfoRuntime, type MorfoRuntime } from '$uix/morfo';
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
// ── Provider (root) ─────────────────────────────────────────────────────────
export type DialogVariant = 'dialog' | 'alertdialog';
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
interface DialogOpts
extends
ProviderOpts,
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
StateProps<{ open: boolean }>,
ActiveProps<{
disabled: boolean;
modal: boolean;
variant: DialogVariant;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
onOpenChangeComplete: OnChangeFn<boolean>;
}> {}
export class DialogProvider extends Provider<DialogOpts> {
static readonly ctx = context<DialogProvider>('Dialog');
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
static get(): DialogProvider | undefined { return this.ctx.getOr(undefined) as DialogProvider | undefined; }
static require(): DialogProvider { return this.ctx.get(); }
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
static create(opts: DialogOpts) {
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
return new DialogProvider(opts);
}
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
readonly soma = Soma.get();
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
// tracked IDs for ARIA
contentId = state('');
titleId = state('');
descriptionId = state('');
triggerId = state('');
// tracked nodes
triggerNode = state<HTMLElement | null>(null);
// ── Nesting ──────────────────────────────────────────────────────────────
readonly parent: DialogProvider | undefined;
readonly depth: number;
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
nestedOpenCount = state(0);
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
// ── Presence ─────────────────────────────────────────────────────────────
readonly contentPresence: Presence;
readonly overlayPresence: Presence;
private contentRef = state<HTMLElement | null>(null);
private overlayRef = state<HTMLElement | null>(null);
soma/dialog: soft-migrate close-* events through MorfoRuntime Inject a MorfoRuntime side-channel in DialogProvider that fires the prewrite → semantic.emit → handler cadence for the close-* events declared in the dialog morfo. The legacy provider machinery (assertProps + resolveMorfoProps + Provider class hierarchy) stays — runtime is alongside, not replacing. Wiring: - DialogProvider creates the runtime in its constructor with `events.{close-save, close-cancel, close-dismiss, close-dismiss-outside, close-after-fail}` all delegating to handleClose(). The runtime gets dom + semantic from soma + state sources for `open` + prop sources for `disabled`/`modal`. - DialogContentProvider registers the content part with the runtime when its constructor runs, so trigger() can resolve `event.target = partRef('content')` to a real DOM node. - DialogTriggerProvider.onclick keeps direct handleOpen() — the 'open' event in the morfo targets content, but content isn't in the DOM until AFTER open flips. Chicken-and-egg. - DialogCloseProvider.onclick → trigger('close-cancel'). - DialogContentProvider's dismissal callbacks: onEscapeKeydown → trigger('close-dismiss') onInteractOutside → trigger('close-dismiss-outside') What this unlocks: Each close path now writes `data-last-action` (saved/cancelled/ dismissed/dismissed-outside/failed) BEFORE flipping data-state, visible during the exit animation. The dialog recipe's tint rules in eidos finally fire in vivo. Verification (playwright check-eidos-recipes): @8ms post-click lastAction=cancelled state=open (prewrite) @241ms lastAction=cancelled state=open (signal hold) @378ms lastAction=cancelled state=closed (exit) @493ms opacity=0.017 (exiting) The 240ms wait between click and exit is sema's family='emerge' hold. The user can override per-event via `morfo.events[].hold` if 240ms feels too long for a dialog cancel. Smoke 68/68, morfo-check 66/66. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
// ── Morfo runtime (side-channel for trigger() cadence) ───────────────────
// The runtime fires the prewrite → semantic.emit → handler sequence so
// eidos can react to data-event-* during the configured hold and tint the
// exit border by `data-last-action`. The legacy provider machinery
// (assertProps + resolveMorfoProps) stays — runtime is alongside, not
// replacing.
readonly runtime: MorfoRuntime;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
private constructor(opts: DialogOpts) {
// Read parent BEFORE registering in context (ctx.set happens in super)
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
const parent = DialogProvider.get() as DialogProvider | undefined;
super(opts, { morfo: dialogMorfo, part: 'provider' }, DialogProvider.ctx);
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
this.parent = parent;
this.depth = parent ? parent.depth + 1 : 0;
// Track nested open count in parent — untrack to avoid circular reactivity
if (parent) {
watch(
() => opts.open.current,
(isOpen, prevOpen) => {
untrack(() => {
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
if (isOpen && !prevOpen) parent.nestedOpenCount.current++;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
else if (!isOpen && prevOpen)
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
parent.nestedOpenCount.current = Math.max(0, parent.nestedOpenCount.current - 1);
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
});
}
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
);
}
this.contentPresence = new Presence({
open: opts.open,
ref: this.contentRef,
onComplete: (open) => opts.onOpenChangeComplete.current(open)
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
});
this.overlayPresence = new Presence({
open: opts.open,
ref: this.overlayRef
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
});
soma/dialog: soft-migrate close-* events through MorfoRuntime Inject a MorfoRuntime side-channel in DialogProvider that fires the prewrite → semantic.emit → handler cadence for the close-* events declared in the dialog morfo. The legacy provider machinery (assertProps + resolveMorfoProps + Provider class hierarchy) stays — runtime is alongside, not replacing. Wiring: - DialogProvider creates the runtime in its constructor with `events.{close-save, close-cancel, close-dismiss, close-dismiss-outside, close-after-fail}` all delegating to handleClose(). The runtime gets dom + semantic from soma + state sources for `open` + prop sources for `disabled`/`modal`. - DialogContentProvider registers the content part with the runtime when its constructor runs, so trigger() can resolve `event.target = partRef('content')` to a real DOM node. - DialogTriggerProvider.onclick keeps direct handleOpen() — the 'open' event in the morfo targets content, but content isn't in the DOM until AFTER open flips. Chicken-and-egg. - DialogCloseProvider.onclick → trigger('close-cancel'). - DialogContentProvider's dismissal callbacks: onEscapeKeydown → trigger('close-dismiss') onInteractOutside → trigger('close-dismiss-outside') What this unlocks: Each close path now writes `data-last-action` (saved/cancelled/ dismissed/dismissed-outside/failed) BEFORE flipping data-state, visible during the exit animation. The dialog recipe's tint rules in eidos finally fire in vivo. Verification (playwright check-eidos-recipes): @8ms post-click lastAction=cancelled state=open (prewrite) @241ms lastAction=cancelled state=open (signal hold) @378ms lastAction=cancelled state=closed (exit) @493ms opacity=0.017 (exiting) The 240ms wait between click and exit is sema's family='emerge' hold. The user can override per-event via `morfo.events[].hold` if 240ms feels too long for a dialog cancel. Smoke 68/68, morfo-check 66/66. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
this.runtime = createMorfoRuntime(dialogMorfo, {
dom: this.soma.dom,
semantic: this.soma.semantic,
states: { open: () => opts.open.current },
props: {
disabled: () => opts.disabled.current,
modal: () => opts.modal.current
},
events: {
soma: emit perceptual signal on open in dialog/drawer/popover Diagnosis: clicking "open" on dialog/drawer/popover produced no sound (or any semantic feedback). Cause: every overlay trigger was bypassing `runtime.trigger(...)` with a direct `handleOpen()` because the morfo's declared target part (overlay content) doesn't yet exist in the DOM when the trigger fires — and `runtime.trigger` was throwing when the target part had no registered ref. Fix: - `MorfoRuntime.trigger(name, opts?)` now accepts `{ fallbackTarget?: HTMLElement }`. When the declared target part is unmounted, the fallback is used as the visual signal target so the perceptual signal still fires. Sound / vibra channels don't care about the target; the visual channel writes its `data-event*` to the trigger briefly, which is the natural locus of the user's action anyway. - Dialog / Drawer / Popover triggers now go through `runtime.trigger` with the trigger element as `fallbackTarget`. Each provider's `events` map gains an `open` (or `present`) entry that runs `handleOpen()` as the runtime's handler step — preserving the prewrite → emit → handler order. - Popover's toggle uses `close-dismiss` for the close direction so both directions emit a perceptual signal, not just open. Soma class: `soma.dom` and `soma.semantic` are now non-optional again (matching pre-migration semantics — every layout declares both services). `soma.format.*` slices stay optional. Verified end-to-end with a Playwright probe that spies AudioContext construction: Open dialog → 2 oscillators (was 0) Press Escape → +2 (was 2) Click overlay → +2 (was 0) Gates: vitest 7 files / 78 tests, smoke 68/68, morfo-check 66/66.
5 months ago
open: () => this.handleOpen(),
soma/dialog: soft-migrate close-* events through MorfoRuntime Inject a MorfoRuntime side-channel in DialogProvider that fires the prewrite → semantic.emit → handler cadence for the close-* events declared in the dialog morfo. The legacy provider machinery (assertProps + resolveMorfoProps + Provider class hierarchy) stays — runtime is alongside, not replacing. Wiring: - DialogProvider creates the runtime in its constructor with `events.{close-save, close-cancel, close-dismiss, close-dismiss-outside, close-after-fail}` all delegating to handleClose(). The runtime gets dom + semantic from soma + state sources for `open` + prop sources for `disabled`/`modal`. - DialogContentProvider registers the content part with the runtime when its constructor runs, so trigger() can resolve `event.target = partRef('content')` to a real DOM node. - DialogTriggerProvider.onclick keeps direct handleOpen() — the 'open' event in the morfo targets content, but content isn't in the DOM until AFTER open flips. Chicken-and-egg. - DialogCloseProvider.onclick → trigger('close-cancel'). - DialogContentProvider's dismissal callbacks: onEscapeKeydown → trigger('close-dismiss') onInteractOutside → trigger('close-dismiss-outside') What this unlocks: Each close path now writes `data-last-action` (saved/cancelled/ dismissed/dismissed-outside/failed) BEFORE flipping data-state, visible during the exit animation. The dialog recipe's tint rules in eidos finally fire in vivo. Verification (playwright check-eidos-recipes): @8ms post-click lastAction=cancelled state=open (prewrite) @241ms lastAction=cancelled state=open (signal hold) @378ms lastAction=cancelled state=closed (exit) @493ms opacity=0.017 (exiting) The 240ms wait between click and exit is sema's family='emerge' hold. The user can override per-event via `morfo.events[].hold` if 240ms feels too long for a dialog cancel. Smoke 68/68, morfo-check 66/66. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
'close-save': () => this.handleClose(),
'close-cancel': () => this.handleClose(),
'close-dismiss': () => this.handleClose(),
'close-dismiss-outside': () => this.handleClose(),
'close-after-fail': () => this.handleClose()
}
});
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
}
readonly isNested = $derived.by(() => this.depth > 0);
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
readonly hasNestedOpen = $derived.by(() => this.nestedOpenCount.current > 0);
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
handleOpen() {
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
if (this.opts.disabled.current || this.opts.open.current) return;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
this.opts.open.current = true;
}
handleClose() {
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
if (this.opts.disabled.current || !this.opts.open.current) return;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
this.opts.open.current = false;
}
soma/dialog: dismissWith(action) public API + tinted demo section Expose a programmatic dismiss method on DialogProvider that fires the matching close-* event through the runtime, and use it from the eidos Dialog demo to make the exit-tinting visible. Soma: - DialogProvider.dismissWith('save'|'cancel'|'fail'|'dismiss'| 'dismiss-outside') maps to the corresponding morfo event (close-save, close-cancel, close-after-fail, close-dismiss, close-dismiss-outside) and fires runtime.trigger(). - DialogProvider class re-exported from $soma/components/dialog so consumers can call DialogProvider.get() inside a child component. Demo (test/eidos/dialog): - New "Exit tinting by causa" section with three buttons that close the same dialog via three different events: Save → close-save → border-top tinted success (240ms hold) Cancel → close-cancel → border-top tinted neutral (240ms hold) Fail → close-after-fail → border-top tinted danger (600ms hold) The 600ms fail hold is sema's family='alert' default — the dialog stays open longer for the user to register the failure before close. - Uses a small _dismiss-button.svelte child component that captures DialogProvider.get() at component init time. The inline onclick pattern (Dialog.DialogProvider.get()?.dismissWith(...)) doesn't work from the parent route's scope because Svelte's getContext is init-time-only — the route is the parent of Dialog.Provider, not a child. The _dismiss-button is rendered inside Dialog.Content so its init-time context lookup resolves correctly. Verification (playwright probe): save t=144ms lastAction=saved hold=240ms cancel t=116ms lastAction=cancelled hold=240ms fail t=117ms lastAction=failed hold=600ms (full alert family) Smoke 68/68. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
/**
* Programmatic dismiss with a named cause. Drives the cadence through the
* morfo runtime so the matching `close-<action>` event fires its prewrite
* (writes `data-last-action`) BEFORE flipping `data-state` to `'closed'`.
* Eidos tints the exit border by causa during the close animation.
*
* action='save' → close-save (border tint = success)
* action='cancel' → close-cancel (border tint = neutral)
* action='dismiss' → close-dismiss (border tint = neutral)
* action='dismiss-outside' → close-dismiss-outside (border tint = neutral)
* action='fail' → close-after-fail (border tint = danger)
*/
dismissWith(action: 'save' | 'cancel' | 'dismiss' | 'dismiss-outside' | 'fail'): Promise<void> {
const eventName = action === 'fail' ? 'close-after-fail' : `close-${action}`;
return this.runtime.trigger(eventName);
}
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
setContentRef(el: HTMLElement | null) {
this.contentRef.current = el;
}
setOverlayRef(el: HTMLElement | null) {
this.overlayRef.current = el;
}
readonly props = $derived.by(() =>
this.assertProps({
...this.baseProps,
...this.resolveMorfoProps({
states: {
open: this.opts.open.current
},
props: {
disabled: this.opts.disabled.current
}
})
} as const)
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
);
}
// ── Trigger ───────────<E29480><E29480>──────────────────────────────<E29480><E29480>──────────────────────
interface DialogTriggerOpts extends WithRefOpts {}
export class DialogTriggerProvider extends Provider<DialogTriggerOpts> {
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
static create(opts: DialogTriggerOpts) {
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
return new DialogTriggerProvider(opts);
}
readonly provider: DialogProvider;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
private constructor(opts: DialogTriggerOpts) {
super(opts, { morfo: dialogMorfo, part: 'trigger' });
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
this.provider = DialogProvider.require();
this.provider.triggerId.current = opts.id.current;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
}
soma: emit perceptual signal on open in dialog/drawer/popover Diagnosis: clicking "open" on dialog/drawer/popover produced no sound (or any semantic feedback). Cause: every overlay trigger was bypassing `runtime.trigger(...)` with a direct `handleOpen()` because the morfo's declared target part (overlay content) doesn't yet exist in the DOM when the trigger fires — and `runtime.trigger` was throwing when the target part had no registered ref. Fix: - `MorfoRuntime.trigger(name, opts?)` now accepts `{ fallbackTarget?: HTMLElement }`. When the declared target part is unmounted, the fallback is used as the visual signal target so the perceptual signal still fires. Sound / vibra channels don't care about the target; the visual channel writes its `data-event*` to the trigger briefly, which is the natural locus of the user's action anyway. - Dialog / Drawer / Popover triggers now go through `runtime.trigger` with the trigger element as `fallbackTarget`. Each provider's `events` map gains an `open` (or `present`) entry that runs `handleOpen()` as the runtime's handler step — preserving the prewrite → emit → handler order. - Popover's toggle uses `close-dismiss` for the close direction so both directions emit a perceptual signal, not just open. Soma class: `soma.dom` and `soma.semantic` are now non-optional again (matching pre-migration semantics — every layout declares both services). `soma.format.*` slices stay optional. Verified end-to-end with a Playwright probe that spies AudioContext construction: Open dialog → 2 oscillators (was 0) Press Escape → +2 (was 2) Click overlay → +2 (was 0) Gates: vitest 7 files / 78 tests, smoke 68/68, morfo-check 66/66.
5 months ago
readonly onclick = (e: SomaMouseEvent<HTMLButtonElement>) => {
// `open`'s declared target (partRef('content')) is NOT in the DOM
// until handleOpen flips state. Pass the trigger as `fallbackTarget`
// so the runtime can still emit the perceptual signal — the visual
// channel writes its `data-event*` to the trigger briefly, sound /
// vibra channels don't care about the target.
void this.provider.runtime.trigger('open', {
fallbackTarget: e.currentTarget as HTMLElement
});
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
};
readonly props = $derived.by(() =>
this.assertProps({
...this.baseProps,
...this.resolveMorfoProps({
states: {
open: this.provider.opts.open.current
},
parts: {
content: this.provider.contentId.current
}
}),
disabled: this.provider.opts.disabled.current || undefined,
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
onclick: this.onclick,
...this.attachment
} as const)
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
);
}
// ── Content ─────────────────────────────────────────────────────────────────
interface DialogContentOpts
extends
WithRefOpts,
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
ActiveProps<{
trapFocus: boolean;
loop: boolean;
preventScroll: boolean;
restoreScrollDelay: number;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
onOpenAutoFocus: (e: Event) => void;
onCloseAutoFocus: (e: Event) => void;
onEscapeKeydown: (e: KeyboardEvent) => void;
escapeKeydownBehavior: DismissalBehavior | undefined;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
onInteractOutside: (e: PointerEvent) => void;
interactOutsideBehavior: DismissalBehavior | undefined;
onFocusOutside: (e: FocusEvent) => void;
}> {}
export class DialogContentProvider extends Provider<DialogContentOpts> {
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
static create(opts: DialogContentOpts) {
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
return new DialogContentProvider(opts);
}
readonly provider: DialogProvider;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
// ── Behavior layers ──────────────────────────────────────────────────────
readonly focusScope: ReturnType<typeof FocusScope.use>;
readonly dismissal: Dismissal;
readonly scrollLock: ScrollLock;
readonly textSelection: TextSelection;
private constructor(opts: DialogContentOpts) {
super(opts, { morfo: dialogMorfo, part: 'content' }, undefined, (el) => {
this.provider.setContentRef(el);
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
});
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
this.provider = DialogProvider.require();
this.provider.contentId.current = opts.id.current;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
soma/dialog: soft-migrate close-* events through MorfoRuntime Inject a MorfoRuntime side-channel in DialogProvider that fires the prewrite → semantic.emit → handler cadence for the close-* events declared in the dialog morfo. The legacy provider machinery (assertProps + resolveMorfoProps + Provider class hierarchy) stays — runtime is alongside, not replacing. Wiring: - DialogProvider creates the runtime in its constructor with `events.{close-save, close-cancel, close-dismiss, close-dismiss-outside, close-after-fail}` all delegating to handleClose(). The runtime gets dom + semantic from soma + state sources for `open` + prop sources for `disabled`/`modal`. - DialogContentProvider registers the content part with the runtime when its constructor runs, so trigger() can resolve `event.target = partRef('content')` to a real DOM node. - DialogTriggerProvider.onclick keeps direct handleOpen() — the 'open' event in the morfo targets content, but content isn't in the DOM until AFTER open flips. Chicken-and-egg. - DialogCloseProvider.onclick → trigger('close-cancel'). - DialogContentProvider's dismissal callbacks: onEscapeKeydown → trigger('close-dismiss') onInteractOutside → trigger('close-dismiss-outside') What this unlocks: Each close path now writes `data-last-action` (saved/cancelled/ dismissed/dismissed-outside/failed) BEFORE flipping data-state, visible during the exit animation. The dialog recipe's tint rules in eidos finally fire in vivo. Verification (playwright check-eidos-recipes): @8ms post-click lastAction=cancelled state=open (prewrite) @241ms lastAction=cancelled state=open (signal hold) @378ms lastAction=cancelled state=closed (exit) @493ms opacity=0.017 (exiting) The 240ms wait between click and exit is sema's family='emerge' hold. The user can override per-event via `morfo.events[].hold` if 240ms feels too long for a dialog cancel. Smoke 68/68, morfo-check 66/66. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
// Register the content part with the morfo runtime so close-* triggers
// can resolve `event.target = partRef('content')` to this DOM node.
this.provider.runtime.registerPart('content', { id: opts.id, ref: opts.ref });
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
// Layers — all integrated as behaviors
this.focusScope = FocusScope.use({
onOpenAutoFocus: opts.onOpenAutoFocus,
onCloseAutoFocus: opts.onCloseAutoFocus,
trap: opts.trapFocus,
loop: opts.loop,
ref: opts.ref,
enabled: readableActive(() => this.provider.contentPresence.isPresent)
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
});
// Behavior resolution: explicit prop wins → variant/modal defaults → 'close'
const isAlert = () => this.provider.opts.variant.current === 'alertdialog';
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
const resolvedInteractBehavior = readableActive(
() =>
opts.interactOutsideBehavior.current ??
(this.provider.opts.modal.current || isAlert() ? 'ignore' : 'close')
);
const resolvedEscapeBehavior = readableActive(
() => opts.escapeKeydownBehavior.current ?? (isAlert() ? 'ignore' : 'close')
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
);
this.dismissal = Dismissal.use({
ref: readableActive(() => opts.ref.current),
enabled: readableActive(() => this.provider.opts.open.current),
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
onEscapeKeydown: readableActive(() => (e: KeyboardEvent) => {
opts.onEscapeKeydown.current(e);
soma/dialog: soft-migrate close-* events through MorfoRuntime Inject a MorfoRuntime side-channel in DialogProvider that fires the prewrite → semantic.emit → handler cadence for the close-* events declared in the dialog morfo. The legacy provider machinery (assertProps + resolveMorfoProps + Provider class hierarchy) stays — runtime is alongside, not replacing. Wiring: - DialogProvider creates the runtime in its constructor with `events.{close-save, close-cancel, close-dismiss, close-dismiss-outside, close-after-fail}` all delegating to handleClose(). The runtime gets dom + semantic from soma + state sources for `open` + prop sources for `disabled`/`modal`. - DialogContentProvider registers the content part with the runtime when its constructor runs, so trigger() can resolve `event.target = partRef('content')` to a real DOM node. - DialogTriggerProvider.onclick keeps direct handleOpen() — the 'open' event in the morfo targets content, but content isn't in the DOM until AFTER open flips. Chicken-and-egg. - DialogCloseProvider.onclick → trigger('close-cancel'). - DialogContentProvider's dismissal callbacks: onEscapeKeydown → trigger('close-dismiss') onInteractOutside → trigger('close-dismiss-outside') What this unlocks: Each close path now writes `data-last-action` (saved/cancelled/ dismissed/dismissed-outside/failed) BEFORE flipping data-state, visible during the exit animation. The dialog recipe's tint rules in eidos finally fire in vivo. Verification (playwright check-eidos-recipes): @8ms post-click lastAction=cancelled state=open (prewrite) @241ms lastAction=cancelled state=open (signal hold) @378ms lastAction=cancelled state=closed (exit) @493ms opacity=0.017 (exiting) The 240ms wait between click and exit is sema's family='emerge' hold. The user can override per-event via `morfo.events[].hold` if 240ms feels too long for a dialog cancel. Smoke 68/68, morfo-check 66/66. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
if (!e.defaultPrevented) void this.provider.runtime.trigger('close-dismiss');
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
}),
escapeKeydownBehavior: resolvedEscapeBehavior,
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
onInteractOutside: readableActive(() => (e: PointerEvent) => {
opts.onInteractOutside.current(e);
soma/dialog: soft-migrate close-* events through MorfoRuntime Inject a MorfoRuntime side-channel in DialogProvider that fires the prewrite → semantic.emit → handler cadence for the close-* events declared in the dialog morfo. The legacy provider machinery (assertProps + resolveMorfoProps + Provider class hierarchy) stays — runtime is alongside, not replacing. Wiring: - DialogProvider creates the runtime in its constructor with `events.{close-save, close-cancel, close-dismiss, close-dismiss-outside, close-after-fail}` all delegating to handleClose(). The runtime gets dom + semantic from soma + state sources for `open` + prop sources for `disabled`/`modal`. - DialogContentProvider registers the content part with the runtime when its constructor runs, so trigger() can resolve `event.target = partRef('content')` to a real DOM node. - DialogTriggerProvider.onclick keeps direct handleOpen() — the 'open' event in the morfo targets content, but content isn't in the DOM until AFTER open flips. Chicken-and-egg. - DialogCloseProvider.onclick → trigger('close-cancel'). - DialogContentProvider's dismissal callbacks: onEscapeKeydown → trigger('close-dismiss') onInteractOutside → trigger('close-dismiss-outside') What this unlocks: Each close path now writes `data-last-action` (saved/cancelled/ dismissed/dismissed-outside/failed) BEFORE flipping data-state, visible during the exit animation. The dialog recipe's tint rules in eidos finally fire in vivo. Verification (playwright check-eidos-recipes): @8ms post-click lastAction=cancelled state=open (prewrite) @241ms lastAction=cancelled state=open (signal hold) @378ms lastAction=cancelled state=closed (exit) @493ms opacity=0.017 (exiting) The 240ms wait between click and exit is sema's family='emerge' hold. The user can override per-event via `morfo.events[].hold` if 240ms feels too long for a dialog cancel. Smoke 68/68, morfo-check 66/66. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
if (!e.defaultPrevented) void this.provider.runtime.trigger('close-dismiss-outside');
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
}),
interactOutsideBehavior: resolvedInteractBehavior,
onFocusOutside: opts.onFocusOutside,
isValidEvent: readableActive(() => () => false)
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
});
this.scrollLock = new ScrollLock(undefined, () => opts.restoreScrollDelay.current);
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
$effect(() => {
this.scrollLock.locked.current =
this.provider.opts.open.current && opts.preventScroll.current;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
});
this.textSelection = TextSelection.use({
ref: readableActive(() => opts.ref.current),
enabled: readableActive(() => this.provider.opts.open.current),
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
onPointerDown: readableActive(() => () => {}),
onPointerUp: readableActive(() => () => {})
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
});
}
readonly isPresent = $derived.by(() => this.provider.contentPresence.isPresent);
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
readonly props = $derived.by(() =>
this.assertProps({
...this.baseProps,
...this.resolveMorfoProps({
states: {
open: this.provider.opts.open.current
},
props: {
modal: this.provider.opts.modal.current
},
parts: {
title: this.provider.titleId.current,
description: this.provider.descriptionId.current
}
}),
role: this.provider.opts.variant.current,
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
'aria-roledescription': undefined,
'data-nested': this.provider.isNested ? '' : undefined,
'data-nested-open': this.provider.hasNestedOpen ? '' : undefined,
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
style: {
'pointer-events': 'auto',
'--soma-dialog-depth': `${this.provider.depth}`,
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
'--soma-dialog-nested-count': `${this.provider.nestedOpenCount.current}`
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
},
...this.provider.contentPresence.transitionAttrs,
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
...this.focusScope.props,
...this.dismissal.props
} as const)
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
);
}
// ── Overlay ────────────────────────────────────────────────────────────────
interface DialogOverlayOpts extends WithRefOpts {}
export class DialogOverlayProvider extends Provider<DialogOverlayOpts> {
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
static create(opts: DialogOverlayOpts) {
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
return new DialogOverlayProvider(opts);
}
readonly provider: DialogProvider;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
private constructor(opts: DialogOverlayOpts) {
super(opts, { morfo: dialogMorfo, part: 'overlay' }, undefined, (el) => {
this.provider.setOverlayRef(el);
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
});
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
this.provider = DialogProvider.require();
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
}
readonly isPresent = $derived.by(() => this.provider.overlayPresence.isPresent);
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
readonly props = $derived.by(() =>
this.assertProps({
...this.baseProps,
...this.resolveMorfoProps({
states: {
open: this.provider.opts.open.current
}
}),
'data-nested': this.provider.isNested ? '' : undefined,
'data-nested-open': this.provider.hasNestedOpen ? '' : undefined,
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
style: {
'pointer-events': 'auto',
'--soma-dialog-depth': `${this.provider.depth}`,
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
'--soma-dialog-nested-count': `${this.provider.nestedOpenCount.current}`
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
},
...this.provider.overlayPresence.transitionAttrs
} as const)
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
);
}
// ── Title ────<E29480><E29480><EFBFBD>──────────────────────────────────────────────────────────────
interface DialogTitleOpts extends WithRefOpts, ActiveProps<{ level: number }> {}
export class DialogTitleProvider extends Provider<DialogTitleOpts> {
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
static create(opts: DialogTitleOpts) {
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
return new DialogTitleProvider(opts);
}
readonly provider: DialogProvider;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
private constructor(opts: DialogTitleOpts) {
super(opts, { morfo: dialogMorfo, part: 'title' });
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
this.provider = DialogProvider.require();
this.provider.titleId.current = opts.id.current;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
}
readonly props = $derived.by(() =>
this.assertProps({
...this.baseProps,
...this.resolveMorfoProps({
props: {
level: this.opts.level.current
}
})
} as const)
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
);
}
// ─<><E29480> Description ────────────────────────────────────────<E29480><E29480><EFBFBD>────────────────────
interface DialogDescriptionOpts extends WithRefOpts {}
export class DialogDescriptionProvider extends Provider<DialogDescriptionOpts> {
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
static create(opts: DialogDescriptionOpts) {
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
return new DialogDescriptionProvider(opts);
}
readonly provider: DialogProvider;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
private constructor(opts: DialogDescriptionOpts) {
super(opts, { morfo: dialogMorfo, part: 'description' });
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
this.provider = DialogProvider.require();
this.provider.descriptionId.current = opts.id.current;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
}
readonly props = $derived.by(() =>
this.assertProps({
...this.baseProps
} as const)
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
);
}
// ── Close ──────────<E29480><E29480><EFBFBD>────────────────────────────────────────────────────────
interface DialogCloseOpts extends WithRefOpts {}
export class DialogCloseProvider extends Provider<DialogCloseOpts> {
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
static create(opts: DialogCloseOpts) {
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
return new DialogCloseProvider(opts);
}
readonly provider: DialogProvider;
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
private constructor(opts: DialogCloseOpts) {
super(opts, { morfo: dialogMorfo, part: 'close' });
soma: gesture layer, drawer component, full audit fixes across 26 components Gesture Layer: - Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking - VelocityTracker with ring buffer, staleness check, projection - 52 tests (velocity + gesture integration) - setPointerCapture deferred until moveBuffer exceeded (prevents click stealing) Drawer Component: - 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close - Gesture.drag() integration for swipe dismiss - Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle - Modal/non-modal/non-dismissible modes - Logical directions (start/end) RTL-aware via soma presentation - CSS custom properties (--drawer-progress, --drawer-offset-x/y) Architecture: - T1: 219 files migrated from $soma/ alias to relative paths - T2: 35 wrappers — noop replaced with () => {} inline - Translation system: componentLangs + common.buttons.* + idlangref constants - COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns - contracts.ts: case-normalized registerContract/assertContract Audit Fixes (P0 critical): - DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super - TB1: data-table attr on wrapper - CH1/SW1/NF4: hidden input rendering fixes - SP2: panel cleanup on unmount - RG1: roving tabindex fallback to first item - CO1: aria-labelledby on collapsible content Audit Fixes (P1 high): - SafePolygon integrated in dropdown-menu SubProvider + tooltip - 9 langs.ts files with idlangref constants - Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards - Stepper: count decrement + private, aria-label on List - ToggleGroup: roving tabindex in multiple mode - Select: pure aria-activedescendant (no mixed focus), label registry - NumberField: startValue respects min, scrubber commit on pointerup only - Toolbar: element-based focus tracking (not index) Audit Fixes (P2 medium): - A6: timer/listener cleanup in 6 components - A12: getDirectionalKeys in 4 components - A10: DOM queries scoped to root in 3 components - Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern - Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup - Pagination: reactive page clamping, Set-based computePageRange - Scroll-area: thumbSize zero-guard, mount flash prevention - Splitter: collapse/expand respects adjacent constraints, immediate pointer capture 5 issues remain (design decisions): stepper registry, table sub-row IDs, tags-input ARIA model, tags-input paste, toast exit animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
this.provider = DialogProvider.require();
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
}
readonly onclick = (_e: SomaMouseEvent<HTMLButtonElement>) => {
soma/dialog: soft-migrate close-* events through MorfoRuntime Inject a MorfoRuntime side-channel in DialogProvider that fires the prewrite → semantic.emit → handler cadence for the close-* events declared in the dialog morfo. The legacy provider machinery (assertProps + resolveMorfoProps + Provider class hierarchy) stays — runtime is alongside, not replacing. Wiring: - DialogProvider creates the runtime in its constructor with `events.{close-save, close-cancel, close-dismiss, close-dismiss-outside, close-after-fail}` all delegating to handleClose(). The runtime gets dom + semantic from soma + state sources for `open` + prop sources for `disabled`/`modal`. - DialogContentProvider registers the content part with the runtime when its constructor runs, so trigger() can resolve `event.target = partRef('content')` to a real DOM node. - DialogTriggerProvider.onclick keeps direct handleOpen() — the 'open' event in the morfo targets content, but content isn't in the DOM until AFTER open flips. Chicken-and-egg. - DialogCloseProvider.onclick → trigger('close-cancel'). - DialogContentProvider's dismissal callbacks: onEscapeKeydown → trigger('close-dismiss') onInteractOutside → trigger('close-dismiss-outside') What this unlocks: Each close path now writes `data-last-action` (saved/cancelled/ dismissed/dismissed-outside/failed) BEFORE flipping data-state, visible during the exit animation. The dialog recipe's tint rules in eidos finally fire in vivo. Verification (playwright check-eidos-recipes): @8ms post-click lastAction=cancelled state=open (prewrite) @241ms lastAction=cancelled state=open (signal hold) @378ms lastAction=cancelled state=closed (exit) @493ms opacity=0.017 (exiting) The 240ms wait between click and exit is sema's family='emerge' hold. The user can override per-event via `morfo.events[].hold` if 240ms feels too long for a dialog cancel. Smoke 68/68, morfo-check 66/66. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
void this.provider.runtime.trigger('close-cancel');
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
};
readonly props = $derived.by(() =>
this.assertProps({
...this.baseProps,
...this.resolveMorfoProps(),
onclick: this.onclick
} as const)
Refactor soma: consolidate layers, add Soma class, Dialog component, animation system Layers: - Consolidate 28 files/10 dirs → 13 files/2 dirs - Separate behavior layers (classes) from internal components - Normalize naming: Dismissal, ScrollLock, TextSelection, FocusScope - Adapt floating layer from terra to soma (imports, CSS vars --soma--) - Presence rewritten: data-starting/ending-style, forceMount, onComplete, getAnimations API Architecture: - Replace config/ with Soma class (root instance with services) - Add SomaFormat namespace (date, number, currency, unit formatters) - Add generic resolve() for prop → config → fallback chain - Provider supports optional ref (ProviderOpts vs WithRefOpts) - Hierarchical component barrel: import { Dialog } from '$soma/components' - Descriptive IDs: soma-dialog-trigger-c12 Dialog component (7 parts): - Provider, Trigger, Content, Overlay, Title, Description, Close - Content integrates all behavior layers as classes (no template nesting) - modal prop controls interactOutsideBehavior automatically - Nested dialog support: depth, data-nested, --soma-dialog-depth CSS vars - Animation support: forceMount, data-starting/ending-style, onOpenChangeComplete - Translator integration for aria-labels - JSDoc documentation on all props Bug fixes: - Presence mount without ref (chicken-and-egg) - ScrollLock unlock path restores body style - Nested dialog infinite loop (untrack mutation) - pointer-events: none blocking dialog interaction Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
);
}

Powered by TurnKey Linux.