|
|
|
|
import { context, type WithRefOpts } from '../../provider';
|
|
|
|
|
import { createAttrs } from '$uix/morfo';
|
|
|
|
|
import { boolToEmptyStrOrUndef } from '$adom';
|
|
|
|
|
import { readableActive, type Active, type ActiveProps, type StateProps } from '$libs/reactive';
|
|
|
|
|
import type { OnChangeFn, Orientation, SomaKeyboardEvent, SomaMouseEvent } from '../../types';
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
import { KEYS, getDirectionalKeys } from '../../keyboard';
|
|
|
|
|
import { Soma } from '../../core/soma.svelte';
|
|
|
|
|
import { Gesture } from '../../layers/gesture';
|
|
|
|
|
import { CAROUSEL_LANGS } from './langs';
|
morfo: port 65 components + sium.lazy + morfo-check passes 66/66
All 65 soma components now consume their morfo as the cross-layer contract.
createAttrs(morfo) and registerContract(morfo) overloads removed — the
Morfo form is now mandatory. Each component provider has a 3-line morfo
import + wire-up block instead of 20+ lines of inline declarations.
Additions:
sium/core/lazy.ts — lazy() combinator for recursive schemas (unblocks
morfo's eventual lazy part-tree validation; tests included).
sium/examples/ — booking, color, login, settings, signup, survey, tree
form demos.
Route demos at src/routes/test/sium/{booking,color,login,settings,
signup,survey,tree}.
Tooling:
morfo-check.ts — now tolerates sibling parts sharing a physical element
(Link variant of Item, etc.). Queries via allPartAttrs cross-scope.
morfo-vocabulary-check.ts — 28 WARN (legitimate per-component
vocabularies or subsets like switch missing "indeterminate"). All
reviewed, none are bugs.
Fixes caught by morfo-check:
table: data-sorted / data-pinned marked severity:'optional' (only
emitted when sorting/pinning active, not always).
tree-grid: data-expanded on Row severity:'optional' (branches only).
menubar: data-menubar-value declared on Trigger.
splitter: data-splitter-panel-id declared on Panel.
Verify:
npm run check — 0 morfo errors (4 pre-existing in sium/examples,
unrelated).
npx vitest run src/uix/morfo — 7/7 tests pass.
npm run smoke — 65/65 routes pass.
npm run morfo:check — 66/66 morfos validate against real DOM.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
import { carouselMorfo } from '../../../morfo/components/carousel';
|
|
|
|
|
import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte';
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
|
morfo: port 65 components + sium.lazy + morfo-check passes 66/66
All 65 soma components now consume their morfo as the cross-layer contract.
createAttrs(morfo) and registerContract(morfo) overloads removed — the
Morfo form is now mandatory. Each component provider has a 3-line morfo
import + wire-up block instead of 20+ lines of inline declarations.
Additions:
sium/core/lazy.ts — lazy() combinator for recursive schemas (unblocks
morfo's eventual lazy part-tree validation; tests included).
sium/examples/ — booking, color, login, settings, signup, survey, tree
form demos.
Route demos at src/routes/test/sium/{booking,color,login,settings,
signup,survey,tree}.
Tooling:
morfo-check.ts — now tolerates sibling parts sharing a physical element
(Link variant of Item, etc.). Queries via allPartAttrs cross-scope.
morfo-vocabulary-check.ts — 28 WARN (legitimate per-component
vocabularies or subsets like switch missing "indeterminate"). All
reviewed, none are bugs.
Fixes caught by morfo-check:
table: data-sorted / data-pinned marked severity:'optional' (only
emitted when sorting/pinning active, not always).
tree-grid: data-expanded on Row severity:'optional' (branches only).
menubar: data-menubar-value declared on Trigger.
splitter: data-splitter-panel-id declared on Panel.
Verify:
npm run check — 0 morfo errors (4 pre-existing in sium/examples,
unrelated).
npx vitest run src/uix/morfo — 7/7 tests pass.
npm run smoke — 65/65 routes pass.
npm run morfo:check — 66/66 morfos validate against real DOM.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
const attrs = createAttrs(carouselMorfo);
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
|
|
|
|
|
// ── Root provider ──────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
interface CarouselOpts
|
|
|
|
|
extends
|
|
|
|
|
WithRefOpts,
|
|
|
|
|
StateProps<{ value: number }>,
|
|
|
|
|
ActiveProps<{
|
|
|
|
|
orientation: Orientation;
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
slidesPerView: number;
|
|
|
|
|
slidesToScroll: number;
|
|
|
|
|
align: 'start' | 'center' | 'end';
|
|
|
|
|
gap: string;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
loop: boolean;
|
|
|
|
|
dragEnabled: boolean;
|
|
|
|
|
dragThreshold: number;
|
|
|
|
|
autoplay: boolean;
|
|
|
|
|
autoplayDelay: number;
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
playOnInit: boolean;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
pauseOnHover: boolean;
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
stopOnInteraction: boolean;
|
|
|
|
|
stopOnFocusIn: boolean;
|
|
|
|
|
stopOnMouseEnter: boolean;
|
|
|
|
|
stopOnLastSnap: boolean;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
disabled: boolean;
|
|
|
|
|
ariaLabel: string | undefined;
|
|
|
|
|
onValueChange: OnChangeFn<number> | undefined;
|
|
|
|
|
}> {}
|
|
|
|
|
|
|
|
|
|
export class CarouselProvider {
|
|
|
|
|
readonly opts: CarouselOpts;
|
|
|
|
|
readonly runtimePart: SomaRuntimePart;
|
|
|
|
|
readonly soma: Soma;
|
|
|
|
|
readonly runtime: SomaRuntime;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
static readonly ctx = context<CarouselProvider>('Carousel');
|
|
|
|
|
static get(): CarouselProvider | undefined {
|
|
|
|
|
return this.ctx.getOr(undefined) as CarouselProvider | undefined;
|
|
|
|
|
}
|
|
|
|
|
static require(): CarouselProvider {
|
|
|
|
|
return this.ctx.get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static create(opts: CarouselOpts) {
|
|
|
|
|
return new CarouselProvider(opts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Refs — set by the respective child providers.
|
|
|
|
|
viewportRef = $state<HTMLElement | null>(null);
|
|
|
|
|
itemGroupRef = $state<HTMLElement | null>(null);
|
|
|
|
|
|
|
|
|
|
// Drag state (px offset during active drag).
|
|
|
|
|
dragOffset = $state(0);
|
|
|
|
|
|
|
|
|
|
// Autoplay pause state.
|
|
|
|
|
hovering = $state(false);
|
|
|
|
|
focused = $state(false);
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
/** User explicitly stopped (via play/pause API or stopOnInteraction). */
|
|
|
|
|
userStopped = $state(false);
|
|
|
|
|
/** Latched once interaction occurred when stopOnInteraction is true. */
|
|
|
|
|
interactionStopped = $state(false);
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
|
|
|
|
|
readonly gesture: ReturnType<typeof Gesture.base>;
|
|
|
|
|
|
|
|
|
|
private constructor(opts: CarouselOpts) {
|
|
|
|
|
this.opts = opts;
|
|
|
|
|
this.soma = Soma.require();
|
|
|
|
|
this.runtime = this.soma.runtime(carouselMorfo, {});
|
|
|
|
|
this.runtimePart = this.runtime.part('provider', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this,
|
|
|
|
|
context: CarouselProvider.ctx
|
|
|
|
|
});
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
// Apply `playOnInit=false` — start in user-stopped state so the
|
|
|
|
|
// timer effect doesn't tick until the consumer calls `play()`.
|
|
|
|
|
if (opts.autoplay.current && opts.playOnInit.current === false) {
|
|
|
|
|
this.userStopped = true;
|
|
|
|
|
}
|
|
|
|
|
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
this.gesture = Gesture.base({
|
|
|
|
|
dom: this.soma.dom,
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
ref: readableActive(() => this.itemGroupRef),
|
|
|
|
|
enabled: readableActive(() => !this.isDisabled && this.opts.dragEnabled.current),
|
|
|
|
|
axis: readableActive(() => (this.opts.orientation.current === 'horizontal' ? 'x' : 'y')),
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
onCancel: () => {
|
|
|
|
|
this.dragOffset = 0;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// ── Autoplay ─────────────────────────────────────────────────────────
|
|
|
|
|
$effect(() => {
|
|
|
|
|
if (!opts.autoplay.current) return;
|
|
|
|
|
if (this.isDisabled) return;
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
if (!this.isPlaying) return;
|
|
|
|
|
const handle = this.soma.uix.timers.interval(
|
|
|
|
|
this.autoplayTimerKey,
|
|
|
|
|
opts.autoplayDelay.current,
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
() => {
|
|
|
|
|
if (this.opts.stopOnLastSnap.current && !this.opts.loop.current) {
|
|
|
|
|
if (this.opts.value.current >= this.slideCount - 1) {
|
|
|
|
|
this.userStopped = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.next();
|
|
|
|
|
},
|
|
|
|
|
{ replace: true, meta: { component: 'carousel', action: 'autoplay' } }
|
|
|
|
|
);
|
|
|
|
|
return () => handle.cancel();
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private get autoplayTimerKey() {
|
|
|
|
|
return `soma:carousel:${this.opts.id.current}:autoplay`;
|
|
|
|
|
}
|
|
|
|
|
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
// ── Slide detection (live DOM query) ────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
getItems(): HTMLElement[] {
|
|
|
|
|
const group = this.itemGroupRef;
|
|
|
|
|
if (!group) return [];
|
|
|
|
|
return Array.from(group.querySelectorAll<HTMLElement>(`[${attrs.item}]`));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly slideCount = $derived.by(() => this.getItems().length);
|
|
|
|
|
|
|
|
|
|
// ── Flags ────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
readonly isDisabled = $derived.by(() => this.opts.disabled.current);
|
|
|
|
|
|
|
|
|
|
readonly canGoPrev = $derived.by(() => this.opts.loop.current || this.opts.value.current > 0);
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
readonly canGoNext = $derived.by(
|
|
|
|
|
() => this.opts.loop.current || this.opts.value.current < this.slideCount - 1
|
|
|
|
|
);
|
|
|
|
|
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
/** Combined autoplay-paused state — true means the timer should not tick. */
|
|
|
|
|
readonly isPlaying = $derived.by(() => {
|
|
|
|
|
if (!this.opts.autoplay.current) return false;
|
|
|
|
|
if (this.isDisabled) return false;
|
|
|
|
|
if (this.userStopped) return false;
|
|
|
|
|
if (this.interactionStopped) return false;
|
|
|
|
|
if (this.opts.pauseOnHover.current && this.hovering) return false;
|
|
|
|
|
if (this.opts.stopOnMouseEnter.current && this.hovering) return false;
|
|
|
|
|
if (this.opts.stopOnFocusIn.current && this.focused) return false;
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/** Public name kept for back-compat; `isPlaying` is the canonical signal. */
|
|
|
|
|
readonly paused = $derived.by(() => !this.isPlaying);
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
|
|
|
|
|
// ── Geometry ─────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
/** Size (px) of the viewport along the primary axis. */
|
|
|
|
|
readonly viewportSize = $derived.by(() => {
|
|
|
|
|
const vp = this.viewportRef;
|
|
|
|
|
if (!vp) return 0;
|
|
|
|
|
return this.opts.orientation.current === 'horizontal' ? vp.clientWidth : vp.clientHeight;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
});
|
|
|
|
|
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
/** Slide size (px) along the primary axis = viewport / slidesPerView. */
|
|
|
|
|
readonly slideSize = $derived.by(() => {
|
|
|
|
|
const spv = Math.max(1, this.opts.slidesPerView.current);
|
|
|
|
|
return this.viewportSize / spv;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/** Align offset (px) applied to the translate so the active slide(s) line up. */
|
|
|
|
|
readonly alignOffset = $derived.by(() => {
|
|
|
|
|
const align = this.opts.align.current;
|
|
|
|
|
const spv = Math.max(1, this.opts.slidesPerView.current);
|
|
|
|
|
if (align === 'start' || spv <= 1) return 0;
|
|
|
|
|
const free = this.viewportSize - this.slideSize;
|
|
|
|
|
if (align === 'center') return free / 2;
|
|
|
|
|
if (align === 'end') return free;
|
|
|
|
|
return 0;
|
|
|
|
|
});
|
|
|
|
|
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
/** Translate value (px) for the item-group. */
|
|
|
|
|
readonly translate = $derived.by(() => {
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
const base = -this.opts.value.current * this.slideSize + this.alignOffset;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
return base + this.dragOffset;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
readonly itemGroupTransform = $derived.by(() => {
|
|
|
|
|
const v = this.translate;
|
|
|
|
|
return this.opts.orientation.current === 'horizontal'
|
|
|
|
|
? `translate3d(${v}px, 0, 0)`
|
|
|
|
|
: `translate3d(0, ${v}px, 0)`;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// ── Navigation ───────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
commit(next: number) {
|
|
|
|
|
if (this.isDisabled) return;
|
|
|
|
|
const count = this.slideCount;
|
|
|
|
|
if (count === 0) return;
|
|
|
|
|
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
const spv = Math.max(1, this.opts.slidesPerView.current);
|
|
|
|
|
const lastSnap = Math.max(0, count - spv);
|
|
|
|
|
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
let target: number;
|
|
|
|
|
if (this.opts.loop.current) {
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
const wrap = lastSnap + 1;
|
|
|
|
|
target = ((next % wrap) + wrap) % wrap;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
} else {
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
target = Math.max(0, Math.min(lastSnap, next));
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (target === this.opts.value.current) return;
|
|
|
|
|
this.opts.value.current = target;
|
|
|
|
|
this.opts.onValueChange.current?.(target);
|
|
|
|
|
}
|
|
|
|
|
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
/** Mark this navigation as user-driven so `stopOnInteraction` can latch. */
|
|
|
|
|
private noteInteraction() {
|
|
|
|
|
if (this.opts.stopOnInteraction.current && this.opts.autoplay.current) {
|
|
|
|
|
this.interactionStopped = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
next() {
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
const step = Math.max(1, this.opts.slidesToScroll.current);
|
|
|
|
|
this.commit(this.opts.value.current + step);
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prev() {
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
const step = Math.max(1, this.opts.slidesToScroll.current);
|
|
|
|
|
this.commit(this.opts.value.current - step);
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goto(index: number) {
|
|
|
|
|
this.commit(index);
|
|
|
|
|
}
|
|
|
|
|
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
// ── Imperative API surface ───────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
scrollNext() {
|
|
|
|
|
this.noteInteraction();
|
|
|
|
|
this.next();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scrollPrev() {
|
|
|
|
|
this.noteInteraction();
|
|
|
|
|
this.prev();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scrollTo(index: number) {
|
|
|
|
|
this.noteInteraction();
|
|
|
|
|
this.commit(index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
play() {
|
|
|
|
|
this.userStopped = false;
|
|
|
|
|
this.interactionStopped = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pause() {
|
|
|
|
|
this.userStopped = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reset() {
|
|
|
|
|
this.userStopped = false;
|
|
|
|
|
this.interactionStopped = false;
|
|
|
|
|
}
|
|
|
|
|
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
// ── Keyboard ─────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
readonly onkeydown = (e: SomaKeyboardEvent<HTMLDivElement>) => {
|
|
|
|
|
if (this.isDisabled) return;
|
|
|
|
|
const { nextKey, prevKey } = getDirectionalKeys('ltr', this.opts.orientation.current);
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
if (e.key === nextKey) {
|
|
|
|
|
e.preventDefault();
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
this.scrollNext();
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
} else if (e.key === prevKey) {
|
|
|
|
|
e.preventDefault();
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
this.scrollPrev();
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
} else if (e.key === KEYS.HOME) {
|
|
|
|
|
e.preventDefault();
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
this.scrollTo(0);
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
} else if (e.key === KEYS.END) {
|
|
|
|
|
e.preventDefault();
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
const spv = Math.max(1, this.opts.slidesPerView.current);
|
|
|
|
|
this.scrollTo(Math.max(0, this.slideCount - spv));
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
readonly onpointerenter = () => {
|
|
|
|
|
this.hovering = true;
|
|
|
|
|
};
|
|
|
|
|
readonly onpointerleave = () => {
|
|
|
|
|
this.hovering = false;
|
|
|
|
|
};
|
|
|
|
|
readonly onfocusin = () => {
|
|
|
|
|
this.focused = true;
|
|
|
|
|
};
|
|
|
|
|
readonly onfocusout = (e: FocusEvent) => {
|
|
|
|
|
const next = e.relatedTarget as Node | null;
|
|
|
|
|
if (next && this.opts.ref.current?.contains(next)) return;
|
|
|
|
|
this.focused = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ── Drag release → commit ────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
/** Called by the ItemGroup's drag lifecycle when the gesture ends. */
|
|
|
|
|
finishDrag() {
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
const size = this.slideSize;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
if (size === 0) {
|
|
|
|
|
this.dragOffset = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const horizontal = this.opts.orientation.current === 'horizontal';
|
|
|
|
|
const offset = horizontal ? this.gesture.offsetX : this.gesture.offsetY;
|
|
|
|
|
const velocity = horizontal ? this.gesture.velocityX : this.gesture.velocityY;
|
|
|
|
|
const fraction = offset / size;
|
|
|
|
|
const threshold = this.opts.dragThreshold.current;
|
|
|
|
|
const fastSwipe = Math.abs(velocity) > 0.5;
|
|
|
|
|
const shouldAdvance = Math.abs(fraction) > threshold || fastSwipe;
|
|
|
|
|
|
|
|
|
|
this.dragOffset = 0;
|
|
|
|
|
if (!shouldAdvance) return;
|
|
|
|
|
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
this.noteInteraction();
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
// Negative offset = dragged left/up = advance to next slide.
|
|
|
|
|
if (offset < 0) this.next();
|
|
|
|
|
else this.prev();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Snippet + root props ─────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
readonly snippetProps = $derived.by(() => ({
|
|
|
|
|
index: this.opts.value.current,
|
|
|
|
|
slideCount: this.slideCount,
|
|
|
|
|
canGoNext: this.canGoNext,
|
|
|
|
|
canGoPrev: this.canGoPrev,
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
isDragging: this.gesture.isDragging,
|
|
|
|
|
isPlaying: this.isPlaying,
|
|
|
|
|
api: {
|
|
|
|
|
scrollNext: () => this.scrollNext(),
|
|
|
|
|
scrollPrev: () => this.scrollPrev(),
|
|
|
|
|
scrollTo: (i: number) => this.scrollTo(i),
|
|
|
|
|
play: () => this.play(),
|
|
|
|
|
pause: () => this.pause(),
|
|
|
|
|
reset: () => this.reset()
|
|
|
|
|
}
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
readonly resolvedAriaLabel: Active<string | undefined> = readableActive(
|
|
|
|
|
() => this.opts.ariaLabel.current || this.soma.langs.ts(CAROUSEL_LANGS.LABEL) || undefined
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
);
|
|
|
|
|
|
|
|
|
|
readonly props = $derived.by(() =>
|
|
|
|
|
this.runtimePart.assert({
|
|
|
|
|
...this.runtimePart.props,
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
role: 'region' as const,
|
|
|
|
|
'aria-roledescription': 'carousel',
|
|
|
|
|
'aria-label': this.resolvedAriaLabel.current,
|
|
|
|
|
tabindex: this.isDisabled ? -1 : 0,
|
|
|
|
|
'data-orientation': this.opts.orientation.current,
|
|
|
|
|
'data-disabled': boolToEmptyStrOrUndef(this.isDisabled),
|
|
|
|
|
'data-dragging': boolToEmptyStrOrUndef(this.gesture.isDragging),
|
|
|
|
|
'data-autoplay': boolToEmptyStrOrUndef(this.opts.autoplay.current && !this.paused),
|
|
|
|
|
onkeydown: this.onkeydown,
|
|
|
|
|
onpointerenter: this.onpointerenter,
|
|
|
|
|
onpointerleave: this.onpointerleave,
|
|
|
|
|
onfocusin: this.onfocusin,
|
|
|
|
|
onfocusout: this.onfocusout
|
|
|
|
|
} as const)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Viewport ───────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
interface CarouselViewportOpts extends WithRefOpts {}
|
|
|
|
|
|
|
|
|
|
export class CarouselViewportProvider {
|
|
|
|
|
readonly opts: CarouselViewportOpts;
|
|
|
|
|
readonly runtimePart: SomaRuntimePart;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
static create(opts: CarouselViewportOpts) {
|
|
|
|
|
return new CarouselViewportProvider(opts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly provider: CarouselProvider;
|
|
|
|
|
|
|
|
|
|
private constructor(opts: CarouselViewportOpts) {
|
|
|
|
|
this.opts = opts;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
this.provider = CarouselProvider.require();
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('viewport', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this,
|
|
|
|
|
onRefChange: (el) => {
|
|
|
|
|
this.provider.viewportRef = el;
|
|
|
|
|
}
|
|
|
|
|
});
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly props = $derived.by(() =>
|
|
|
|
|
this.runtimePart.assert({
|
|
|
|
|
...this.runtimePart.props,
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
'data-orientation': this.provider.opts.orientation.current,
|
|
|
|
|
style: { overflow: 'hidden' }
|
|
|
|
|
} as const)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── ItemGroup ──────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
interface CarouselItemGroupOpts extends WithRefOpts {}
|
|
|
|
|
|
|
|
|
|
export class CarouselItemGroupProvider {
|
|
|
|
|
readonly opts: CarouselItemGroupOpts;
|
|
|
|
|
readonly runtimePart: SomaRuntimePart;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
static create(opts: CarouselItemGroupOpts) {
|
|
|
|
|
return new CarouselItemGroupProvider(opts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly provider: CarouselProvider;
|
|
|
|
|
|
|
|
|
|
private constructor(opts: CarouselItemGroupOpts) {
|
|
|
|
|
this.opts = opts;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
this.provider = CarouselProvider.require();
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('item-group', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this,
|
|
|
|
|
onRefChange: (el) => {
|
|
|
|
|
this.provider.itemGroupRef = el;
|
|
|
|
|
}
|
|
|
|
|
});
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
|
|
|
|
|
// Drag lifecycle — track offset during drag, commit on release.
|
|
|
|
|
let wasDragging = false;
|
|
|
|
|
$effect(() => {
|
|
|
|
|
const isDragging = this.provider.gesture.isDragging;
|
|
|
|
|
if (isDragging) {
|
|
|
|
|
const horizontal = this.provider.opts.orientation.current === 'horizontal';
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
this.provider.dragOffset = horizontal
|
|
|
|
|
? this.provider.gesture.offsetX
|
|
|
|
|
: this.provider.gesture.offsetY;
|
|
|
|
|
} else if (wasDragging) {
|
|
|
|
|
this.provider.finishDrag();
|
|
|
|
|
}
|
|
|
|
|
wasDragging = isDragging;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly props = $derived.by(() =>
|
|
|
|
|
this.runtimePart.assert({
|
|
|
|
|
...this.runtimePart.props,
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
'data-orientation': this.provider.opts.orientation.current,
|
|
|
|
|
'data-dragging': boolToEmptyStrOrUndef(this.provider.gesture.isDragging),
|
|
|
|
|
style: {
|
|
|
|
|
display: 'flex',
|
|
|
|
|
'flex-direction':
|
|
|
|
|
this.provider.opts.orientation.current === 'horizontal' ? 'row' : 'column',
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
gap: this.provider.opts.gap.current,
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
transform: this.provider.itemGroupTransform,
|
|
|
|
|
transition: this.provider.gesture.isDragging ? 'none' : 'transform 300ms ease-out',
|
|
|
|
|
'touch-action': this.provider.opts.orientation.current === 'horizontal' ? 'pan-y' : 'pan-x'
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
},
|
|
|
|
|
...this.provider.gesture.props
|
|
|
|
|
} as const)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Item ───────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
interface CarouselItemOpts extends WithRefOpts, ActiveProps<{ index: number }> {}
|
|
|
|
|
|
|
|
|
|
export class CarouselItemProvider {
|
|
|
|
|
readonly opts: CarouselItemOpts;
|
|
|
|
|
readonly runtimePart: SomaRuntimePart;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
static create(opts: CarouselItemOpts) {
|
|
|
|
|
return new CarouselItemProvider(opts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly provider: CarouselProvider;
|
|
|
|
|
|
|
|
|
|
private constructor(opts: CarouselItemOpts) {
|
|
|
|
|
this.opts = opts;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
this.provider = CarouselProvider.require();
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('item', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this
|
|
|
|
|
});
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
}
|
|
|
|
|
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
readonly isActive = $derived.by(() => {
|
|
|
|
|
const i = this.opts.index.current;
|
|
|
|
|
const start = this.provider.opts.value.current;
|
|
|
|
|
const spv = Math.max(1, this.provider.opts.slidesPerView.current);
|
|
|
|
|
return i >= start && i < start + spv;
|
|
|
|
|
});
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
|
|
|
|
|
readonly snippetProps = $derived.by(() => ({
|
|
|
|
|
index: this.opts.index.current,
|
|
|
|
|
isActive: this.isActive
|
|
|
|
|
}));
|
|
|
|
|
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
readonly props = $derived.by(() => {
|
|
|
|
|
const spv = Math.max(1, this.provider.opts.slidesPerView.current);
|
|
|
|
|
const gap = this.provider.opts.gap.current;
|
|
|
|
|
// `flex-basis: calc((100% - (spv - 1) * gap) / spv)` keeps slides
|
|
|
|
|
// uniformly sized when gap > 0; falls through to `100% / spv` when
|
|
|
|
|
// gap is the default `0px`.
|
|
|
|
|
const basis = spv === 1 ? '100%' : `calc((100% - ${spv - 1} * ${gap}) / ${spv})`;
|
|
|
|
|
return this.runtimePart.assert({
|
|
|
|
|
...this.runtimePart.props,
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
role: 'group' as const,
|
|
|
|
|
'aria-roledescription': 'slide',
|
|
|
|
|
'aria-label': `Slide ${this.opts.index.current + 1} of ${this.provider.slideCount}`,
|
|
|
|
|
'data-state': this.isActive ? 'active' : 'inactive',
|
|
|
|
|
'data-index': this.opts.index.current,
|
|
|
|
|
'data-orientation': this.provider.opts.orientation.current,
|
|
|
|
|
style: {
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
flex: `0 0 ${basis}`,
|
|
|
|
|
'min-width': 0,
|
|
|
|
|
'min-height': 0
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
}
|
fix(carousel): vertical overflow + close gaps vs embla/ark-ui/mantine
Real reference audit walked the published embla `.d.ts`, Mantine docs,
ark-ui, shadcn-svelte and Swiper. Found three classes of gaps in the
initial port (a) the vertical bug breaking the only non-default
orientation, (b) layout primitives every other lib ships (slidesPerView,
slidesToScroll, align, gap), (c) autoplay granularity (playOnInit,
stopOnInteraction, stopOnFocusIn, stopOnMouseEnter, stopOnLastSnap),
plus an imperative API every consumer needs.
## Vertical bug fix
Recipe now gives the root a default `block-size` in vertical orientation
(`16rem`, overridable via `--_carousel-vertical-block-size` or the new
eidos `verticalBlockSize` prop) and stretches the viewport to fill it.
Without this the viewport collapses to content height and items spill.
## Soma extensions
- `defaultValue` (uncontrolled init)
- `slidesPerView` (1+) — each Item basis = (100% − gap·(n−1)) / n
- `slidesToScroll` (1+) — paged group navigation
- `align: 'start' | 'center' | 'end'` — viewport alignment
- `gap: string` (CSS length) — between-slide spacing on the ItemGroup
- `playOnInit` — start autoplay on mount (default true)
- `stopOnInteraction` — latch-stop after user clicks prev/next/indicator or drags
- `stopOnFocusIn` — pause while focus is inside (default true)
- `stopOnMouseEnter` — pause while cursor over root (Embla parity)
- `stopOnLastSnap` — latch-stop at last snap when loop=false
- Snippet exposes `isPlaying` + an `api` handle with
`scrollNext / scrollPrev / scrollTo / play / pause / reset`
`commit()` now respects `slidesPerView` (last snap = count − spv).
`next()` / `prev()` step by `slidesToScroll`. Translate calc derives
from `slideSize = viewportSize / slidesPerView` so multi-view works.
Item flex-basis adapts to slidesPerView + gap.
## Eidos additions
- `verticalBlockSize` prop — forwarded as CSS custom property for the
vertical recipe override
- Recipe selectors for vertical orientation enforcing the block-size +
viewport stretch
- Style composition so consumers can still pass inline `style`
## Demo
Live tab now has 4 organized sections (layout / drag / autoplay /
imperative API) covering every new prop. The imperative API row drives
the carousel from external buttons via the snippet handle so consumers
see the pattern in action. `verticalBlockSize` slider exercises the
vertical fix. Snippet preview emits every set prop.
## Reference comparison
Following the canon's mandate to compare with references BEFORE
declaring done, the actual feature matrix from embla published `.d.ts`,
Mantine docs, ark-ui, shadcn-svelte, Swiper:
| Feature | embla | mantine | ark | swiper | UIX |
|------------------------|-------|---------|-----|--------|-----|
| Index nav | ✓ | ✓ | ✓ | ✓ | ✓ |
| Loop | ✓ | ✓ | ✓ | ✓ | ✓ |
| Drag | ✓ | ✓ | ✓ | ✓ | ✓ |
| Autoplay | plug | plug | ✓ | ✓ | ✓ |
| Orientation H/V | ✓ | ✓ | ✓ | ✓ | ✓ |
| slidesPerView | indir | ✓ | ✓ | ✓ | ✓ |
| slidesToScroll | ✓ | ✓ | ✓ | ✓ | ✓ |
| Align | ✓ | indir | per | ✓ | ✓ |
| Gap | css | ✓ | ✓ | ✓ | ✓ |
| defaultValue | startIndex | ✓ | ✓ | ✓ | ✓ |
| playOnInit | ✓ | indir | ✓ | ✓ | ✓ |
| stopOnInteraction | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnFocusIn | ✓ | ✓ | ✓ | partl | ✓ |
| stopOnMouseEnter | ✓ | ✓ | ✓ | ✓ | ✓ |
| stopOnLastSnap | ✓ | ✓ | ✗ | ✓ | ✓ |
| Imperative API | ✓ | ✓ | ✓ | ✓ | ✓ |
| Indicators / triggers | DIY | ✓ | ✓ | ✓ | ✓ |
| Fade effect | plug | plug | ✗ | ✓ | ✗ deferred |
| Virtual slides | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
| Multirow grid | ✗ | ✗ | ✗ | ✓ | ✗ deferred |
Deferred power-user features (fade, virtual, multirow grid, cube/cards,
parallax) are documented as power-user in the reference audit, not
table-stakes, and would require Embla-class internals to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
} as const);
|
|
|
|
|
});
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── PrevTrigger ────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
interface CarouselPrevTriggerOpts
|
|
|
|
|
extends WithRefOpts, ActiveProps<{ ariaLabel: string | undefined }> {}
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
|
|
|
|
|
export class CarouselPrevTriggerProvider {
|
|
|
|
|
readonly opts: CarouselPrevTriggerOpts;
|
|
|
|
|
readonly runtimePart: SomaRuntimePart;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
static create(opts: CarouselPrevTriggerOpts) {
|
|
|
|
|
return new CarouselPrevTriggerProvider(opts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly provider: CarouselProvider;
|
|
|
|
|
|
|
|
|
|
private constructor(opts: CarouselPrevTriggerOpts) {
|
|
|
|
|
this.opts = opts;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
this.provider = CarouselProvider.require();
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('prev-trigger', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this
|
|
|
|
|
});
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly isDisabled = $derived.by(() => this.provider.isDisabled || !this.provider.canGoPrev);
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
|
|
|
|
|
readonly onclick = (_e: SomaMouseEvent<HTMLButtonElement>) => {
|
|
|
|
|
if (this.isDisabled) return;
|
|
|
|
|
this.provider.prev();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
readonly props = $derived.by(() =>
|
|
|
|
|
this.runtimePart.assert({
|
|
|
|
|
...this.runtimePart.props,
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
type: 'button' as const,
|
|
|
|
|
'aria-label': this.opts.ariaLabel.current || this.provider.soma.langs.ts(CAROUSEL_LANGS.PREV),
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
disabled: this.isDisabled || undefined,
|
|
|
|
|
'data-disabled': boolToEmptyStrOrUndef(this.isDisabled),
|
|
|
|
|
onclick: this.onclick
|
|
|
|
|
} as const)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── NextTrigger ────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
interface CarouselNextTriggerOpts
|
|
|
|
|
extends WithRefOpts, ActiveProps<{ ariaLabel: string | undefined }> {}
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
|
|
|
|
|
export class CarouselNextTriggerProvider {
|
|
|
|
|
readonly opts: CarouselNextTriggerOpts;
|
|
|
|
|
readonly runtimePart: SomaRuntimePart;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
static create(opts: CarouselNextTriggerOpts) {
|
|
|
|
|
return new CarouselNextTriggerProvider(opts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly provider: CarouselProvider;
|
|
|
|
|
|
|
|
|
|
private constructor(opts: CarouselNextTriggerOpts) {
|
|
|
|
|
this.opts = opts;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
this.provider = CarouselProvider.require();
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('next-trigger', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this
|
|
|
|
|
});
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly isDisabled = $derived.by(() => this.provider.isDisabled || !this.provider.canGoNext);
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
|
|
|
|
|
readonly onclick = (_e: SomaMouseEvent<HTMLButtonElement>) => {
|
|
|
|
|
if (this.isDisabled) return;
|
|
|
|
|
this.provider.next();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
readonly props = $derived.by(() =>
|
|
|
|
|
this.runtimePart.assert({
|
|
|
|
|
...this.runtimePart.props,
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
type: 'button' as const,
|
|
|
|
|
'aria-label': this.opts.ariaLabel.current || this.provider.soma.langs.ts(CAROUSEL_LANGS.NEXT),
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
disabled: this.isDisabled || undefined,
|
|
|
|
|
'data-disabled': boolToEmptyStrOrUndef(this.isDisabled),
|
|
|
|
|
onclick: this.onclick
|
|
|
|
|
} as const)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── IndicatorGroup ─────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
interface CarouselIndicatorGroupOpts extends WithRefOpts {}
|
|
|
|
|
|
|
|
|
|
export class CarouselIndicatorGroupProvider {
|
|
|
|
|
readonly opts: CarouselIndicatorGroupOpts;
|
|
|
|
|
readonly runtimePart: SomaRuntimePart;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
static create(opts: CarouselIndicatorGroupOpts) {
|
|
|
|
|
return new CarouselIndicatorGroupProvider(opts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly provider: CarouselProvider;
|
|
|
|
|
|
|
|
|
|
private constructor(opts: CarouselIndicatorGroupOpts) {
|
|
|
|
|
this.opts = opts;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
this.provider = CarouselProvider.require();
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('indicator-group', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this
|
|
|
|
|
});
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly props = $derived.by(() =>
|
|
|
|
|
this.runtimePart.assert({
|
|
|
|
|
...this.runtimePart.props,
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
role: 'tablist' as const,
|
|
|
|
|
'aria-orientation': this.provider.opts.orientation.current,
|
|
|
|
|
'data-orientation': this.provider.opts.orientation.current
|
|
|
|
|
} as const)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Indicator ──────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
interface CarouselIndicatorOpts
|
|
|
|
|
extends WithRefOpts, ActiveProps<{ index: number; ariaLabel: string | undefined }> {}
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
|
|
|
|
|
export class CarouselIndicatorProvider {
|
|
|
|
|
readonly opts: CarouselIndicatorOpts;
|
|
|
|
|
readonly runtimePart: SomaRuntimePart;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
static create(opts: CarouselIndicatorOpts) {
|
|
|
|
|
return new CarouselIndicatorProvider(opts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly provider: CarouselProvider;
|
|
|
|
|
|
|
|
|
|
private constructor(opts: CarouselIndicatorOpts) {
|
|
|
|
|
this.opts = opts;
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
this.provider = CarouselProvider.require();
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('indicator', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this
|
|
|
|
|
});
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly isActive = $derived.by(
|
|
|
|
|
() => this.opts.index.current === this.provider.opts.value.current
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
readonly snippetProps = $derived.by(() => ({
|
|
|
|
|
index: this.opts.index.current,
|
|
|
|
|
isActive: this.isActive
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
readonly onclick = (_e: SomaMouseEvent<HTMLButtonElement>) => {
|
|
|
|
|
if (this.provider.isDisabled) return;
|
|
|
|
|
this.provider.goto(this.opts.index.current);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
readonly props = $derived.by(() =>
|
|
|
|
|
this.runtimePart.assert({
|
|
|
|
|
...this.runtimePart.props,
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
type: 'button' as const,
|
|
|
|
|
role: 'tab' as const,
|
|
|
|
|
'aria-selected': this.isActive,
|
|
|
|
|
'aria-label': this.opts.ariaLabel.current || `Go to slide ${this.opts.index.current + 1}`,
|
soma: 10 new components + reactivity audit + guide rules A30–A33
Components shipped:
- AlertDialog (thin Dialog specialisation with Escape=close default)
- Breadcrumb (+ interactive Ellipsis composing DropdownMenu)
- Carousel (gesture + autoplay + indicators)
- Listbox (roving tabindex + typeahead + Ctrl+A multi-select)
- NavigationMenu (hover-intent + data-motion direction + Indicator CSS vars)
- PinInput (Field-aware segmented input with paste transformer)
- RatingGroup (half-step + clearable + keyboard digits)
- Toggle (standalone two-state with Field OR-merge)
- VirtualGrid (2D windowing for spreadsheets / thumbnail grids)
- VirtualList (fixed + dynamic heights, ResizeObserver anti-jump, WindowViewport)
Guide rules (src/uix/soma/COMPONENT_GUIDE.md):
- A30 + item 32: id registration via direct assign, never $effect — the
$effect(() => parent.id = opts.id) pattern causes reactive loops that
freeze the page. Ref: PinInput + Listbox incidents.
- A31 + item 33: per-entity $derived must not call provider methods that
read global state — lift to single provider $derived, per-entity
derivations pointer-compare. Ref: Command (2026-04-17), Listbox
rovingTarget.
- A32 + items 34–35: present comparison table in conversation before
declaring done. Every ❌/⚠️ gets an explicit decision (implement /
defer to v2 / drop); deferred features become their own README section.
- A33 + item 36: reactive collections use SvelteMap / SvelteSet from
svelte/reactivity — $state(new Map()) only tracks field reassignment,
not per-entry .set/.get/.has reads inside $derived.
Reactivity audits + fixes:
- VirtualList sizeCache → SvelteMap (dynamic heights were silently stuck).
- Form touched + registry → SvelteMap (isTouched / isDirty / onBlur
validation $derived never re-ran with plain Map).
- Combobox labelRegistry → SvelteMap (removed clone-and-reassign
workaround, O(N)→O(1) per registration).
Other fixes this pass:
- ColorField/ColorPicker RGB co-increment bug (HSV round-trip was lossy).
- 24 state_referenced_locally warnings swept across date/time/color
field+picker wrappers (removed `void X;` placeholders that Svelte 5
flagged, added svelte-ignore for intentional mount-time reads).
- AlertDialog Content wrapper forces escapeKeydownBehavior=close
(overrides Dialog's alertdialog→ignore default → matches WAI-ARIA).
- Breadcrumb Ellipsis interactive prop renders <button aria-haspopup>
so DropdownMenu composition works without manual trigger plumbing.
- VirtualList Viewport drops `contain: strict` (was breaking programmatic
scrollTo in some engines).
- Memory entries: feedback_id_effect_assign_directly,
feedback_scope_approval, feedback_svelte_reactivity_collections.
Sium library (delegated session, landed in tree):
- Core schema + primitives + combinators + pipe + refines + modifiers.
- Langs module with idlangref resolver.
- Svelte form adapter.
- Protocol docs + status ledger for Codex coordination.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
tabindex: this.isActive ? 0 : -1,
|
|
|
|
|
'data-state': this.isActive ? 'active' : 'inactive',
|
|
|
|
|
'data-index': this.opts.index.current,
|
|
|
|
|
onclick: this.onclick
|
|
|
|
|
} as const)
|
|
|
|
|
);
|
|
|
|
|
}
|