@lekoala/date-picker 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"date-field.d.ts","sourceRoot":"","sources":["../../src/date-field.js"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,qBAAa,mBAAmB;IAMvB,KAAK;IACL,QAAQ;IACR,OAAO;;;;;;IACZ,sCAAsC;IACjC,MAAM,EADA,gBAAgB,GAAG,IAAI;IAElC,kDAAkD;IAC7C,SAAS;IACT,MAAM;IACN,SAAS;IACT,aAAa;IAClB,sCAAsC;IACjC,kBAAkB,EADZ,gBAAgB,GAAG,IAAI;IAElC,kCAAkC;IAC7B,mBAAmB,EADb,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI;IAE9B;;;;OAIG;IACE,OAAO,EAFF,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAC,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC,GAAG,IAAI;IAtB/E;;;OAGG;IACH,YAAY,KAAK,EAHN,gBAGM,EAAE,OAAO,AAFvB,CAAuE,EAA/D;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAE/B,EAqB9B;IAED,6BAA6B;IAC7B,SAAS,CAAC,MAAM,EADJ,MACI,QAEf;IAED,+CAA+C;IAC/C,WAAW,CAAC,QAAQ,EADR,MAAM,CAAC,MAAM,EAAE,MAAM,CACb,QAEnB;IAED,4BAA4B;IAC5B,MAAM,CAAC,KAAK,EADA,MACA,UAEX;IAED,2BAA2B;IAC3B,KAAK,CAAC,IAAI,EADE,MACF,UAET;IAED,IAAI,WAAW,WAEd;IAED,IAAI,UAAU,YAEb;IAED,IAAI,UAAU,YAEb;IAED;uDACmD;IACnD,cAAc,SASb;IAED,iEAAiE;IACjE,cAAc,SAmBb;IAED,0DAA0D;IAC1D,KAAK,SAEJ;IAED,2EAA2E;IAC3E,IAAI,OAAO,YAEV;IAED;;;mFAG+E;IAC/E,WAAW,SAkBV;IAED;;;;;OAKG;IACG,MAAM,IAFC,OAAO,CAAC;QAAC,MAAM,EAAE,IAAI,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CA4BnF;IAED;;;OAGG;IACH,YAAY,CAAC,KAAK,EAHP,MAGO,EAAE,OAAO,AAFxB,CAAqC,EAA7B;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAEI,QAW/B;IAED,mEAAmE;IACnE,cAAc,WAIb;IAED;+CAC2C;IAC3C,QAAQ,SAOP;CACF"}
1
+ {"version":3,"file":"date-field.d.ts","sourceRoot":"","sources":["../../src/date-field.js"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,qBAAa,mBAAmB;IAMvB,KAAK;IACL,QAAQ;IACR,OAAO;;;;;;IACZ,sCAAsC;IACjC,MAAM,EADA,gBAAgB,GAAG,IAAI;IAElC,kDAAkD;IAC7C,SAAS;IACT,MAAM;IACN,SAAS;IACT,aAAa;IAClB,sCAAsC;IACjC,kBAAkB,EADZ,gBAAgB,GAAG,IAAI;IAElC,kCAAkC;IAC7B,mBAAmB,EADb,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI;IAE9B;;;;;OAKG;IACE,OAAO,EAFF,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAC,WAAW,CAAC,EAAE,OAAO,CAAA;KAAC,KAAK,OAAO,CAAC;QAAC,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC,GAAG,IAAI;IAvBlH;;;OAGG;IACH,YAAY,KAAK,EAHN,gBAGM,EAAE,OAAO,AAFvB,CAAuE,EAA/D;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAE/B,EAsB9B;IAED,6BAA6B;IAC7B,SAAS,CAAC,MAAM,EADJ,MACI,QAEf;IAED,+CAA+C;IAC/C,WAAW,CAAC,QAAQ,EADR,MAAM,CAAC,MAAM,EAAE,MAAM,CACb,QAEnB;IAED,4BAA4B;IAC5B,MAAM,CAAC,KAAK,EADA,MACA,UAEX;IAED,2BAA2B;IAC3B,KAAK,CAAC,IAAI,EADE,MACF,UAET;IAED,IAAI,WAAW,WAEd;IAED,IAAI,UAAU,YAEb;IAED,IAAI,UAAU,YAEb;IAED;uDACmD;IACnD,cAAc,SASb;IAED,iEAAiE;IACjE,cAAc,SAmBb;IAED,0DAA0D;IAC1D,KAAK,SAEJ;IAED,2EAA2E;IAC3E,IAAI,OAAO,YAEV;IAED;;;mFAG+E;IAC/E,WAAW,SAkBV;IAED;;;;;;;;OAQG;IACG,MAAM,CAAC,OAAO,AAHjB,CACA,EADQ;QAAC,WAAW,CAAC,EAAE,OAAO,CAAA;KAGR,GAFZ,OAAO,CAAC;QAAC,MAAM,EAAE,IAAI,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CA4BnF;IAED;;;OAGG;IACH,YAAY,CAAC,KAAK,EAHP,MAGO,EAAE,OAAO,AAFxB,CAAqC,EAA7B;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAEI,QAW/B;IAED,mEAAmE;IACnE,cAAc,WAIb;IAED;+CAC2C;IAC3C,QAAQ,SAOP;CACF"}
@@ -21,9 +21,27 @@ export declare class DatePickerElement extends HTMLElement {
21
21
  /** @type {"" | "start" | "end"} */
22
22
  _lastFocusEndpoint: "" | "start" | "end";
23
23
  _rangeCommitId: number;
24
- /** Map of clicked/keyboard-activated grid dates to the generation at click
25
- * time (range mode supersession/stale protection). @type {Map<string, number>} */
26
- _pendingIntents: Map<string, number>;
24
+ /** Grid activation intents, keyed by date: the generation at interaction
25
+ * time (range mode supersession/stale protection) plus the bound a drag
26
+ * drop targets, empty for a normal pick.
27
+ * @type {Map<string, {id: number, endpoint: "" | "start" | "end"}>} */
28
+ _pendingIntents: Map<string, {
29
+ id: number;
30
+ endpoint: "" | "start" | "end";
31
+ }>;
32
+ /** Candidate date currently projected onto the calendar band, if any. */
33
+ _previewDate: string;
34
+ /** Live endpoint drag, or null. @type {{pointerId:number, endpoint:"start"|"end", x:number, y:number, date:string, active:boolean} | null} */
35
+ _drag: {
36
+ pointerId: number;
37
+ endpoint: "start" | "end";
38
+ x: number;
39
+ y: number;
40
+ date: string;
41
+ active: boolean;
42
+ } | null;
43
+ /** A real drag already committed; swallow the click that follows it. */
44
+ _suppressGridClick: boolean;
27
45
  /** Overlaid calendar triggers, one per field (single) or per bound (range). @type {{button: HTMLButtonElement, endpoint: "" | "start" | "end"}[]} */
28
46
  _buttons: {
29
47
  button: HTMLButtonElement;
@@ -236,6 +254,59 @@ export declare class DatePickerElement extends HTMLElement {
236
254
  * activation supersedes every earlier pending one.
237
255
  * @param {Event} event */
238
256
  _captureGridIntent(event: Event): void;
257
+ /** Whether one bound can receive a user pick right now.
258
+ * @param {"start" | "end"} bound */
259
+ _boundEditable(bound: "start" | "end"): boolean;
260
+ /**
261
+ * Single write path for a calendar-driven range change. Both fields are
262
+ * synchronized before anything is announced, because one transition can move
263
+ * both bounds at once (`10` then `5` commits `start 10 -> 5` together with
264
+ * `end "" -> 10`); writing bound by bound would expose an intermediate
265
+ * inverted pair. Synthetic `input`/`change` stay on the bounds that moved.
266
+ * @param {import("./date-range.js").RangeTransition} transition
267
+ */
268
+ _applyRangeTransition(transition: import("./date-range.js").RangeTransition): void;
269
+ /**
270
+ * Project a candidate date onto the calendar band. Purely visual: no
271
+ * `rangechange`, no field write, no validation and no source request — the
272
+ * projection reads the month state already loaded, and the real availability
273
+ * check still runs on commit.
274
+ * @param {string} date @param {"" | "start" | "end"} [endpoint]
275
+ */
276
+ _setPreview(date: string, endpoint?: "" | "start" | "end"): void;
277
+ /** Drop the projection and put the committed range back on the band. */
278
+ _clearPreview(): void;
279
+ /** @param {Event} event */
280
+ _onGridDateFocus(event: Event): void;
281
+ /**
282
+ * Hover candidate. `focusedDate` stays the keyboard target only: pointer
283
+ * hover never moves it, it just feeds the same projection.
284
+ * @param {Event} event
285
+ */
286
+ _onGridPointerOver(event: Event): void;
287
+ _onGridPointerLeave(): void;
288
+ /** @param {EventTarget | null} target @returns {string} */
289
+ _cellDate(target: EventTarget | null): string;
290
+ /** @param {number} x @param {number} y @returns {string} */
291
+ _dateAtPoint(x: number, y: number): string;
292
+ /**
293
+ * Arm an endpoint drag. Only a complete, ordered range offers two distinct
294
+ * handles; a one-day range carries both markers on the same cell, and
295
+ * guessing which one the user meant would be worse than not dragging.
296
+ * @param {Event} event
297
+ */
298
+ _onGridPointerDown(event: Event): void;
299
+ /** @param {Event} event */
300
+ _onGridPointerMove(event: Event): void;
301
+ /** @param {Event} event */
302
+ _onGridPointerUp(event: Event): void;
303
+ /** @param {Event} event */
304
+ _onGridPointerCancel(event: Event): void;
305
+ /** @param {number} pointerId */
306
+ _releaseDragCapture(pointerId: number): void;
307
+ /** Expose whether the band currently offers draggable handles, and whether
308
+ * one is being dragged, so the cursor can say so. */
309
+ _syncDragAffordance(): void;
239
310
  /** @param {KeyboardEvent} event */
240
311
  _onEscape(event: KeyboardEvent): void;
241
312
  _syncCalendarOptions(): void;
@@ -246,25 +317,30 @@ export declare class DatePickerElement extends HTMLElement {
246
317
  _refreshRangeButtonLabel(): void;
247
318
  /** @param {string} value */
248
319
  _reflectValue(value: string): void;
249
- /** @param {string} value @param {{emit?:boolean,format?:boolean,reflect?:boolean}} [options] */
320
+ /** @param {string} value @param {{emit?:boolean,format?:boolean,reflect?:boolean,moveDisplay?:boolean}} [options] */
250
321
  _setValue(value: string, options?: {
251
322
  emit?: boolean;
252
323
  format?: boolean;
253
324
  reflect?: boolean;
325
+ moveDisplay?: boolean;
254
326
  }): void;
255
327
  /**
256
328
  * Calendar-backed availability gate injected into the field controllers.
257
329
  * A cancelled or failed source load confirms nothing: do not fill the
258
330
  * submitted ISO field nor treat the date as available.
259
- * @param {string} date @returns {Promise<{ok: boolean, message?: string}>}
331
+ * @param {string} date @param {{moveDisplay?: boolean}} [options]
332
+ * @returns {Promise<{ok: boolean, message?: string}>}
260
333
  */
261
- _confirmDate(date: string): Promise<{
334
+ _confirmDate(date: string, options?: {
335
+ moveDisplay?: boolean;
336
+ }): Promise<{
262
337
  ok: boolean;
263
338
  message?: string;
264
339
  }>;
265
- /** @param {boolean} emit @param {{force?: boolean}} [options] */
340
+ /** @param {boolean} emit @param {{force?: boolean, moveDisplay?: boolean}} [options] */
266
341
  _commitText(emit: boolean, options?: {
267
342
  force?: boolean;
343
+ moveDisplay?: boolean;
268
344
  }): Promise<boolean>;
269
345
  /** @param {"start" | "end"} which */
270
346
  _commitFieldText(which: "start" | "end"): Promise<boolean>;
@@ -284,8 +360,14 @@ export declare class DatePickerElement extends HTMLElement {
284
360
  /** @param {"start" | "end"} which */
285
361
  _boundCanonical(which: "start" | "end"): string;
286
362
  _emitRangeChange(): void;
287
- /** Forward only a displayable range to the calendar band. An inverted or
288
- * start-less business range shows no misleading band. */
363
+ /** Displayable projection of the business range. An inverted or start-less
364
+ * pair shows no misleading band. @returns {{start:string, end:string}} */
365
+ _displayRange(): {
366
+ start: string;
367
+ end: string;
368
+ };
369
+ /** Put the committed range back on the calendar band, dropping any
370
+ * projection currently shown over it. */
289
371
  _syncHighlight(): void;
290
372
  /**
291
373
  * Cross-bound validity: the order error is attributed to the bound that was
@@ -1 +1 @@
1
- {"version":3,"file":"date-picker.d.ts","sourceRoot":"","sources":["../../src/date-picker.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"date-picker.d.ts","sourceRoot":"","sources":["../../src/date-picker.js"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAkB,MAAM,iBAAiB,CAAC;AAUtE,qBAAa,iBAAkB,SAAQ,WAAW;IAKzC,GAAG;IACH,UAAU;IACV,WAAW;IACX,MAAM;IACN,MAAM;IACX,yCAAyC;IACpC,MAAM,EADA,mBAAmB,GAAG,IAAI;IAErC,2CAA2C;IACtC,OAAO,EADD,mBAAmB,EAAE,GAAG,IAAI;IAEvC,yCAAyC;IACpC,MAAM,EADA,mBAAmB,GAAG,IAAI;IAEhC,UAAU;IACf,uGAAuG;IAClG,WAAW,EADiC,CAAC,gBAAgB,GAAG,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAEnG,mFAAmF;IAC9E,eAAe,EADsC,GAAG,CAAC,gBAAgB,CAAC;IAE/E,mCAAmC;IAC9B,kBAAkB,EADZ,EAAE,GAAG,OAAO,GAAG,KAAK;IAE1B,cAAc;IACnB;;;2EAGuE;IAClE,eAAe,EADV,GAAG,CAAC,MAAM,EAAE;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,EAAE,GAAG,OAAO,GAAG,KAAK,CAAA;KAAC,CAAC;IAEnE,yEAAyE;IACpE,YAAY;IACjB,8IAA8I;IACzI,KAAK,EAD8B;QAAC,SAAS,EAAC,MAAM,CAAC;QAAC,QAAQ,EAAC,OAAO,GAAC,KAAK,CAAC;QAAC,CAAC,EAAC,MAAM,CAAC;QAAC,CAAC,EAAC,MAAM,CAAC;QAAC,IAAI,EAAC,MAAM,CAAC;QAAC,MAAM,EAAC,OAAO,CAAA;KAAC,GAAG,IAAI;IAE1I,wEAAwE;IACnE,kBAAkB;IACvB,qJAAqJ;IAChJ,QAAQ,EADuE;QAAC,MAAM,EAAE,iBAAiB,CAAC;QAAC,QAAQ,EAAE,EAAE,GAAG,OAAO,GAAG,KAAK,CAAA;KAAC,EAAE;IAEjJ;oCACgC;IAC3B,YAAY,EADP,WAAW,GAAG,IAAI;IAEvB,MAAM;IACN,SAAS;IACT,oBAAoB;IACpB,yBAAyB;IACzB,WAAW;IACX,qBAAqB;IACrB,WAAW;IACX,aAAa;IACb,KAAK;IACL,kBAAkB;IAClB,SAAS;;;;;;;;;;;;;;;;;;;;IACd,kBAAkB;IACb,OAAO,EADD,GAAG;IAEd,kBAAkB;IACb,UAAU,EADJ,GAAG;IAEd,kBAAkB;IACb,UAAU,EADJ,GAAG;IAEd,kBAAkB;IACb,eAAe,EADT,GAAG;IAEd,8EAA8E;IACzE,gBAAgB,EAD8B,UAAU,GAAG,UAAU;IA1D5E,MAAM,CAAC,kBAAkB,WAAsE;IAE/F,cA0DC;IAED,UAAU,YAET;IAED,iBAAiB,SAOhB;IAED,cAAc,SAqCb;IAED;;;;OAIG;IACH,mBAAmB,SAoBlB;IAED,aAAa,SAkDZ;IAED,oBAAoB,SAuBnB;IAED,gDAAgD;IAChD,cAAc,CAAC,KAAK,EADR,mBAAmB,GAAG,IACd,QAanB;IAED,uFAAuF;IACvF,wBAAwB,CAAC,IAAI,EADjB,MACiB,EAAE,QAAQ,EADN,MAAM,GAAC,IACD,EAAE,QAAQ,EADc,MAAM,GAAC,IACrB,QAYhD;IAED,cAAc;IACd,IAAI,KAAK,wCAER;IAED,cAAc;IACd,IAAI,QAAQ,+BAEX;IAED,cAAc;IACd,IAAI,KAAK,uBAER;IAED,IAAI,KAAK,CAAC,KAAK,oBAAA,EAMd;IAED,cAAc;IACd,IAAI,KAAK;;;kBAER;IAED,IAAI,KAAK,CAAC,KAAK;;;iBAAA,EAId;IAED,cAAc;IACd,IAAI,MAAM,WAET;IAED,IAAI,MAAM,CAAC,KAAK,QAAA,EAGf;IAED,+HAA+H;IAC/H,IAAI,WAAW,qBAEd;IAED,IAAI,WAAW,CAAC,KAAK,QAAA,EAGpB;IAED,cAAc;IACd,IAAI,GAAG,WAGN;IAED,IAAI,GAAG,CAAC,KAAK,QAAA,EAGZ;IAED,cAAc;IACd,IAAI,GAAG,WAGN;IAED,IAAI,GAAG,CAAC,KAAK,QAAA,EAGZ;IAED,cAAc;IACd,IAAI,WAAW,YAEd;IAED,IAAI,WAAW,CAAC,KAAK,SAAA,EAGpB;IAED,cAAc;IACd,IAAI,IAAI,YAEP;IAED,cAAc;IACd,IAAI,QAAQ;;;;;;;;;;;;;;;;;;;MAEX;IAED,IAAI,QAAQ,CAAC,KAAK;;;;;;;;;;;;;;;;;;;KAAA,EAOjB;IAED,6BAA6B;IAC7B,IAAI,MAAM,IADY,GAAG,CAGxB;IAED,IAAI,MAAM,CAAC,KAAK,EALM,GAKN,EAIf;IAED,6BAA6B;IAC7B,IAAI,SAAS,IADS,GAAG,CAGxB;IAED,IAAI,SAAS,CAAC,KAAK,EALG,GAKH,EAIlB;IAED,6BAA6B;IAC7B,IAAI,SAAS,IADS,GAAG,CAGxB;IAED,IAAI,SAAS,CAAC,KAAK,EALG,GAKH,EAGlB;IAED,6BAA6B;IAC7B,IAAI,cAAc,IADI,GAAG,CAGxB;IAED,IAAI,cAAc,CAAC,KAAK,EALF,GAKE,EAIvB;IAED,sMAAsM;IACtM,IAAI,eAAe,IADwJ,UAAU,GAAG,UAAU,CAGjM;IAED,IAAI,eAAe,CAAC,KAAK,EALkJ,UAAU,GAAG,UAK/J,EAExB;IAED,QAAQ;;;;;MAEP;IAED,eAAe,SAEd;IAED,eAAe,SASd;IAED,gBAAgB,SAef;IAED,aAAa,SAaZ;IAED;;;;;;OAMG;IACH,cAAc,CAAC,QAAQ,EAHZ,EAAE,GAAG,OAAO,GAAG,KAGH,GAFV,iBAAiB,CAa7B;IAED;;;;;OAKG;IACH,MAAM,SAuDL;IAED,KAAK,SAgHJ;IAED,UAAU,SA+HT;IAED;;;;OAIG;IACH,sBAAsB,CAAC,QAAQ,EAFpB,OAAO,GAAG,KAEU,QAa9B;IAED;;;;;;OAMG;IACH,oBAAoB,CAAC,QAAQ,EAHlB,OAAO,GAAG,KAGQ,EAAE,KAAK,EAFzB,UAEyB,QAiBnC;IAED;;;;;;OAMG;IACH,iBAAiB,CAAC,QAAQ,EAHf,EAAE,GAAG,OAAO,GAAG,KAGA,EAAE,KAAK,EAFtB,aAEsB,QAWhC;IAED,0EAA0E;IAC1E,eAAe,CAAC,QAAQ,EADZ,EAAE,GAAG,OAAO,GAAG,KACH,EAAE,KAAK,EADoB,aACpB,QAkB9B;IAED,uEAAuE;IACvE,aAAa,CAAC,QAAQ,EADV,EAAE,GAAG,OAAO,GAAG,KACL,EAAE,KAAK,EADsB,UACtB,QAe5B;IAED;;;8BAG0B;IAC1B,kBAAkB,CAAC,KAAK,EADb,KACa,QAavB;IAED;wCACoC;IACpC,cAAc,CAAC,KAAK,EADT,OAAO,GAAG,KACD,WAGnB;IAED;;;;;;;OAOG;IACH,qBAAqB,CAAC,UAAU,EAFrB,OAAO,iBAAiB,EAAE,eAEL,QAqB/B;IAED;;;;;;OAMG;IACH,WAAW,CAAC,IAAI,EAFL,MAEK,EAAE,QAAQ,AAFF,CAAwC,EAAhC,EAAE,GAAG,OAAO,GAAG,KAEhB,QAgB9B;IAED,wEAAwE;IACxE,aAAa,SAGZ;IAED,2BAA2B;IAC3B,gBAAgB,CAAC,KAAK,EADV,KACU,QAMrB;IAED;;;;OAIG;IACH,kBAAkB,CAAC,KAAK,EAFb,KAEa,QAIvB;IAED,mBAAmB,SAMlB;IAED,2DAA2D;IAC3D,SAAS,CAAC,MAAM,EADJ,WAAW,GAAG,IACV,GADiC,MAAM,CAKtD;IAED,4DAA4D;IAC5D,YAAY,CAAC,CAAC,EADF,MACE,EAAE,CAAC,EADa,MACb,GADiC,MAAM,CAKvD;IAED;;;;;OAKG;IACH,kBAAkB,CAAC,KAAK,EAFb,KAEa,QA4BvB;IAED,2BAA2B;IAC3B,kBAAkB,CAAC,KAAK,EADZ,KACY,QA4BvB;IAED,2BAA2B;IAC3B,gBAAgB,CAAC,KAAK,EADV,KACU,QA0BrB;IAED,2BAA2B;IAC3B,oBAAoB,CAAC,KAAK,EADd,KACc,QAQzB;IAED,gCAAgC;IAChC,mBAAmB,CAAC,SAAS,EADjB,MACiB,QAG5B;IAED;yDACqD;IACrD,mBAAmB,SAYlB;IAED,mCAAmC;IACnC,SAAS,CAAC,KAAK,EADH,aACG,QAMd;IAED,oBAAoB,SAenB;IAED,cAAc,SA4Bb;IAED,mBAAmB,SAUlB;IAED;2EACuE;IACvE,wBAAwB,SAUvB;IAED,4BAA4B;IAC5B,aAAa,CAAC,KAAK,EADP,MACO,QAKlB;IAED,qHAAqH;IACrH,SAAS,CAAC,KAAK,EADH,MACG,EAAE,OAAO,AADE,CAAwF,EAAhF;QAAC,IAAI,CAAC,EAAC,OAAO,CAAC;QAAA,MAAM,CAAC,EAAC,OAAO,CAAC;QAAA,OAAO,CAAC,EAAC,OAAO,CAAC;QAAA,WAAW,CAAC,EAAC,OAAO,CAAA;KACzE,QAqB5B;IAED;;;;;;OAMG;IACG,YAAY,CAAC,IAAI,EAHZ,MAGY,EAAE,OAAO,AAHR,CACrB,EAD6B;QAAC,WAAW,CAAC,EAAE,OAAO,CAAA;KAGjB,GAFxB,OAAO,CAAC;QAAC,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CAgBpD;IAED,wFAAwF;IAClF,WAAW,CAAC,IAAI,EADV,OACU,EAAE,OAAO,AADL,CAA2D,EAAnD;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAA;KACrC,oBAcnC;IAED,qCAAqC;IAC/B,gBAAgB,CAAC,KAAK,EADhB,OAAO,GAAG,KACM,oBAgB3B;IAED;+FAC2F;IAC3F,SAAS,CAAC,KAAK,EAFH,OAAO,GAAG,KAEP,EAAE,KAAK,EAFqB,MAErB,EAAE,OAAO,AAD5B,CAAmE,EAA3D;QAAC,IAAI,CAAC,EAAC,OAAO,CAAC;QAAC,MAAM,CAAC,EAAC,OAAO,CAAC;QAAC,IAAI,CAAC,EAAC,OAAO,CAAA;KACrB,GAD4C,OAAO,CA8BtF;IAED;uGACmG;IACnG,SAAS,CAAC,KAAK,EADJ,MACI,EAAE,GAAG,EADa,MACb,EAAE,OAAO,AADgB,CAAmD,EAA3C;QAAC,IAAI,CAAC,EAAC,OAAO,CAAC;QAAC,MAAM,CAAC,EAAC,OAAO,CAAA;KAClD,QAWjC;IAED,qCAAqC;IACrC,eAAe,CAAC,KAAK,EADT,OAAO,GAAG,KACD,UAEpB;IAED,gBAAgB,SAGf;IAED;8EAC0E;IAC1E,aAAa,IAD+B;QAAC,KAAK,EAAC,MAAM,CAAC;QAAC,GAAG,EAAC,MAAM,CAAA;KAAC,CAMrE;IAED;6CACyC;IACzC,cAAc,SAMb;IAED;;;;;OAKG;IACH,gBAAgB,CAAC,KAAK,EAFX,OAAO,GAAG,KAEC,QAkBrB;IAED;;;;;;;;OAQG;IACH,oBAAoB,CAAC,KAAK,EAFf,OAAO,GAAG,KAEK,QAyBzB;IAED,uBAAuB,SAGtB;IAED,eAAe,SAed;IAED,oBAAoB,SAWnB;IAED,qCAAqC;IACrC,WAAW,CAAC,KAAK,EADL,OAAO,GAAG,KACL,QAShB;IAED;;;;;OAKG;IACH,aAAa,SASZ;IAED,sCAAsC;IACtC,qBAAqB,IADP,EAAE,GAAG,OAAO,GAAG,KAAK,CAcjC;IAED,cAAc;IACR,QAAQ,qBA+Bb;IAED,yGAAyG;IACzG,IAAI,CAAC,OAAO,AADA,CAA0F,EAAlF;QAAC,SAAS,CAAC,EAAC,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAC,OAAO,GAAC,KAAK,CAAC;QAAC,WAAW,CAAC,EAAC,WAAW,CAAA;KACzE,QAoChB;IAED,gCAAgC;IAChC,YAAY,CAAC,QAAQ,EADT,OACS,QAKpB;IAED,8CAA8C;IAC9C,IAAI,CAAC,YAAY,AADL,CAA+B,EAAvB,OACK,QA8BxB;IAED;;;yCAGqC;IACrC,qBAAqB,IADR,EAAE,GAAG,OAAO,GAAG,KAAK,CAShC;CACF"}
@@ -29,21 +29,63 @@ export declare function normalizeRange(range: {
29
29
  * @returns {"" | "start" | "in" | "end" | "single"}
30
30
  */
31
31
  export declare function rangePosition(date: string, range: DateRange | null | undefined): "" | "start" | "in" | "end" | "single";
32
+ export type RangeTransition = {
33
+ status: "pending" | "complete" | "refused";
34
+ /**
35
+ * primary bound the transition speaks through
36
+ */
37
+ endpoint: "start" | "end";
38
+ /**
39
+ * bounds whose value actually moves
40
+ */
41
+ changedEndpoints: ("start" | "end")[];
42
+ /**
43
+ * the whole resulting pair, not only the moved bound
44
+ */
45
+ range: DateRange;
46
+ /**
47
+ * bound the next pick would target
48
+ */
49
+ activeEndpoint: "" | "start" | "end";
50
+ /**
51
+ * the workflow cannot continue in the popup
52
+ */
53
+ close?: boolean;
54
+ };
55
+ /**
56
+ * @typedef {object} RangeTransition
57
+ * @property {"pending" | "complete" | "refused"} status
58
+ * @property {"start" | "end"} endpoint primary bound the transition speaks through
59
+ * @property {("start" | "end")[]} changedEndpoints bounds whose value actually moves
60
+ * @property {DateRange} range the whole resulting pair, not only the moved bound
61
+ * @property {"" | "start" | "end"} activeEndpoint bound the next pick would target
62
+ * @property {boolean} [close] the workflow cannot continue in the popup
63
+ */
32
64
  /**
33
65
  * Pure two-bound state machine for the shared-calendar range picker. Covers
34
66
  * start/end state and the active-endpoint transition rules; it knows nothing
35
67
  * about DOM, popups or async availability.
36
68
  *
37
- * Interaction contract (U9):
69
+ * Interaction contract:
38
70
  * - opening through a field targets that bound;
39
71
  * - a pick outside a complete range extends the corresponding bound;
40
- * - otherwise activating through `end` refuses a date before `start`;
72
+ * - while a range is being created (`start` set, no `end`), a second pick
73
+ * before the anchor is sorted into `date -> start` instead of refused:
74
+ * calendar interaction never produces an inverted range;
75
+ * - an explicit change to one bound of an already complete pair keeps that
76
+ * bound's identity, so moving `end` before `start` is refused rather than
77
+ * silently rewriting the other field;
41
78
  * - activating through `start` commits `start`, moves the active endpoint to
42
79
  * `end` and leaves the popup open for the second selection.
43
80
  *
44
- * The business range may be temporarily incomplete or inverted; it is the
45
- * coordinator's job to forward only a displayable range to
46
- * `calendar.highlightedRange`.
81
+ * Each rule exists once, as a `project*()` projection; `activate()` and
82
+ * `moveEndpoint()` only apply one. Hover, keyboard and drag previews read the
83
+ * same projections, so a second copy of the interaction rules cannot drift
84
+ * into the DOM layer.
85
+ *
86
+ * Text entry is deliberately outside this machine: a typed pair may be
87
+ * temporarily inverted and report a validation error. It is the coordinator's
88
+ * job to forward only a displayable range to `calendar.highlightedRange`.
47
89
  */
48
90
  export declare class DateRangeController {
49
91
  /** @type {"" | "start" | "end"} */
@@ -51,32 +93,72 @@ export declare class DateRangeController {
51
93
  start: string;
52
94
  end: string;
53
95
  constructor();
54
- /** @returns {{start:string, end:string}} */
55
- get range(): {
56
- start: string;
57
- end: string;
58
- };
96
+ /** @returns {DateRange} */
97
+ get range(): DateRange;
59
98
  /** Whether both bounds exist and are ordered (start <= end). */
60
99
  get complete(): boolean;
61
100
  /** @param {"" | "start" | "end"} endpoint */
62
101
  focus(endpoint: "" | "start" | "end"): void;
102
+ /** @param {"start" | "end"} endpoint @returns {RangeTransition} */
103
+ _refuse(endpoint: "start" | "end"): RangeTransition;
63
104
  /**
64
- * Process one grid activation through the active endpoint.
105
+ * Project one grid activation through the active endpoint, without mutating.
65
106
  *
66
107
  * `editable(bound)` reports whether a bound can receive a user pick. It
67
108
  * guards every commit and the `start -> end` transition: when the next bound
68
- * is uneditable the returned result carries `close: true` instead of leaving
69
- * the popup targeting a bound that can never change. `status: "complete"`
70
- * stays reserved for an actually ordered pair.
109
+ * is uneditable the returned transition carries `close: true` instead of
110
+ * leaving the popup targeting a bound that can never change. `status:
111
+ * "complete"` stays reserved for an actually ordered pair.
112
+ * @param {string} date
113
+ * @param {(bound: "start" | "end") => boolean} [editable]
114
+ * @returns {RangeTransition}
115
+ */
116
+ project(date: string, editable?: (bound: "start" | "end") => boolean): RangeTransition;
117
+ /**
118
+ * Project a direct move of one bound (endpoint drag), without mutating.
119
+ *
120
+ * Only a complete, ordered pair offers two handles to grab, and a handle
121
+ * never crosses the other one: the candidate is clamped to the opposite
122
+ * bound, so the previewed band is exactly what a drop commits. Equality is
123
+ * allowed (a one-day range).
124
+ * @param {string} date
125
+ * @param {"start" | "end"} endpoint
126
+ * @param {(bound: "start" | "end") => boolean} [editable]
127
+ * @returns {RangeTransition}
128
+ */
129
+ projectEndpoint(date: string, endpoint: "start" | "end", editable?: (bound: "start" | "end") => boolean): RangeTransition;
130
+ /**
131
+ * Displayable band a candidate date would produce, or `null` when there is
132
+ * nothing to promise. Single source of truth for hover, keyboard and drag
133
+ * previews: the projection rules with no mutation and no event.
134
+ *
135
+ * Without a drag handle a preview only speaks during range creation, when
136
+ * exactly one bound is anchored and the other is still open. An empty range
137
+ * has no anchor to project from, and a complete pair is not a promise in
138
+ * progress — previewing it would repaint the committed band on every hover.
139
+ * @param {string} date
140
+ * @param {"" | "start" | "end"} [endpoint] drag handle, empty for a normal pick
141
+ * @param {(bound: "start" | "end") => boolean} [editable]
142
+ * @returns {DateRange | null}
143
+ */
144
+ previewRange(date: string, endpoint?: "" | "start" | "end", editable?: (bound: "start" | "end") => boolean): DateRange | null;
145
+ /** @param {RangeTransition} transition @returns {RangeTransition} */
146
+ _apply(transition: RangeTransition): RangeTransition;
147
+ /**
148
+ * Apply one grid activation through the active endpoint.
149
+ * @param {string} date
150
+ * @param {(bound: "start" | "end") => boolean} [editable]
151
+ * @returns {RangeTransition}
152
+ */
153
+ activate(date: string, editable?: (bound: "start" | "end") => boolean): RangeTransition;
154
+ /**
155
+ * Apply a direct move of one bound (endpoint drag).
71
156
  * @param {string} date
157
+ * @param {"start" | "end"} endpoint
72
158
  * @param {(bound: "start" | "end") => boolean} [editable]
73
- * @returns {{status: "pending" | "complete" | "refused", endpoint: "start" | "end", close?: boolean}}
159
+ * @returns {RangeTransition}
74
160
  */
75
- activate(date: string, editable?: (bound: "start" | "end") => boolean): {
76
- status: "pending" | "complete" | "refused";
77
- endpoint: "start" | "end";
78
- close?: boolean;
79
- };
161
+ moveEndpoint(date: string, endpoint: "start" | "end", editable?: (bound: "start" | "end") => boolean): RangeTransition;
80
162
  }
81
163
  /**
82
164
  * Link two date pickers without teaching either picker about its sibling.
@@ -1 +1 @@
1
- {"version":3,"file":"date-range.d.ts","sourceRoot":"","sources":["../../src/date-range.js"],"names":[],"mappings":"AAEI,YAAsC,SAAS,GAArC;IAAC,KAAK,EAAC,MAAM,CAAC;IAAC,GAAG,EAAC,MAAM,CAAA;CAAC,CAAW;AAAnD,sDAAsD;AAEtD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAHzB;IAAC,KAAK,CAAC,EAAC,MAAM,CAAC;IAAC,GAAG,CAAC,EAAC,MAAM,CAAA;CAAC,GAAC,IAAI,GAAC,SAGT,GAFvB,SAAS,CAYrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAJvB,MAIuB,EAAE,KAAK,EAH9B,SAAS,GAAC,IAAI,GAAC,SAGe,GAF5B,EAAE,GAAG,OAAO,GAAG,IAAI,GAAG,KAAK,GAAG,QAAQ,CAUlD;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,mBAAmB;IAE5B,mCAAmC;IAC9B,cAAc,EADR,EAAE,GAAG,OAAO,GAAG,KAAK;IAE1B,KAAK;IACL,GAAG;IAJV,cAKC;IAED,4CAA4C;IAC5C,IAAI,KAAK,IADK;QAAC,KAAK,EAAC,MAAM,CAAC;QAAC,GAAG,EAAC,MAAM,CAAA;KAAC,CAGvC;IAED,gEAAgE;IAChE,IAAI,QAAQ,YAEX;IAED,6CAA6C;IAC7C,KAAK,CAAC,QAAQ,EADF,EAAE,GAAG,OAAO,GAAG,KACb,QAEb;IAED;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,IAAI,EAJF,MAIE,EAAE,QAAQ,AAHpB,CACA,EADQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,KAAK,OAGH,GAFvB;QAAC,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;QAAC,QAAQ,EAAE,OAAO,GAAG,KAAK,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAC,CA4BpG;CACF;AAgBD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAJxB,OAAO,kBAAkB,EAAE,iBAIH,EAAE,GAAG,EAH7B,OAAO,kBAAkB,EAAE,iBAGE,GAF3B,MAAM,IAAI,CAyBtB"}
1
+ {"version":3,"file":"date-range.d.ts","sourceRoot":"","sources":["../../src/date-range.js"],"names":[],"mappings":"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"}
@@ -58,6 +58,16 @@ export declare function endOfWeek(value: string, firstDay?: number): string;
58
58
  export declare function getMonthWeeks(value: string, options?: {
59
59
  firstDay?: number;
60
60
  }): string[][];
61
+ /**
62
+ * Nearest month whose true civil weeks stay inside 0001-01-01..9999-12-31, so a
63
+ * grid can always be built. A month's covering weeks can reach a few days
64
+ * before or after it, so the earliest and latest displayable months depend on
65
+ * `firstDay`.
66
+ * @param {string} value YYYY-MM or YYYY-MM-DD
67
+ * @param {number} [firstDay]
68
+ * @returns {string} YYYY-MM
69
+ */
70
+ export declare function clampDisplayMonth(value: string, firstDay?: number): string;
61
71
  /** @param {string} value @param {string} [min] @param {string} [max] */
62
72
  export declare function clampDate(value: string, min?: string, max?: string): string;
63
73
  /** Local civil date; no timezone conversion of the selected date model. */
@@ -1 +1 @@
1
- {"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/date.js"],"names":[],"mappings":"AAGA,2BAA2B;AAC3B,wBAAgB,UAAU,CAAC,IAAI,EADnB,MACmB,WAE9B;AAED,iDAAiD;AACjD,wBAAgB,WAAW,CAAC,IAAI,EADpB,MACoB,EAAE,KAAK,EADN,MACM,qBAGtC;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAHpB,MAGoB,GAFlB;IAAC,IAAI,EAAC,MAAM,CAAC;IAAC,KAAK,EAAC,MAAM,CAAC;IAAC,GAAG,EAAC,MAAM,CAAA;CAAC,GAAG,IAAI,CAW1D;AAED,4BAA4B;AAC5B,wBAAgB,MAAM,CAAC,KAAK,EADhB,MACgB,WAE3B;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAHnB,MAGmB,GAFjB,MAAM,CAYlB;AAED,qEAAqE;AACrE,wBAAgB,SAAS,CAAC,IAAI,EADlB,MACkB,EAAE,KAAK,EADJ,MACI,EAAE,GAAG,EADa,MACb,UAIzC;AAeD,4BAA4B;AAC5B,wBAAgB,UAAU,CAAC,KAAK,EADpB,MACoB,QAI/B;AAED,0CAA0C;AAC1C,wBAAgB,YAAY,CAAC,CAAC,EADlB,MACkB,EAAE,CAAC,EADH,MACG,cAGhC;AAED,mDAAmD;AACnD,wBAAgB,OAAO,CAAC,KAAK,EADjB,MACiB,EAAE,MAAM,EADH,MACG,UAOpC;AAED,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,KAAK,EADnB,MACmB,EAAE,MAAM,EADL,MACK,UAUtC;AAED,mDAAmD;AACnD,wBAAgB,QAAQ,CAAC,KAAK,EADlB,MACkB,EAAE,MAAM,EADJ,MACI,UAOrC;AAED,mDAAmD;AACnD,wBAAgB,UAAU,CAAC,KAAK,EADpB,MACoB,EAAE,MAAM,EADN,MACM,UAGvC;AAED,4BAA4B;AAC5B,wBAAgB,YAAY,CAAC,KAAK,EADtB,MACsB,UAEjC;AAED,4BAA4B;AAC5B,wBAAgB,UAAU,CAAC,KAAK,EADpB,MACoB,UAI/B;AAED,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,KAAK,EADM,MACN,UAI9B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAF/B,MAE+B,UAKzC;AAED,qDAAqD;AACrD,wBAAgB,WAAW,CAAC,KAAK,EADrB,MACqB,EAAE,QAAQ,GADT,MACa,UAG9C;AAED,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,KAAK,EADnB,MACmB,EAAE,QAAQ,GADP,MACW,UAE5C;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAHxB,MAGwB,EAAE,OAAO,AAFzC,CAAsC,EAA9B;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAEoB,cAchD;AAED,wEAAwE;AACxE,wBAAgB,SAAS,CAAC,KAAK,EADnB,MACmB,EAAE,GAAG,AADV,CAAsB,EAAd,MACO,EAAE,GAAG,AADE,CAAqB,EAAb,MACL,UAKlD;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,WAGvB;AAED,kDAAkD;AAClD,wBAAgB,aAAa,CAAC,KAAK,EADD,MACC,UAUlC"}
1
+ {"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/date.js"],"names":[],"mappings":"AAGA,2BAA2B;AAC3B,wBAAgB,UAAU,CAAC,IAAI,EADnB,MACmB,WAE9B;AAED,iDAAiD;AACjD,wBAAgB,WAAW,CAAC,IAAI,EADpB,MACoB,EAAE,KAAK,EADN,MACM,qBAGtC;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAHpB,MAGoB,GAFlB;IAAC,IAAI,EAAC,MAAM,CAAC;IAAC,KAAK,EAAC,MAAM,CAAC;IAAC,GAAG,EAAC,MAAM,CAAA;CAAC,GAAG,IAAI,CAW1D;AAED,4BAA4B;AAC5B,wBAAgB,MAAM,CAAC,KAAK,EADhB,MACgB,WAE3B;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAHnB,MAGmB,GAFjB,MAAM,CAYlB;AAED,qEAAqE;AACrE,wBAAgB,SAAS,CAAC,IAAI,EADlB,MACkB,EAAE,KAAK,EADJ,MACI,EAAE,GAAG,EADa,MACb,UAIzC;AAeD,4BAA4B;AAC5B,wBAAgB,UAAU,CAAC,KAAK,EADpB,MACoB,QAI/B;AAED,0CAA0C;AAC1C,wBAAgB,YAAY,CAAC,CAAC,EADlB,MACkB,EAAE,CAAC,EADH,MACG,cAGhC;AAED,mDAAmD;AACnD,wBAAgB,OAAO,CAAC,KAAK,EADjB,MACiB,EAAE,MAAM,EADH,MACG,UAOpC;AAED,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,KAAK,EADnB,MACmB,EAAE,MAAM,EADL,MACK,UAUtC;AAED,mDAAmD;AACnD,wBAAgB,QAAQ,CAAC,KAAK,EADlB,MACkB,EAAE,MAAM,EADJ,MACI,UAOrC;AAED,mDAAmD;AACnD,wBAAgB,UAAU,CAAC,KAAK,EADpB,MACoB,EAAE,MAAM,EADN,MACM,UAGvC;AAED,4BAA4B;AAC5B,wBAAgB,YAAY,CAAC,KAAK,EADtB,MACsB,UAEjC;AAED,4BAA4B;AAC5B,wBAAgB,UAAU,CAAC,KAAK,EADpB,MACoB,UAI/B;AAED,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,KAAK,EADM,MACN,UAI9B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAF/B,MAE+B,UAKzC;AAED,qDAAqD;AACrD,wBAAgB,WAAW,CAAC,KAAK,EADrB,MACqB,EAAE,QAAQ,GADT,MACa,UAG9C;AAED,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,KAAK,EADnB,MACmB,EAAE,QAAQ,GADP,MACW,UAE5C;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAHxB,MAGwB,EAAE,OAAO,AAFzC,CAAsC,EAA9B;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAEoB,cAkBhD;AAaD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAJ5B,MAI4B,EAAE,QAAQ,AAH9C,CACA,EADQ,MAG0C,GAFxC,MAAM,CAyBlB;AAED,wEAAwE;AACxE,wBAAgB,SAAS,CAAC,KAAK,EADnB,MACmB,EAAE,GAAG,AADV,CAAsB,EAAd,MACO,EAAE,GAAG,AADE,CAAqB,EAAb,MACL,UAKlD;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,WAGvB;AAED,kDAAkD;AAClD,wBAAgB,aAAa,CAAC,KAAK,EADD,MACC,UAUlC"}
@@ -1 +1 @@
1
- {"version":3,"file":"intl.d.ts","sourceRoot":"","sources":["../../src/intl.js"],"names":[],"mappings":"AAIA,+BAA+B;AAC/B,wBAAgB,aAAa,CAAC,MAAM,AADhC,CAAwB,EAAhB,MAC6B,UAKxC;AAmBD,qDAAqD;AACrD,wBAAgB,cAAc,CAAC,KAAK,EADxB,MACwB,EAAE,MAAM,AADlB,CAAwB,EAAhB,MACe,UAUhD;AAED,qDAAqD;AACrD,wBAAgB,eAAe,CAAC,KAAK,EADzB,MACyB,EAAE,MAAM,AADnB,CAAwB,EAAhB,MACgB,UAQjD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,MAAM,AAFlC,CAAyB,EAAjB,MAE+B,GAFJ,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CA2B1E;AAED,+DAA+D;AAC/D,wBAAgB,UAAU,CAAC,MAAM,AAD7B,CAAyB,EAAjB,MAC0B,EAAE,KAAK,AADhB,CAA+B,EAAvB,MAAM,GAAC,OACU,YAMrD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,AAJhC,CACA,EADQ,MAI6B,EAAE,QAAQ,AAH/C,CACA,EADQ,MAG2C,EAAE,KAAK,AAF1D,CAAwC,EAAhC,MAAM,GAAC,OAAO,GAAC,QAE6C,YAetE;AAOD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,AAFrC,CAAwB,EAAhB,MAEkC;;;IAiCzC,4BAA4B;kBAAhB,MAAM;IAKlB,6CAA6C;gBAAjC,MAAM,GAAiB,MAAM;EAmB5C;AAED,4BAA4B;AAC5B,wBAAgB,SAAS,CAAC,KAAK,EADnB,MACmB;;;;SAE9B"}
1
+ {"version":3,"file":"intl.d.ts","sourceRoot":"","sources":["../../src/intl.js"],"names":[],"mappings":"AAIA,+BAA+B;AAC/B,wBAAgB,aAAa,CAAC,MAAM,AADhC,CAAwB,EAAhB,MAC6B,UAKxC;AAsBD,qDAAqD;AACrD,wBAAgB,cAAc,CAAC,KAAK,EADxB,MACwB,EAAE,MAAM,AADlB,CAAwB,EAAhB,MACe,UAUhD;AAED,qDAAqD;AACrD,wBAAgB,eAAe,CAAC,KAAK,EADzB,MACyB,EAAE,MAAM,AADnB,CAAwB,EAAhB,MACgB,UAQjD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,MAAM,AAFlC,CAAyB,EAAjB,MAE+B,GAFJ,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CA2B1E;AAED,+DAA+D;AAC/D,wBAAgB,UAAU,CAAC,MAAM,AAD7B,CAAyB,EAAjB,MAC0B,EAAE,KAAK,AADhB,CAA+B,EAAvB,MAAM,GAAC,OACU,YAMrD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,AAJhC,CACA,EADQ,MAI6B,EAAE,QAAQ,AAH/C,CACA,EADQ,MAG2C,EAAE,KAAK,AAF1D,CAAwC,EAAhC,MAAM,GAAC,OAAO,GAAC,QAE6C,YAetE;AAOD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,AAFrC,CAAwB,EAAhB,MAEkC;;;IAoCzC,4BAA4B;kBAAhB,MAAM;IAKlB,6CAA6C;gBAAjC,MAAM,GAAiB,MAAM;EAmB5C;AAED,4BAA4B;AAC5B,wBAAgB,SAAS,CAAC,KAAK,EADnB,MACmB;;;;SAE9B"}
@@ -38,7 +38,11 @@ Weekday headings use visible short labels plus a full `abbr` value.
38
38
  | Shift+PageDown | same/clamped day in next year |
39
39
  | Enter / Space | activate focused date |
40
40
 
41
- Moving focus never changes selection.
41
+ Moving focus never changes selection. Each cell that actually receives focus dispatches `datefocus`, so an application can follow keyboard navigation without reading internal DOM classes; hover never dispatches it, and assigning `focusedDate` without moving focus stays silent.
42
+
43
+ A range preview projected onto the band is visual only: it never contributes a range start/end to a day's accessible name, so a proposal is never announced as a committed selection.
44
+
45
+ Endpoint dragging is a pointer enhancement. Every adjustment it offers is also reachable from the keyboard: activating before or after a complete range moves the corresponding bound.
42
46
 
43
47
  ## Month/year controls
44
48
 
@@ -110,7 +114,7 @@ Guard: re-run the `color-contrast` review and the forced-colors screenshot bundl
110
114
 
111
115
  ## Visible focus
112
116
 
113
- The default focus language uses `--dp-accent`, so the picker holds together without a consumer stylesheet (`outline: none` plus an accent border and a light halo). Only the focus state is normalized: the resting input appearance stays consumer-owned.
117
+ Fields (including native time companions), calendar header controls and day cells use an inner solid outline. `--dp-focus` defaults to `var(--dp-accent)` and `--dp-focus-width` defaults to `2px`; the inward offset follows the width. This replaces the previous accent border and soft halo on fields and header controls. The resting input appearance stays consumer-owned.
114
118
 
115
119
  Focus is only ever drawn on a real box. The calendar trigger is a real button painted inside the date field's own box, so the field's focus ring naturally wraps the affordance too — no host-level ring, no pseudo-element. When the trigger itself is focused it shows a small inner ring, like the native `input[type=time]` indicator, instead of pretending the whole field is focused.
116
120
 
package/docs/API.md CHANGED
@@ -62,6 +62,7 @@ calendar.nextMonth();
62
62
  calendar.focusDate("2026-09-10");
63
63
  calendar.focusGrid();
64
64
  calendar.getDateState("2026-09-10");
65
+ await calendar.activateDate("2026-09-10");
65
66
  await calendar.ensureDate("2026-09-10");
66
67
  await calendar.refreshSource();
67
68
  calendar.render();
@@ -87,6 +88,28 @@ calendar.addEventListener("dateactivate", (event) => {
87
88
  });
88
89
  ```
89
90
 
91
+ `activateDate(date)` runs that same path on demand: availability check, then
92
+ the cancelable event, then selection. Click, keyboard and the range endpoint
93
+ drag all go through it, so an application that cancels `dateactivate` cannot be
94
+ bypassed by a different input device.
95
+
96
+ #### `datefocus`
97
+
98
+ Fired when a date cell actually receives focus, with `{ date, state }`. Arrow,
99
+ Home, End, PageUp and PageDown all emit one through the cell that took focus.
100
+
101
+ ```js
102
+ calendar.addEventListener("datefocus", (event) => {
103
+ console.log(event.detail.date);
104
+ });
105
+ ```
106
+
107
+ It observes navigation and nothing else: a disabled day still reports it (grid
108
+ navigation stays discoverable), hover never does, and assigning `focusedDate`
109
+ without moving DOM focus stays silent. The three verbs are distinct —
110
+ `datefocus` observes, `dateactivate` requests an activation, `datechange`
111
+ observes a selection.
112
+
90
113
  #### `datechange`
91
114
 
92
115
  Fired when `selection="single"` changes `value`.
@@ -272,7 +295,11 @@ The business range may be temporarily incomplete or inverted; `calendar.highligh
272
295
  ### Interaction
273
296
 
274
297
  - When an ordered range is complete, picking before its start updates only the start; picking after its end updates only the end, regardless of the opening field. The popup closes after this update. An uneditable target bound refuses the activation.
275
- - Otherwise, opening through a field targets that bound (`activeEndpoint`). Picking from `start` commits it, moves the endpoint to `end` without closing, and a second pick commits and closes. Opening from `end` refuses a date before `start` (`dateinvalid`, nothing changes).
298
+ - Otherwise, opening through a field targets that bound (`activeEndpoint`). Picking from `start` commits it, moves the endpoint to `end` without closing, and a second pick commits and closes.
299
+ - **Calendar interaction never produces an inverted range.** While a range is being created, a second pick before the anchor is sorted rather than refused: `10` then `15` gives `10 -> 15`, `10` then `5` gives `5 -> 10`, and `10` then `10` a one-day range. That transition moves **both** bounds at once and is applied in a single write — one `rangechange`, with synthetic `input`/`change` on each bound that moved, and no intermediate inverted pair ever observable. Typed text keeps the opposite contract and may be temporarily inverted (see [DECISIONS D6](DECISIONS.md)).
300
+ - Changing one bound of an already complete pair keeps that bound's identity: moving `end` before `start` is refused (`dateinvalid`, nothing changes) instead of rewriting the other field.
301
+ - **Preview.** While a range is being created, hovering a day or moving the keyboard focus projects the range the next pick would commit onto `calendar.highlightedRange`, and the pick commits exactly what was projected. The projection is visual only: no `rangechange`, no field write, no validation and no source request. It reads the month already loaded, so a day known to be unavailable promises nothing; the real availability check still runs on commit. Pointer hover never moves `focusedDate`, which stays the keyboard target. Leaving the grid, Escape and closing the popup restore the committed band.
302
+ - **Endpoint drag.** On a complete, ordered range whose two ends sit on different days, each endpoint can be dragged with a mouse or pen (pointer events plus capture, armed only once the pointer travels). A handle never crosses the other one — the candidate is clamped to it, equality allowed — an unavailable cell is not a drop target, and `pointercancel` restores the committed band. The drop runs the same projection and the same `ensureDate` + cancelable `dateactivate` path as a click, emits one `rangechange`, and keeps the popup open: a drag adjusts a range, it does not validate it. A press without travel stays a plain click. Touch keeps native scrolling and stays a plain tap.
276
303
  - Each bound owns its trigger (`input[data-range-start]` then its trigger, `input[data-range-end]` then its trigger); the two triggers share **one** popup, calendar, source and state. Pressing the other bound's trigger while the popup is open switches the active bound and keeps it open instead of toggling it shut. A trigger never opens a `readonly`/`disabled` bound.
277
304
  - Typing stays independent per field. Moving `start` past `end` keeps both values and flags the *modified* bound with `rangeOrderStart`; fixing either side revalidates both. Parse/source errors are never cleared by cross-bound revalidation.
278
305
  - A stale availability response resolving after the active endpoint changed (or after a newer selection) never commits; a field focus that switches the endpoint invalidates in-flight activations.
@@ -297,6 +324,29 @@ rangePosition("2026-09-12", range); // "start" | "in" | "end" | "single" | ""
297
324
 
298
325
  `normalizeRange` validates an ordered displayable range and never reorders: an inversion or an `end` without a `start` throws. `rangePosition` classifies one day within a displayable range (see [`highlightedRange`](#highlightedrange)).
299
326
 
327
+ ## `DateRangeController`
328
+
329
+ The pure two-bound state machine behind `date-picker[range]`. It owns the
330
+ selection rules and knows nothing about DOM, popups or async availability.
331
+
332
+ ```js
333
+ const model = new DateRangeController();
334
+ model.focus("start");
335
+ model.activate("2026-09-10"); // { status: "pending", endpoint: "start", … }
336
+ model.previewRange("2026-09-05"); // { start: "2026-09-05", end: "2026-09-10" }
337
+ model.activate("2026-09-05"); // changedEndpoints: ["start", "end"]
338
+ ```
339
+
340
+ - `project(date, editable?)` / `projectEndpoint(date, endpoint, editable?)` describe a transition without applying it;
341
+ - `activate(date, editable?)` / `moveEndpoint(date, endpoint, editable?)` apply one;
342
+ - `previewRange(date, endpoint?, editable?)` returns the displayable band a candidate would produce, or `null` when there is nothing to promise.
343
+
344
+ A transition is `{ status, endpoint, changedEndpoints, range, activeEndpoint, close? }`.
345
+ `range` is the whole resulting pair, because one interaction can move both
346
+ bounds; `changedEndpoints` names the ones that actually move. Every rule exists
347
+ once, as a projection, and the previews read the same projections the commit
348
+ applies.
349
+
300
350
  ## `createDateAdapter(locale)`
301
351
 
302
352
  Locale-aware editable numeric adapter:
package/docs/DECISIONS.md CHANGED
@@ -1,13 +1,15 @@
1
1
  # Decisions
2
2
 
3
- Frozen contracts for the `0.1.0` surface. A change to a decision below is a breaking change and needs a proposal, not an opportunistic edit.
3
+ Frozen contracts for the public surface. A change to a decision below is a breaking change and needs a proposal, not an opportunistic edit.
4
4
 
5
5
  ## D1 — Calendar events are flat, verb-named
6
6
 
7
7
  Never merged with the `value` concept (`dateactivate` is activation, not `value`).
8
8
 
9
- - `date-calendar`: `dateactivate`, `datechange`, `dateinvalid`, `displaychange`, `dateloadstart`, `dateloadend`, `dateloaderror`.
10
- - `date-picker`: `valuechange`, `open`, `close`.
9
+ - `date-calendar`: `dateactivate`, `datefocus`, `datechange`, `dateinvalid`, `displaychange`, `dateloadstart`, `dateloadend`, `dateloaderror`.
10
+ - `date-picker`: `valuechange`, `open`, `close`, plus `rangechange` in range mode.
11
+
12
+ The observation verbs stay distinct: `datefocus` observes navigation, `dateactivate` requests an activation (and is cancelable), `datechange` observes a selection. `datefocus` is named after the user event rather than after the `focusedDate` setter, so a programmatic assignment that moves no DOM focus never announces one.
11
13
 
12
14
  No `dp:` namespace prefix on element events, even though `@lekoala/combobox` namespaces its events (`combobox:*`).
13
15
 
@@ -46,4 +48,15 @@ Context: DOM-backed styling hooks become API the moment they are documented —
46
48
  - Time fields are authored native `input[type=time]` marked `[data-time-start]` / `[data-time-end]`; `name`, `value`, `required`, `min`, `max`, `step` and submission stay native. There is no hidden time input and no time field controller.
47
49
  - `picker.value` / `picker.range` remain date-only (`YYYY-MM-DD`); the picker never constructs a datetime, a timestamp or a timezone-bearing value.
48
50
  - The picker only coordinates from/to order (`start <= end`, equality allowed); duration rules stay application-owned.
49
- - Custom time UI and slot picking stay outside the package.
51
+ - Custom time UI and slot picking stay outside the package.
52
+
53
+ ## D6 — Calendar interaction never produces an inverted range
54
+
55
+ Pointing and typing are different contracts, deliberately.
56
+
57
+ - **Interaction** (click, keyboard, endpoint drag) always yields an ordered range. While a range is being created, the second selection is sorted against the anchor: `10` then `5` commits `5 -> 10`, and `10` then `10` a one-day range. No `dateinvalid` is fired merely because the second point is earlier.
58
+ - **Text entry** may be temporarily inverted. Typing `start` past `end` keeps both values and reports `rangeOrderStart` / `rangeOrderEnd` on the modified bound, because a half-typed pair is a normal editing state.
59
+ - An explicit change to **one bound of an already complete pair** keeps that bound's identity: moving `end` before `start` is refused rather than silently rewriting the other field.
60
+ - Because one interaction can move both bounds at once, a transition describes the whole resulting pair (`{ status, endpoint, changedEndpoints, range, activeEndpoint }`) and is applied in a single write: one `rangechange`, with synthetic `input` / `change` only on the bounds that actually moved.
61
+ - Hover, keyboard focus and endpoint drag read the **same projection** (`previewRange()`) that the commit applies, so what the band promises is what the next selection commits. A preview writes nothing: no `rangechange`, no field write, no validation, no source request.
62
+ - Click, keyboard and drop all end in that one range machine and in the same `ensureDate` plus cancelable `dateactivate` path, so an application veto cannot be bypassed by choosing another input device.
@@ -1,6 +1,6 @@
1
1
  # Flatpickr / Formidable migration map
2
2
 
3
- This prototype was scoped against the existing `FlatpickrInput` wrapper rather than against Flatpickr's full feature list.
3
+ This project was scoped against the existing `FlatpickrInput` wrapper rather than against Flatpickr's full feature list.
4
4
 
5
5
  ## Directly covered
6
6
 
package/docs/TESTING.md CHANGED
@@ -68,6 +68,6 @@ Keep explicit tests for these regressions:
68
68
 
69
69
  ## CI
70
70
 
71
- The included workflow uses Bun 1.4.2 and runs static checks/unit tests before Playwright.
71
+ The included workflow uses Bun 1.4.3 and runs static checks/unit tests before Playwright.
72
72
 
73
73
  `bun.lock` is committed. Keep installs frozen in CI (`bun install --frozen-lockfile`) so dependency resolution stays deterministic. Regenerate the lock with `bun install` when the manifest changes and commit it in the same change.
package/docs/USE_CASES.md CHANGED
@@ -111,6 +111,9 @@ Acceptance:
111
111
  - an inverted range (start after end) keeps both entered values and surfaces an order error on the bound that was just modified; changing either side revalidates both;
112
112
  - form reset restores both fields in one resync;
113
113
  - a stale async availability response arriving after the active endpoint changed never commits a value or closes the popup;
114
+ - calendar interaction never produces an inverted range: while a range is being created, a second selection before the first is sorted (`10` then `5` commits `5 -> 10`) in one atomic update; an explicit change to one bound of an already complete pair keeps that bound's identity instead;
115
+ - pointer hover and keyboard navigation project the range the next selection would commit onto the band, without changing any value, and a selection commits exactly what was projected;
116
+ - the endpoints of a complete range can be dragged to adjust it, through the same projection, the same availability check and the same cancelable activation as a click;
114
117
  - only the bounds are validated; per-night availability stays application-owned.
115
118
 
116
119
  ## U10 — Date with native time companions
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lekoala/date-picker",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Native-first date picker and inline calendar primitives",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "homepage": "https://github.com/lekoala/date-picker",
22
22
  "bugs": "https://github.com/lekoala/date-picker/issues",
23
- "packageManager": "bun@1.4.2",
23
+ "packageManager": "bun@1.4.3",
24
24
  "keywords": [
25
25
  "date-picker",
26
26
  "calendar",
@@ -162,10 +162,10 @@
162
162
  "prepublishOnly": "bun run verify"
163
163
  },
164
164
  "devDependencies": {
165
- "@biomejs/biome": "2.5.13",
166
- "@lekoala/calendar": "0.1.0",
167
- "@playwright/test": "1.63.0",
168
- "temporal-polyfill": "^1.0.4",
165
+ "@biomejs/biome": "2.5.15",
166
+ "@lekoala/calendar": "0.2.0",
167
+ "@playwright/test": "1.64.0",
168
+ "temporal-polyfill": "^1.0.5",
169
169
  "typescript": "7.0.2"
170
170
  },
171
171
  "dependencies": {