@r2digisolutions/components 0.8.7 → 0.8.8

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.
@@ -95,6 +95,9 @@
95
95
  let placed = $state(false);
96
96
  let activeField = $state<'start' | 'end' | 'value'>('value');
97
97
  let panelId = $state('');
98
+ /** In-progress range while the popover is open. Parent props stay put until both days exist. */
99
+ let draftStart = $state('');
100
+ let draftEnd = $state('');
98
101
 
99
102
  $effect(() => {
100
103
  panelId ||= createId('datepicker');
@@ -111,6 +114,9 @@
111
114
  });
112
115
  }
113
116
 
117
+ const shownStart = $derived(open && mode === 'range' ? draftStart : start);
118
+ const shownEnd = $derived(open && mode === 'range' ? draftEnd : end);
119
+
114
120
  const fieldLabel = $derived.by(() => {
115
121
  if (mode === 'single') return value ? formatIso(value) : placeholder;
116
122
  if (mode === 'multiple') {
@@ -118,8 +124,8 @@
118
124
  if (values.length === 1) return formatIso(values[0]);
119
125
  return `${values.length} dates`;
120
126
  }
121
- if (start && end) return `${formatIso(start)} → ${formatIso(end)}`;
122
- if (start) return `${formatIso(start)} → …`;
127
+ if (shownStart && shownEnd) return `${formatIso(shownStart)} → ${formatIso(shownEnd)}`;
128
+ if (shownStart) return `${formatIso(shownStart)} → …`;
123
129
  return placeholder;
124
130
  });
125
131
 
@@ -228,6 +234,7 @@
228
234
  event.preventDefault();
229
235
  return;
230
236
  }
237
+ beginRangeDraft();
231
238
  placed = false;
232
239
  // Set top/left before the first paint — UA popover defaults to 0,0.
233
240
  positionPanel({ measure: false });
@@ -236,8 +243,18 @@
236
243
  }
237
244
  }
238
245
 
246
+ function beginRangeDraft() {
247
+ draftStart = start;
248
+ draftEnd = end;
249
+ // Opening "Hasta" with a complete range: keep start, wait for a new end.
250
+ if (mode === 'range' && activeField === 'end' && start && end) {
251
+ draftEnd = '';
252
+ }
253
+ }
254
+
239
255
  function handleToggle(event: ToggleEvent) {
240
256
  const next = event.newState === 'open';
257
+ if (next) beginRangeDraft();
241
258
  open = next;
242
259
  if (next) schedulePosition();
243
260
  else placed = false;
@@ -268,17 +285,23 @@
268
285
  start: string;
269
286
  end: string;
270
287
  }) {
288
+ if (mode === 'range') {
289
+ // Keep the in-progress day local. Parent (URL/filters) only gets a complete range.
290
+ if (detail.start && detail.end) {
291
+ start = detail.start;
292
+ end = detail.end;
293
+ onchange?.(detail);
294
+ if (closeOnSelect) setOpen(false);
295
+ }
296
+ return;
297
+ }
298
+
271
299
  onchange?.(detail);
272
300
 
273
301
  if (!closeOnSelect) return;
274
302
 
275
303
  if (mode === 'single' && detail.value) {
276
304
  setOpen(false);
277
- return;
278
- }
279
-
280
- if (mode === 'range' && detail.start && detail.end) {
281
- setOpen(false);
282
305
  }
283
306
  }
284
307
 
@@ -340,8 +363,8 @@
340
363
  ]}
341
364
  >
342
365
  <span class="text-[11px] font-medium tracking-wide text-muted uppercase">{startLabel}</span>
343
- <span class={['truncate text-sm', start ? 'text-primary' : 'text-muted']}>
344
- {start ? formatIso(start) : startPlaceholder}
366
+ <span class={['truncate text-sm', shownStart ? 'text-primary' : 'text-muted']}>
367
+ {shownStart ? formatIso(shownStart) : startPlaceholder}
345
368
  </span>
346
369
  </button>
347
370
  <div class="w-px self-stretch bg-border" aria-hidden="true"></div>
@@ -363,8 +386,8 @@
363
386
  ]}
364
387
  >
365
388
  <span class="text-[11px] font-medium tracking-wide text-muted uppercase">{endLabel}</span>
366
- <span class={['truncate text-sm', end ? 'text-primary' : 'text-muted']}>
367
- {end ? formatIso(end) : endPlaceholder}
389
+ <span class={['truncate text-sm', shownEnd ? 'text-primary' : 'text-muted']}>
390
+ {shownEnd ? formatIso(shownEnd) : endPlaceholder}
368
391
  </span>
369
392
  </button>
370
393
  {#if hasValue && !disabled}
@@ -460,7 +483,7 @@
460
483
  months === 2 ? 'max-w-[min(42rem,calc(100vw-1rem))]' : 'max-w-[20rem]'
461
484
  ]}
462
485
  >
463
- {#key `${open}:${start}:${value}`}
486
+ {#key open}
464
487
  {#if mode === 'single'}
465
488
  <Calendar
466
489
  mode="single"
@@ -493,8 +516,8 @@
493
516
  <Calendar
494
517
  mode="range"
495
518
  {months}
496
- bind:start
497
- bind:end
519
+ bind:start={draftStart}
520
+ bind:end={draftEnd}
498
521
  {min}
499
522
  {max}
500
523
  {disabledDates}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@r2digisolutions/components",
3
- "version": "0.8.7",
3
+ "version": "0.8.8",
4
4
  "private": false,
5
5
  "description": "R2DigiSolutions Svelte 5 component library — Atomic Design, Tailwind 4, Light/Dark mode",
6
6
  "license": "MIT",