From 3a23fa239bb52f7dd2b64c390f004541a3c87a38 Mon Sep 17 00:00:00 2001 From: dev Date: Sun, 24 May 2026 23:16:01 +0200 Subject: [PATCH] =?UTF-8?q?docs(pendientes):=20downgrade=20BaseSegmentProv?= =?UTF-8?q?ider=20from=20'diferir'=20to=20'descartar'=20=E2=80=94=20false?= =?UTF-8?q?=20positive?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deep re-analysis of the date-field (291 lines) and time-field (250 lines) abstract bases — claimed by Kim Round 3 as ~300 lines of duplication — shows the duplication is superficial: - ~50 lines structurally identical: constructor, announcer/getMin/ getMax/directionalKeys getters, keydown router skeleton. - ~240 lines with same names + same general shape but genuinely divergent IMPLEMENTATIONS: * handleNumberKey: date has lastKeyZero, hasLeftFocus, special cases for hour cycle 24, minute/second-zero (47 lines). Time uses candidate-based prev*10+num (37 lines). * handleArrowUp/Down: date uses cycleNumericSegment with DateValue.cycle wraparound. Time uses direct arithmetic. * handleBackspace: date has '0X' → null special case. Time doesn't. * formatValue: date has forDisplay flag. Time doesn't. * getAnnouncement exists in date, not in time. * getSegmentProps: date interplays placeholder.set + hour/ dayPeriod intermix. Time is a flat read. Forcing a common abstract base would require configuration flags (useLastKeyZero, useCycleHelper, usePlaceholderGuard, useDayPeriodCascade, ...) that would create a God-Object worse than the current state. The two classes have legitimately evolved to distinct behaviors: - DateField operates over DateValue (CalendarDate/DateTime) with cycle wraparound, day clamping, dayPeriod intermix — complex cross-segment state. - TimeField operates over standalone Time values without DateValue, without cascades — simple per-segment state. Marking the item as **descartar** (discard, not just defer). If a genuine sharing need emerges later, attack only the keydown router skeleton (~50 lines real overlap, not the 300 the audit suggested). Co-Authored-By: Claude Opus 4.7 (1M context) --- src/uix/PENDIENTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uix/PENDIENTES.md b/src/uix/PENDIENTES.md index 1dfc48606..7de31ed5d 100644 --- a/src/uix/PENDIENTES.md +++ b/src/uix/PENDIENTES.md @@ -115,7 +115,7 @@ fantasma. Lo siguiente queda **diferir** hasta sprint de refactor. | Item | Disposición | | --- | --- | | **FloatingShellProvider factory** — el setup `FloatingProvider.create + Presence + FloatingContent.create` está copia-pegado en 15 providers (popover, dropdown-menu, combobox, select, tooltip, context-menu, 5 pickers, link-preview, menubar). Cada uno repite ~40-60 líneas. Total: ~600 líneas duplicadas (18 matches confirmados via grep). | **diferir** — refactor grande de alto valor pero alto riesgo (15 archivos críticos). Sprint propio. | -| **BaseSegmentProvider** (date-field 1674 líneas, time-field 1072 líneas). Ambos tienen `BaseNumericSegmentProvider` / `BaseTimeNumericSegmentProvider` con `updateSegment`, `handleNumberKey`, `handleBackspace`, `handleArrowUp/Down`, `onfocusout` y `SEGMENT_CONFIGS` estructuralmente idénticos. Plus `DayPeriod`, `Literal`, `TimeZone` casi byte-idénticas. ~300 líneas duplicadas. | **diferir** — extraer base abstracta genérica sobre ``. Las firmas divergen un poco (`formatValue` con/sin `forDisplay`, `getAnnouncement` en date no en time) — reconciliarlas requiere decisión cuidadosa. | +| ~~**BaseSegmentProvider** (date-field/time-field)~~ — **falso positivo del audit (re-analizado 2026-05-24)**. Lectura profunda de las 2 bases (date 291 líneas, time 250 líneas) muestra que la "duplicación" es superficial: comparten ~50 líneas estructurales (constructor, getters `announcer/getMin/getMax/directionalKeys`, esqueleto del router de teclas) pero las ~240 líneas restantes (`handleNumberKey`, `handleArrowUp/Down`, `handleBackspace`, `formatValue`, `getSegmentProps`) tienen IMPLEMENTACIONES genuinamente distintas. DateField usa `cycleNumericSegment(DateValue.cycle)` con wraparound + day-clamp + dayPeriod intermix; TimeField usa aritmética directa sin DateValue. Forzar una base común exigiría flags `useLastKeyZero`/`useCycleHelper`/`usePlaceholderGuard`/`useDayPeriodCascade` que crearían un God-Object peor. | **descartar** — las dos bases han evolucionado a comportamientos legítimamente distintos. Mantener separadas hasta que aparezca una necesidad concreta de compartir. Si en el futuro hace falta deduplicar, atacar solo el esqueleto del router de teclas (~50 líneas reales, no las 300 que sugería el audit). | | **ListSelectionHelper** (combobox 1091 líneas + select). `selectItem` con modo single/multi, `allowDeselect`, `handleClose`, trigger de eventos ~80 líneas duplicadas. Combobox sólo añade `inputValue` sync. | **diferir** — abstracción de tamaño medio, valor visible. | | **`DateFieldProvider.updateSegment`** — método monolítico, 96 líneas, 7+ ramas if. | **diferir** — partir en helpers por segment kind. | | **24 imports directos de `../field/field-provider.svelte`** (en realidad 37 de 42 cross-component soma imports). No es violación de capa (soma→soma) sino inconsistencia: el patrón canónico es importar la clase desde el barrel del componente vía `internals.ts`. | **diferir** — cosmético, alto coste (tocar 37 archivos) sin cambio behavioral. |