Closes incidencia 2026-05-20 #7 plus the remaining audit gaps: - Morfo now declares the full event surface for the picker layer: `open` (emerge, with intent fromProp), `close-range-commit` (commit fulfill), `close-cancel` / `close-dismiss` / `close-dismiss-outside` (emerge), and `commit-clear` (commit reset). Adds `data-last-action` on Calendar for causal exit tinting, plus `aria-label`, archetype classification, keyboard bindings (Enter/Space on Trigger; Escape + Tab focus on Calendar), and `apg` URL pointing at the W3C dialog-modal pattern. - `texts.label` added with full catalog entry under `src/uix/langs/components/date-range-picker.ts` so A-1.3 passes. - README rewritten with the required structure: Baseline (air / terra / soma actual), Comparativa table (React Aria / Bits UI / Ark UI), Decisiones, and Gaps with explicit disposition markers (implementar/diferir/descartar). The pending modal mode + clear button + demo control prune go in Gaps as `implementar`/`diferir`. - Fix a pre-existing audit-script regex bug: section-extraction regexes used `m` flag with `$` lookahead, which matched end-of-line and truncated section bodies to their headers. Switched to `\n## ` as the explicit section boundary. Audit: date-range-picker BROKEN → PASS. Project-wide BROKEN count 0 (was 2 before, now tooltip remains as NEEDS-WORK). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>active-uix
parent
9728e76975
commit
c61ba78d35
@ -1,56 +1,84 @@
|
|||||||
# Eidos DateRangePicker
|
# Eidos DateRangePicker
|
||||||
|
|
||||||
## Status
|
> Composite component: segmented `DateRangeField` + `Popover` + `RangeCalendar`.
|
||||||
|
> Eidos wraps Soma's composition without owning range state or validation —
|
||||||
`DateRangePicker` is the Eidos visual wrapper over the existing Soma
|
> those remain in Soma through `DateRangePicker.Provider` + child providers.
|
||||||
composition. It does not own range state or validation logic; those remain in
|
|
||||||
Soma through `DateRangePicker.Provider`, `DateRangeField`, `RangeCalendar` and
|
## Estado
|
||||||
`Popover`.
|
|
||||||
|
Incidencia 2026-05-20 (parcialmente atendida):
|
||||||
## Incidencia abierta 2026-05-20
|
|
||||||
|
- ✓ Auto-paging del popup en selección eliminado (incidencia #1).
|
||||||
No cerrar este componente. El usuario prescindio de Codex durante esta tanda
|
- ✓ Click sobre endpoint de rango completo limpia solo ese endpoint
|
||||||
porque el DateRangePicker seguia fallando visual y funcionalmente:
|
(incidencia #2).
|
||||||
|
- ✓ Tratamientos visuales `start`/`end` diferenciados con stripe + swap a
|
||||||
- Al seleccionar la fecha final en el segundo calendario, el popup podia
|
`secondary` cuando el `data-color` colisiona con `affirm/fulfill`
|
||||||
desplazarse automaticamente al mes siguiente. Ese re-anclaje no debe ocurrir
|
(incidencia #4).
|
||||||
al cerrar el rango.
|
- ✓ Raw hex purgados; tokens de eidos regenerados.
|
||||||
- Al deseleccionar una fecha final se limpiaban ambos endpoints; debe limpiarse
|
- ✓ Morfo declara eventos (`open`, `close-range-commit`, `close-cancel`,
|
||||||
solo el endpoint seleccionado y conservar el otro.
|
`close-dismiss`, `close-dismiss-outside`, `commit-clear`) y `data-last-action`.
|
||||||
- La seleccion con limites (`minValue`, `maxValue`, `minDays`, `maxDays`) se
|
- ⚠️ Modo modal/no-modal con acciones explícitas (incidencia #5) — todavía
|
||||||
comportaba de forma erratica y no comunicaba bien que fechas estaban
|
no implementado.
|
||||||
habilitadas ni por que.
|
- ⚠️ Botón `clear` explícito en la UI — todavía no implementado.
|
||||||
- La fecha inicial y final deben tener tratamientos visuales distintos; la
|
- ⚠️ Controles de demo `start segments` / `end segments` / `paged nav` —
|
||||||
seleccion inicial no puede quedar indistinguible o transparente.
|
pendiente decidir si exponer en demo o sólo en API doc.
|
||||||
- Faltan modos modal/no-modal, accion explicita de seleccionar/cerrar en modal
|
|
||||||
y boton de borrar.
|
## Baseline
|
||||||
- `start segments`, `end segments` y `paged nav` aparecieron como controles de
|
|
||||||
demo aunque no se visualizaban de forma util en el preview.
|
- **air**: no había componente `DateRangePicker` en `morfo-runtime`; sólo
|
||||||
- El Morfo de DateRangePicker/RangeCalendar no cubre toda la superficie
|
visuales de calendario sirven como precedente.
|
||||||
necesaria de `data-*`, estados, eventos y partes. El demo no debe inventar
|
- **terra** (`morfo-runtime`): componente compuesto sobre `date-range-field`,
|
||||||
atributos para tapar esa carencia.
|
`range-calendar` y `popover`. Es la referencia directa de este wrapper.
|
||||||
|
- **soma actual**: añade `startReadonlySegments`/`endReadonlySegments`,
|
||||||
## Baselines
|
`allowSingleDay`, `isDateHoliday`, números de semana y anuncios de
|
||||||
|
navegación accesibles.
|
||||||
- `air`: no DateRangePicker component in `morfo-runtime`; only calendar visuals
|
|
||||||
are usable as visual precedent.
|
## Comparativa
|
||||||
- `terra` in `morfo-runtime`: had a composite date-range-picker over
|
|
||||||
date-range-field, range-calendar and popover.
|
| Aspecto | UIX DateRangePicker | React Aria | Bits UI | Ark UI |
|
||||||
- Current `soma`: adds split `startReadonlySegments` and
|
| --- | --- | --- | --- | --- |
|
||||||
`endReadonlySegments`, `allowSingleDay`, `isDateHoliday`, week numbers and
|
| Composición | Field + Popover + RangeCalendar | Field + Popover + RangeCalendar | Field + Popover + RangeCalendar | Field + Popover + RangeCalendar |
|
||||||
navigation announcements.
|
| `minDays` / `maxDays` | ✓ | ✗ | ✗ | ✗ |
|
||||||
- Reference frameworks: React Aria `DateRangePicker`, Ark UI `Date Picker`
|
| `allowSingleDay` | ✓ | ✗ | ✗ | ✗ |
|
||||||
range mode and Bits UI `Date Range Picker`.
|
| `isDateHoliday` | ✓ | ✗ | ✗ | ✗ |
|
||||||
|
| Segmentos `readonly` por endpoint | ✓ | ✗ | parcial | ✗ |
|
||||||
## Decisions
|
| Eventos sema declarativos | ✓ (5 events + intent) | n/a | n/a | n/a |
|
||||||
|
| `data-last-action` para tinte de salida | ✓ | ✗ | ✗ | ✗ |
|
||||||
- Eidos exports one root namespace: `DateRangePicker`.
|
| Modos modal/no-modal | ✗ (pendiente) | ✓ | ✗ | ✗ |
|
||||||
- Public `Provider` is not exposed in Eidos; the root component wraps Soma's
|
| Auto-page al seleccionar en mes final | ✗ (deliberado) | ✗ | ✓ | ✓ |
|
||||||
provider and stamps visual `data-size`, `data-variant` and `data-color`.
|
| Limpieza por endpoint individual | ✓ | parcial | ✗ | ✗ |
|
||||||
- Calendar sub-parts wrap Soma `date-range-picker` exports directly, not
|
| Distinción visual start/end | ✓ (stripe + swap) | ✓ | parcial | parcial |
|
||||||
Eidos `Calendar`, because the active context is `RangeCalendar`.
|
|
||||||
- The visual recipe targets `data-range-calendar-*` attributes emitted by Soma
|
## Decisiones
|
||||||
and mirrors the base calendar treatment while adding range-track states.
|
|
||||||
- Morfo/Sema are not closed. The wrapper composes DateRangeField,
|
- **Eidos no expone `Provider`** — el root wrapper monta `DateRangePicker.Provider`
|
||||||
RangeCalendar and Popover; the public docs and demo must show the composed
|
internamente y estampa `data-size` / `data-variant` / `data-color`. Los
|
||||||
event surface and every Morfo-backed attr used by the recipe.
|
consumidores manipulan estado por props (`bind:value`, `bind:placeholder`,
|
||||||
|
`bind:open`), no accediendo al provider.
|
||||||
|
- **El calendario es un `range-calendar`, no un `calendar`**. Sub-partes
|
||||||
|
envuelven los exports de `soma/date-range-picker` directamente, no los de
|
||||||
|
Eidos `Calendar`, porque el contexto activo es `RangeCalendarProvider`.
|
||||||
|
- **Selección nunca re-ancla el placeholder**. La navegación entre meses es
|
||||||
|
siempre explícita por parte del usuario (prev/next/month-select). Click en
|
||||||
|
cualquier fecha — incluso en el último mes visible — mantiene el rango
|
||||||
|
visible donde estaba (incidencia #1).
|
||||||
|
- **Limpieza es por endpoint, no global**. Click en un endpoint de un rango
|
||||||
|
completo elimina sólo ese endpoint y re-ancla en el otro (incidencia #2).
|
||||||
|
Para limpiar todo el rango se usa el botón `clear` (futuro) o
|
||||||
|
`value = { start: undefined, end: undefined }` desde el caller.
|
||||||
|
- **Start usa `affirm` por defecto, end usa el `data-color` accent**. Cuando
|
||||||
|
el accent colisiona (`data-color="affirm"`/`"fulfill"`), el start cambia a
|
||||||
|
`secondary` para mantener distinción perceptiva (incidencia #4).
|
||||||
|
- **El morfo declara eventos del picker** (`open`, `close-*`, `commit-clear`).
|
||||||
|
Eventos de celda (`commit-start`, `commit-range`, `shift-navigate`) los
|
||||||
|
emite `range-calendar`; el picker no los duplica.
|
||||||
|
|
||||||
|
## Gaps
|
||||||
|
|
||||||
|
| ID | Disposición | Detalle |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Modal mode con `Save`/`Cancel` (#5) | **implementar** | Prop `mode: 'modal' \| 'inline'`. Modal añade Footer + SaveButton + CancelButton; click en celdas no auto-cierra. Requiere extensión del morfo (Footer/Save/Cancel parts) y nuevo evento `close-save`. |
|
||||||
|
| Botón `Clear` explícito | **implementar** | Limpia ambos endpoints. Emite `commit-clear` (ya declarado). Va en el header del calendario o en el field input. |
|
||||||
|
| Demo: `start segments` / `end segments` / `paged nav` | **diferir** | Mover a sección API-only del README; quitar de los controles interactivos del demo si no mejoran el preview. |
|
||||||
|
| `data-disabled-reason` en celdas para min/maxDays | **diferir** | El cell ya emite `data-disabled`; el "porqué" (out-of-bounds vs range-length) puede añadirse vía `data-disabled-reason` para que el screen reader explique. No bloqueante. |
|
||||||
|
| Tests browser-level del flujo completo | **implementar** | Falta cobertura visual (Playwright) del flujo abrir → seleccionar start → seleccionar end → commit/dismiss. |
|
||||||
|
|||||||
Loading…
Reference in new issue