diff --git a/src/uix/eidos/components/date-picker/date-picker-cancel.svelte b/src/uix/eidos/components/date-picker/date-picker-cancel.svelte deleted file mode 100644 index 8d0853bab..000000000 --- a/src/uix/eidos/components/date-picker/date-picker-cancel.svelte +++ /dev/null @@ -1,38 +0,0 @@ - - - diff --git a/src/uix/eidos/components/date-picker/date-picker-clear.svelte b/src/uix/eidos/components/date-picker/date-picker-clear.svelte deleted file mode 100644 index 88c29dd26..000000000 --- a/src/uix/eidos/components/date-picker/date-picker-clear.svelte +++ /dev/null @@ -1,38 +0,0 @@ - - - diff --git a/src/uix/eidos/components/date-picker/date-picker-close.svelte b/src/uix/eidos/components/date-picker/date-picker-close.svelte deleted file mode 100644 index bd6345769..000000000 --- a/src/uix/eidos/components/date-picker/date-picker-close.svelte +++ /dev/null @@ -1,42 +0,0 @@ - - - diff --git a/src/uix/eidos/components/date-picker/date-picker-footer.svelte b/src/uix/eidos/components/date-picker/date-picker-footer.svelte deleted file mode 100644 index 5116662ab..000000000 --- a/src/uix/eidos/components/date-picker/date-picker-footer.svelte +++ /dev/null @@ -1,26 +0,0 @@ - - -
- {@render children?.()} -
diff --git a/src/uix/eidos/components/date-picker/date-picker.css b/src/uix/eidos/components/date-picker/date-picker.css index 6c0785c98..0773594f6 100644 --- a/src/uix/eidos/components/date-picker/date-picker.css +++ b/src/uix/eidos/components/date-picker/date-picker.css @@ -185,63 +185,6 @@ border-color: transparent; } -/* ── Footer (Clear / Cancel / Close action row) ──────────────────────────── */ - -[data-date-picker-footer] { - display: flex; - align-items: center; - gap: var(--space-2); - padding-block-start: var(--space-3); - margin-block-start: var(--space-3); - border-block-start: var(--border-width) solid var(--color-border-subtle); -} - -[data-date-picker-clear], -[data-date-picker-cancel] { - margin-inline-end: auto; -} - -[data-date-picker-clear], -[data-date-picker-cancel], -[data-date-picker-close] { - inline-size: max-content; - min-block-size: var(--control-height-sm); - padding-inline: var(--space-3); - border-radius: var(--radius-md); - border: var(--border-width) solid transparent; - background: transparent; - color: var(--color-content-primary); - font: inherit; - font-size: var(--font-size-sm); - line-height: var(--leading-ui); - cursor: pointer; - transition: - background var(--duration-fast) var(--ease-default), - border-color var(--duration-fast) var(--ease-default), - color var(--duration-fast) var(--ease-default); -} - -[data-date-picker-clear]:hover, -[data-date-picker-cancel]:hover { - background: var(--color-surface-overlay); -} - -[data-date-picker-close] { - border-color: var(--color-primary-border); - background: var(--color-primary-solid); - color: var(--color-content-on-solid); -} - -[data-date-picker-close]:hover { - background: var(--color-primary-solid-hover); -} - -[data-date-picker-clear]:focus-visible, -[data-date-picker-cancel]:focus-visible, -[data-date-picker-close]:focus-visible { - outline: var(--focus-ring-width) solid var(--color-primary-border); - outline-offset: var(--focus-ring-offset); -} /* ── Year-view + Month-view (kind='year' / 'month') ──────────────────────── */ @@ -333,11 +276,6 @@ [data-date-picker-trigger] { transition: none; } - [data-date-picker-clear], - [data-date-picker-cancel], - [data-date-picker-close] { - transition: none; - } [data-date-picker-year-view-cell], [data-date-picker-month-view-cell] { transition: none; diff --git a/src/uix/eidos/components/date-picker/index.ts b/src/uix/eidos/components/date-picker/index.ts index 4a55489e1..d047cbd30 100644 --- a/src/uix/eidos/components/date-picker/index.ts +++ b/src/uix/eidos/components/date-picker/index.ts @@ -2,10 +2,14 @@ import DatePickerComponent from './date-picker.svelte'; import Trigger from './date-picker-trigger.svelte'; import Content from './date-picker-content.svelte'; import Calendar from './date-picker-calendar.svelte'; -import Footer from './date-picker-footer.svelte'; -import Clear from './date-picker-clear.svelte'; -import Cancel from './date-picker-cancel.svelte'; -import Close from './date-picker-close.svelte'; +// PickerShell parts — shared by every composite picker. Re-exported +// under the DatePicker namespace so `` keeps working. The shell parts read `commit/cancel/clear` +// off the picker via `pickerShellContext`. +import Footer from '../picker-shell/picker-shell-footer.svelte'; +import Clear from '../picker-shell/picker-shell-clear.svelte'; +import Cancel from '../picker-shell/picker-shell-cancel.svelte'; +import Close from '../picker-shell/picker-shell-close.svelte'; import YearView from './date-picker-year-view.svelte'; import MonthView from './date-picker-month-view.svelte'; import Label from '../date-field/date-field-label.svelte'; diff --git a/src/uix/eidos/components/date-picker/types.ts b/src/uix/eidos/components/date-picker/types.ts index 144b2d8dc..8f7fe3fe8 100644 --- a/src/uix/eidos/components/date-picker/types.ts +++ b/src/uix/eidos/components/date-picker/types.ts @@ -2,7 +2,6 @@ import type { ArrowProps as SomaDatePickerArrowProps, CalendarProps as SomaDatePickerCalendarProps, CalendarSnippetProps as DatePickerCalendarSnippetProps, - CloseProps as SomaDatePickerCloseProps, InputProps as SomaDatePickerInputProps, InputSnippetProps as DatePickerInputSnippetProps, LabelProps as SomaDatePickerLabelProps, @@ -10,6 +9,12 @@ import type { SegmentProps as SomaDatePickerSegmentProps, TriggerProps as SomaDatePickerTriggerProps } from '$soma/components/date-picker'; +import type { + FooterProps as PickerShellFooterProps, + ClearProps as PickerShellClearProps, + CancelProps as PickerShellCancelProps, + CloseProps as PickerShellCloseProps +} from '../picker-shell'; import type { PopoverAnchorProps, PopoverContentProps, @@ -78,7 +83,12 @@ export type DatePickerHiddenInputProps = Record; export type DatePickerAnchorProps = PopoverAnchorProps; export type DatePickerOverlayProps = PopoverOverlayProps; export type DatePickerArrowProps = SomaDatePickerArrowProps; -export type DatePickerCloseProps = SomaDatePickerCloseProps; + +// PickerShell action-row props. +export type DatePickerFooterProps = PickerShellFooterProps; +export type DatePickerClearProps = PickerShellClearProps; +export type DatePickerCancelProps = PickerShellCancelProps; +export type DatePickerCloseProps = PickerShellCloseProps; export type DatePickerHeaderProps = EidosCalendarHeaderProps; export type DatePickerHeadingProps = EidosCalendarHeadingProps; diff --git a/src/uix/eidos/components/date-range-picker/date-range-picker-cancel.svelte b/src/uix/eidos/components/date-range-picker/date-range-picker-cancel.svelte deleted file mode 100644 index 854c828c6..000000000 --- a/src/uix/eidos/components/date-range-picker/date-range-picker-cancel.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - - diff --git a/src/uix/eidos/components/date-range-picker/date-range-picker-clear.svelte b/src/uix/eidos/components/date-range-picker/date-range-picker-clear.svelte deleted file mode 100644 index f44831922..000000000 --- a/src/uix/eidos/components/date-range-picker/date-range-picker-clear.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - - diff --git a/src/uix/eidos/components/date-range-picker/date-range-picker-close.svelte b/src/uix/eidos/components/date-range-picker/date-range-picker-close.svelte deleted file mode 100644 index e2ccfc744..000000000 --- a/src/uix/eidos/components/date-range-picker/date-range-picker-close.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - - diff --git a/src/uix/eidos/components/date-range-picker/date-range-picker-footer.svelte b/src/uix/eidos/components/date-range-picker/date-range-picker-footer.svelte deleted file mode 100644 index f99585302..000000000 --- a/src/uix/eidos/components/date-range-picker/date-range-picker-footer.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - -
- {@render children?.()} -
diff --git a/src/uix/eidos/components/date-range-picker/date-range-picker.css b/src/uix/eidos/components/date-range-picker/date-range-picker.css index e02cfa4f2..7e07ce22d 100644 --- a/src/uix/eidos/components/date-range-picker/date-range-picker.css +++ b/src/uix/eidos/components/date-range-picker/date-range-picker.css @@ -933,63 +933,6 @@ outline-offset: var(--focus-ring-offset); } -/* ── Footer (Clear / Cancel / Close action row) ──────────────────────────── */ - -[data-date-range-picker-footer] { - display: flex; - align-items: center; - gap: var(--space-2); - padding-block-start: var(--space-3); - margin-block-start: var(--space-3); - border-block-start: var(--border-width) solid var(--color-border-subtle); -} - -[data-date-range-picker-clear], -[data-date-range-picker-cancel] { - margin-inline-end: auto; -} - -[data-date-range-picker-clear], -[data-date-range-picker-cancel], -[data-date-range-picker-close] { - inline-size: max-content; - min-block-size: var(--control-height-sm); - padding-inline: var(--space-3); - border-radius: var(--radius-md); - border: var(--border-width) solid transparent; - background: transparent; - color: var(--color-content-primary); - font: inherit; - font-size: var(--font-size-sm); - line-height: var(--leading-ui); - cursor: pointer; - transition: - background var(--duration-fast) var(--ease-default), - border-color var(--duration-fast) var(--ease-default), - color var(--duration-fast) var(--ease-default); -} - -[data-date-range-picker-clear]:hover, -[data-date-range-picker-cancel]:hover { - background: var(--color-surface-overlay); -} - -[data-date-range-picker-close] { - border-color: var(--color-primary-border); - background: var(--color-primary-solid); - color: var(--color-content-on-solid); -} - -[data-date-range-picker-close]:hover { - background: var(--color-primary-solid-hover); -} - -[data-date-range-picker-clear]:focus-visible, -[data-date-range-picker-cancel]:focus-visible, -[data-date-range-picker-close]:focus-visible { - outline: var(--focus-ring-width) solid var(--color-primary-border); - outline-offset: var(--focus-ring-offset); -} @media (prefers-reduced-motion: reduce) { [data-date-range-picker-trigger], @@ -999,10 +942,7 @@ [data-range-calendar-next-button], [data-range-calendar-month-select], [data-range-calendar-year-select], - [data-range-calendar-day], - [data-date-range-picker-clear], - [data-date-range-picker-cancel], - [data-date-range-picker-close] { + [data-range-calendar-day] { transition: none; } } diff --git a/src/uix/eidos/components/date-range-picker/index.ts b/src/uix/eidos/components/date-range-picker/index.ts index d1447437e..b21631fdb 100644 --- a/src/uix/eidos/components/date-range-picker/index.ts +++ b/src/uix/eidos/components/date-range-picker/index.ts @@ -8,12 +8,13 @@ import Segment from './date-range-picker-segment.svelte'; import Anchor from '../popover/popover-anchor.svelte'; import Overlay from '../popover/popover-overlay.svelte'; import Arrow from '../popover/popover-arrow.svelte'; -import Close from './date-range-picker-close.svelte'; -import Footer from './date-range-picker-footer.svelte'; +// PickerShell parts — shared by every composite picker. +import Footer from '../picker-shell/picker-shell-footer.svelte'; +import Clear from '../picker-shell/picker-shell-clear.svelte'; +import Cancel from '../picker-shell/picker-shell-cancel.svelte'; +import Close from '../picker-shell/picker-shell-close.svelte'; import YearView from './date-range-picker-year-view.svelte'; import MonthView from './date-range-picker-month-view.svelte'; -import Clear from './date-range-picker-clear.svelte'; -import Cancel from './date-range-picker-cancel.svelte'; import Header from './date-range-picker-header.svelte'; import Heading from './date-range-picker-heading.svelte'; import PrevButton from './date-range-picker-prev-button.svelte'; diff --git a/src/uix/eidos/components/date-range-picker/types.ts b/src/uix/eidos/components/date-range-picker/types.ts index 3a5eb0462..2b2702145 100644 --- a/src/uix/eidos/components/date-range-picker/types.ts +++ b/src/uix/eidos/components/date-range-picker/types.ts @@ -2,7 +2,6 @@ import type { ArrowProps as SomaDateRangePickerArrowProps, CalendarProps as SomaDateRangePickerCalendarProps, CalendarSnippetProps as SomaDateRangePickerCalendarSnippetProps, - CloseProps as SomaDateRangePickerCloseProps, GridBodyProps as SomaDateRangePickerGridBodyProps, GridHeadProps as SomaDateRangePickerGridHeadProps, GridProps as SomaDateRangePickerGridProps, @@ -76,7 +75,14 @@ export type DateRangePickerSegmentProps = SomaDateRangePickerSegmentProps; export type DateRangePickerAnchorProps = PopoverAnchorProps; export type DateRangePickerOverlayProps = PopoverOverlayProps; export type DateRangePickerArrowProps = SomaDateRangePickerArrowProps; -export type DateRangePickerCloseProps = SomaDateRangePickerCloseProps; + +// PickerShell action-row props — Footer/Clear/Cancel/Close are shared. +export type { + FooterProps as DateRangePickerFooterProps, + ClearProps as DateRangePickerClearProps, + CancelProps as DateRangePickerCancelProps, + CloseProps as DateRangePickerCloseProps +} from '../picker-shell'; export type DateRangePickerHeaderProps = SomaDateRangePickerHeaderProps; export type DateRangePickerHeadingProps = SomaDateRangePickerHeadingProps; diff --git a/src/uix/eidos/components/time-picker/index.ts b/src/uix/eidos/components/time-picker/index.ts index b5a1f117f..d94c22e44 100644 --- a/src/uix/eidos/components/time-picker/index.ts +++ b/src/uix/eidos/components/time-picker/index.ts @@ -2,10 +2,11 @@ import TimePickerComponent from './time-picker.svelte' import Trigger from './time-picker-trigger.svelte' import Content from './time-picker-content.svelte' import Clock from './time-picker-clock.svelte' -import Footer from './time-picker-footer.svelte' -import Clear from './time-picker-clear.svelte' -import Cancel from './time-picker-cancel.svelte' -import Close from './time-picker-close.svelte' +// PickerShell parts — shared by every composite picker. +import Footer from '../picker-shell/picker-shell-footer.svelte' +import Clear from '../picker-shell/picker-shell-clear.svelte' +import Cancel from '../picker-shell/picker-shell-cancel.svelte' +import Close from '../picker-shell/picker-shell-close.svelte' import HourSlider from './time-picker-hour-slider.svelte' import MinuteSlider from './time-picker-minute-slider.svelte' import SecondSlider from './time-picker-second-slider.svelte' diff --git a/src/uix/eidos/components/time-picker/time-picker-cancel.svelte b/src/uix/eidos/components/time-picker/time-picker-cancel.svelte deleted file mode 100644 index 6fcd4a20c..000000000 --- a/src/uix/eidos/components/time-picker/time-picker-cancel.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - - diff --git a/src/uix/eidos/components/time-picker/time-picker-clear.svelte b/src/uix/eidos/components/time-picker/time-picker-clear.svelte deleted file mode 100644 index 19d021c08..000000000 --- a/src/uix/eidos/components/time-picker/time-picker-clear.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - - diff --git a/src/uix/eidos/components/time-picker/time-picker-close.svelte b/src/uix/eidos/components/time-picker/time-picker-close.svelte deleted file mode 100644 index b50431f19..000000000 --- a/src/uix/eidos/components/time-picker/time-picker-close.svelte +++ /dev/null @@ -1,37 +0,0 @@ - - - diff --git a/src/uix/eidos/components/time-picker/time-picker-footer.svelte b/src/uix/eidos/components/time-picker/time-picker-footer.svelte deleted file mode 100644 index 13ef5e13e..000000000 --- a/src/uix/eidos/components/time-picker/time-picker-footer.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
- {@render children?.()} -
diff --git a/src/uix/eidos/components/time-picker/time-picker.css b/src/uix/eidos/components/time-picker/time-picker.css index 4d3212edd..650341a60 100644 --- a/src/uix/eidos/components/time-picker/time-picker.css +++ b/src/uix/eidos/components/time-picker/time-picker.css @@ -246,69 +246,9 @@ background: var(--_time-field-accent-border); } -/* ── Footer (Clear / Cancel / Close action row) ──────────────────────────── */ - -[data-time-picker-footer] { - display: flex; - align-items: center; - gap: var(--space-2); - padding-block-start: var(--space-3); - margin-block-start: var(--space-3); - border-block-start: var(--border-width) solid var(--color-border-subtle); -} - -[data-time-picker-clear], -[data-time-picker-cancel] { - margin-inline-end: auto; -} - -[data-time-picker-clear], -[data-time-picker-cancel], -[data-time-picker-close] { - inline-size: max-content; - min-block-size: var(--control-height-sm); - padding-inline: var(--space-3); - border-radius: var(--radius-md); - border: var(--border-width) solid transparent; - background: transparent; - color: var(--color-content-primary); - font: inherit; - font-size: var(--font-size-sm); - line-height: var(--leading-ui); - cursor: pointer; - transition: - background var(--duration-fast) var(--ease-default), - border-color var(--duration-fast) var(--ease-default), - color var(--duration-fast) var(--ease-default); -} - -[data-time-picker-clear]:hover, -[data-time-picker-cancel]:hover { - background: var(--color-surface-overlay); -} - -[data-time-picker-close] { - border-color: var(--color-primary-border); - background: var(--color-primary-solid); - color: var(--color-content-on-solid); -} - -[data-time-picker-close]:hover { - background: var(--color-primary-solid-hover); -} - -[data-time-picker-clear]:focus-visible, -[data-time-picker-cancel]:focus-visible, -[data-time-picker-close]:focus-visible { - outline: var(--focus-ring-width) solid var(--color-primary-border); - outline-offset: var(--focus-ring-offset); -} @media (prefers-reduced-motion: reduce) { - [data-time-picker-trigger], - [data-time-picker-clear], - [data-time-picker-cancel], - [data-time-picker-close] { + [data-time-picker-trigger] { transition: none; } } diff --git a/src/uix/eidos/components/time-picker/types.ts b/src/uix/eidos/components/time-picker/types.ts index a6cb97660..a98d0c145 100644 --- a/src/uix/eidos/components/time-picker/types.ts +++ b/src/uix/eidos/components/time-picker/types.ts @@ -20,7 +20,6 @@ import type { } from '../popover/types' import type { ColorRole, ControlVariant, ResponsiveProp, Size } from '$uix/eidos/lib/types' import type { Snippet } from 'svelte' -import type { HTMLButtonAttributes } from 'svelte/elements' export type TimePickerSize = Extract export type TimePickerVariant = ControlVariant @@ -60,24 +59,13 @@ export type TimePickerClockProps = { children?: Snippet } -export type TimePickerFooterProps = { - id?: string - class?: string - style?: string - children?: Snippet -} - -export type TimePickerClearProps = HTMLButtonAttributes & { - children?: Snippet -} - -export type TimePickerCancelProps = HTMLButtonAttributes & { - children?: Snippet -} - -export type TimePickerCloseProps = HTMLButtonAttributes & { - children?: Snippet -} +// PickerShell action-row props — Footer/Clear/Cancel/Close are shared. +export type { + FooterProps as TimePickerFooterProps, + ClearProps as TimePickerClearProps, + CancelProps as TimePickerCancelProps, + CloseProps as TimePickerCloseProps +} from '../picker-shell' export type TimePickerLabelProps = SomaTimePickerLabelProps export type TimePickerInputProps = SomaTimePickerInputProps diff --git a/src/uix/morfo/components/date-picker.ts b/src/uix/morfo/components/date-picker.ts index 461c86da6..5a53c1555 100644 --- a/src/uix/morfo/components/date-picker.ts +++ b/src/uix/morfo/components/date-picker.ts @@ -231,78 +231,11 @@ export const datePickerMorfo = { { key: 'Tab', action: 'focus-next' }, { key: 'Shift+Tab', action: 'focus-prev' } ] - }, - { - // Optional footer rendered inside the Calendar. Visibility is owned - // by the consumer (`clearButton`/`cancelButton`/`closeButton` props - // on the root). In `mode='modal'` the Close affordance is forced on. - name: 'Footer', - kebab: 'footer', - archetype: 'footer', - kind: 'public', - defaultElement: 'div', - optional: true, - data: [{ attr: 'data-mode', values: ['inline', 'modal'], severity: 'optional' }], - aria: [] - }, - { - // Clear action — resets value to undefined, keeps the popover open. - name: 'Clear', - kebab: 'clear', - archetype: 'trigger', - kind: 'public', - defaultElement: 'button', - role: 'button', - optional: true, - data: [{ attr: 'data-action', value: v.literal('clear') }], - aria: [ - { attr: 'type', value: v.literal('button') }, - { - attr: 'aria-label', - value: v.translationRef('#?components.date-picker.clear|Clear date'), - severity: 'recommended' - } - ] - }, - { - // Cancel action — reverts to the value snapshot taken on open, closes. - name: 'Cancel', - kebab: 'cancel', - archetype: 'trigger', - kind: 'public', - defaultElement: 'button', - role: 'button', - optional: true, - data: [{ attr: 'data-action', value: v.literal('cancel') }], - aria: [ - { attr: 'type', value: v.literal('button') }, - { - attr: 'aria-label', - value: v.translationRef('#?components.date-picker.cancel|Cancel'), - severity: 'recommended' - } - ] - }, - { - // Close / Save action — commits current value and closes. In modal - // mode this is the only affordance to exit (outside-click + Escape - // are intentionally blocked). - name: 'Close', - kebab: 'close', - archetype: 'trigger', - kind: 'public', - defaultElement: 'button', - role: 'button', - optional: true, - data: [{ attr: 'data-action', value: v.literal('close') }], - aria: [ - { attr: 'type', value: v.literal('button') }, - { - attr: 'aria-label', - value: v.translationRef('#?components.date-picker.close|Close'), - severity: 'recommended' - } - ] } + // Footer / Clear / Cancel / Close — declared by the shared + // `picker-shell` (Eidos ``). + // Their data-attrs are `[data-picker-footer/clear/cancel/close]` + // (no per-picker prefix). The audit / runtime won't find them in + // this morfo because they're chrome shared across pickers. ] } as const satisfies Morfo; diff --git a/src/uix/morfo/components/date-range-picker.ts b/src/uix/morfo/components/date-range-picker.ts index cb802db9b..5de58498d 100644 --- a/src/uix/morfo/components/date-range-picker.ts +++ b/src/uix/morfo/components/date-range-picker.ts @@ -237,78 +237,9 @@ export const dateRangePickerMorfo = { { key: 'Tab', action: 'focus-next' }, { key: 'Shift+Tab', action: 'focus-prev' } ] - }, - { - // Optional footer rendered inside the Calendar. Visibility is owned - // by the consumer (`clearButton`/`cancelButton`/`closeButton` props - // on the root). In `mode='modal'` the Close affordance is forced on. - name: 'Footer', - kebab: 'footer', - archetype: 'footer', - kind: 'public', - defaultElement: 'div', - optional: true, - data: [{ attr: 'data-mode', values: ['inline', 'modal'], severity: 'optional' }], - aria: [] - }, - { - // Clear action — resets value to an empty range, keeps the popover open. - name: 'Clear', - kebab: 'clear', - archetype: 'trigger', - kind: 'public', - defaultElement: 'button', - role: 'button', - optional: true, - data: [{ attr: 'data-action', value: v.literal('clear') }], - aria: [ - { attr: 'type', value: v.literal('button') }, - { - attr: 'aria-label', - value: v.translationRef('#?components.date-range-picker.clear|Clear range'), - severity: 'recommended' - } - ] - }, - { - // Cancel action — reverts to the value snapshot taken on open, closes. - name: 'Cancel', - kebab: 'cancel', - archetype: 'trigger', - kind: 'public', - defaultElement: 'button', - role: 'button', - optional: true, - data: [{ attr: 'data-action', value: v.literal('cancel') }], - aria: [ - { attr: 'type', value: v.literal('button') }, - { - attr: 'aria-label', - value: v.translationRef('#?components.date-range-picker.cancel|Cancel'), - severity: 'recommended' - } - ] - }, - { - // Close / Save action — commits current value and closes. In modal - // mode this is the only affordance to exit (outside-click + Escape - // are intentionally blocked). - name: 'Close', - kebab: 'close', - archetype: 'trigger', - kind: 'public', - defaultElement: 'button', - role: 'button', - optional: true, - data: [{ attr: 'data-action', value: v.literal('close') }], - aria: [ - { attr: 'type', value: v.literal('button') }, - { - attr: 'aria-label', - value: v.translationRef('#?components.date-range-picker.close|Close'), - severity: 'recommended' - } - ] } + // Footer / Clear / Cancel / Close — chrome shared via picker-shell; + // not declared here. Eidos `` re-exports the `` parts. ] } as const satisfies Morfo; diff --git a/src/uix/morfo/components/time-picker.ts b/src/uix/morfo/components/time-picker.ts index 60d424c46..dfe307f1c 100644 --- a/src/uix/morfo/components/time-picker.ts +++ b/src/uix/morfo/components/time-picker.ts @@ -308,70 +308,9 @@ export const timePickerMorfo = { optional: true, data: [{ attr: 'data-checked', severity: 'optional' }], aria: [] - }, - { - name: 'Footer', - kebab: 'footer', - archetype: 'footer', - kind: 'public', - defaultElement: 'div', - optional: true, - data: [{ attr: 'data-mode', values: ['inline', 'modal'], severity: 'optional' }], - aria: [] - }, - { - name: 'Clear', - kebab: 'clear', - archetype: 'trigger', - kind: 'public', - defaultElement: 'button', - role: 'button', - optional: true, - data: [{ attr: 'data-action', value: v.literal('clear') }], - aria: [ - { attr: 'type', value: v.literal('button') }, - { - attr: 'aria-label', - value: v.translationRef('#?components.time-picker.clear|Clear time'), - severity: 'recommended' - } - ] - }, - { - name: 'Cancel', - kebab: 'cancel', - archetype: 'trigger', - kind: 'public', - defaultElement: 'button', - role: 'button', - optional: true, - data: [{ attr: 'data-action', value: v.literal('cancel') }], - aria: [ - { attr: 'type', value: v.literal('button') }, - { - attr: 'aria-label', - value: v.translationRef('#?components.time-picker.cancel|Cancel'), - severity: 'recommended' - } - ] - }, - { - name: 'Close', - kebab: 'close', - archetype: 'trigger', - kind: 'public', - defaultElement: 'button', - role: 'button', - optional: true, - data: [{ attr: 'data-action', value: v.literal('close') }], - aria: [ - { attr: 'type', value: v.literal('button') }, - { - attr: 'aria-label', - value: v.translationRef('#?components.time-picker.close|Close'), - severity: 'recommended' - } - ] } + // Footer / Clear / Cancel / Close — chrome shared via picker-shell; + // not declared here. Eidos `` + // re-exports the `` parts. ] } as const satisfies Morfo; diff --git a/src/uix/soma/components/date-picker/date-picker-provider.svelte.ts b/src/uix/soma/components/date-picker/date-picker-provider.svelte.ts index 500af79d7..d5dcea3ed 100644 --- a/src/uix/soma/components/date-picker/date-picker-provider.svelte.ts +++ b/src/uix/soma/components/date-picker/date-picker-provider.svelte.ts @@ -7,6 +7,10 @@ import { type ActiveProps, type StateProps } from '$libs/reactive'; import type { OnChangeFn, Direction } from '../../types'; import { Soma } from '../../core/soma.svelte'; import { isBefore } from '$libs/days'; +import { + pickerShellContext, + type PickerShellHandle +} from '../picker-shell'; import type { DateValue, DateMatcher, @@ -160,8 +164,19 @@ export class DatePickerProvider { } } ); + + // Expose our commit/cancel/clear/mode handle to descendant Eidos + // PickerShell parts (``, ``, etc.). + pickerShellContext.set(this.pickerShellHandle); } + readonly pickerShellHandle: PickerShellHandle = { + getMode: () => this.opts.mode.current, + commit: () => this.commit(), + cancel: () => this.cancel(), + clear: () => this.clear() + }; + readonly validationStatus = $derived.by(() => { const value = this.opts.value.current; if (!value) return false as const; diff --git a/src/uix/soma/components/date-range-picker/date-range-picker-provider.svelte.ts b/src/uix/soma/components/date-range-picker/date-range-picker-provider.svelte.ts index b7869165d..c178e4871 100644 --- a/src/uix/soma/components/date-range-picker/date-range-picker-provider.svelte.ts +++ b/src/uix/soma/components/date-range-picker/date-range-picker-provider.svelte.ts @@ -7,6 +7,10 @@ import { type ActiveProps, type StateProps } from '$libs/reactive'; import type { OnChangeFn, Direction } from '../../types'; import { Soma } from '../../core/soma.svelte'; import { getLocalTimeZone, isBefore } from '$libs/days'; +import { + pickerShellContext, + type PickerShellHandle +} from '../picker-shell'; /** * Picker interaction mode. `inline` (default) auto-closes the popover when @@ -150,8 +154,19 @@ export class DateRangePickerProvider { } } ); + + // Expose our commit/cancel/clear/mode handle to descendant Eidos + // PickerShell parts (``, etc.). + pickerShellContext.set(this.pickerShellHandle); } + readonly pickerShellHandle: PickerShellHandle = { + getMode: () => this.opts.mode.current, + commit: () => this.commit(), + cancel: () => this.cancel(), + clear: () => this.clear() + }; + readonly validationStatus = $derived.by(() => { const value = this.opts.value.current; const start = value.start; diff --git a/src/uix/soma/components/time-picker/time-picker-provider.svelte.ts b/src/uix/soma/components/time-picker/time-picker-provider.svelte.ts index c4e150e2a..23f8f1132 100644 --- a/src/uix/soma/components/time-picker/time-picker-provider.svelte.ts +++ b/src/uix/soma/components/time-picker/time-picker-provider.svelte.ts @@ -17,6 +17,10 @@ import type { import { timePickerMorfo } from '../../../morfo/components/time-picker'; import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte'; +import { + pickerShellContext, + type PickerShellHandle +} from '../picker-shell'; const attrs = createAttrs(timePickerMorfo); @@ -109,8 +113,19 @@ export class TimePickerProvider { } } ); + + // Expose our commit/cancel/clear/mode handle to descendant Eidos + // PickerShell parts (``, ``, etc.). + pickerShellContext.set(this.pickerShellHandle); } + readonly pickerShellHandle: PickerShellHandle = { + getMode: () => this.opts.mode.current, + commit: () => this.commit(), + cancel: () => this.cancel(), + clear: () => this.clear() + }; + /** Resolved hour cycle — same rule as TimeField: explicit → service → locale. */ readonly resolvedHourCycle: HourCycle = $derived.by(() => { const explicit = this.opts.hourCycle.current;