@mhmo91/schmancy 0.10.43 → 0.10.44

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.
Files changed (38) hide show
  1. package/custom-elements.json +2 -2
  2. package/dist/agent/schmancy.agent.js +785 -779
  3. package/dist/agent/schmancy.agent.js.map +1 -1
  4. package/dist/agent/schmancy.manifest.json +1 -1
  5. package/dist/badge.cjs +1 -1
  6. package/dist/badge.js +1 -1
  7. package/dist/content-drawer.cjs +1 -1
  8. package/dist/content-drawer.js +1 -1
  9. package/dist/date-range-B2VN7cl_.cjs +138 -0
  10. package/dist/date-range-B2VN7cl_.cjs.map +1 -0
  11. package/dist/{date-range-D2NZU5Yg.js → date-range-CDF_5ju_.js} +63 -57
  12. package/dist/date-range-CDF_5ju_.js.map +1 -0
  13. package/dist/date-range.cjs +1 -1
  14. package/dist/date-range.js +1 -1
  15. package/dist/form.cjs +1 -1
  16. package/dist/form.js +1 -1
  17. package/dist/handover/agent-runtime-followups.md +1 -1
  18. package/dist/handover/agent-runtime-v1.md +3 -3
  19. package/dist/index.cjs +1 -1
  20. package/dist/index.js +2 -2
  21. package/dist/nav-drawer.cjs +1 -1
  22. package/dist/nav-drawer.js +1 -1
  23. package/dist/navigation-bar.cjs +1 -1
  24. package/dist/navigation-bar.js +1 -1
  25. package/dist/{src-DAtcPmCb.js → src-Bo-vvN6m.js} +1 -1
  26. package/dist/{src-DAtcPmCb.js.map → src-Bo-vvN6m.js.map} +1 -1
  27. package/dist/{src-DuRvYagm.cjs → src-MdpH1zth.cjs} +1 -1
  28. package/dist/{src-DuRvYagm.cjs.map → src-MdpH1zth.cjs.map} +1 -1
  29. package/dist/teleport.cjs +1 -1
  30. package/dist/teleport.js +1 -1
  31. package/package.json +1 -1
  32. package/src/form/fields/date-range/date-range-dialog.ts +14 -1
  33. package/src/form/fields/date-range/date-range.test.ts +218 -1
  34. package/src/form/fields/date-range/date-range.ts +42 -18
  35. package/types/src/form/fields/date-range/date-range.d.ts +4 -0
  36. package/dist/date-range-CVAWMdar.cjs +0 -138
  37. package/dist/date-range-CVAWMdar.cjs.map +0 -1
  38. package/dist/date-range-D2NZU5Yg.js.map +0 -1
@@ -273,7 +273,7 @@ describe('schmancy-date-range', () => {
273
273
  // Exact shape: {start, end} — no preset field.
274
274
  expect(detail.start).toBe('2026-06-01')
275
275
  expect(detail.end).toBe('2026-06-15')
276
- expect(Object.keys(detail).sort()).toEqual(['end', 'start'])
276
+ expect(Object.keys(detail).toSorted()).toEqual(['end', 'start'])
277
277
 
278
278
  // change must NOT have fired — provisional sweep is not a commit.
279
279
  expect(changeReceived.length, 'change must not fire for provisional sweep').toBe(0)
@@ -380,4 +380,221 @@ describe('schmancy-date-range', () => {
380
380
  await expectNoA11yViolations(host)
381
381
  })
382
382
  })
383
+
384
+ // -------------------------------------------------------------------------
385
+ describe('datetime-local', () => {
386
+ // Calendar pick → commits start-of-day / end-of-day YYYY-MM-DDTHH:mm
387
+ it('calendar pick commits start-of-day T00:00 and end-of-day T23:59', async () => {
388
+ const host = await mount('<schmancy-date-range name="dtw" type="datetime-local"></schmancy-date-range>')
389
+ const el = dr(host)
390
+ await el.updateComplete
391
+
392
+ // Open the picker.
393
+ const btn = el.shadowRoot!.querySelector('schmancy-button') as HTMLElement
394
+ document.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true, composed: true, clientX: 10, clientY: 10 }))
395
+ btn.click()
396
+ await el.updateComplete
397
+ await nextUpdate()
398
+
399
+ const dialog = await vi.waitFor(
400
+ () => {
401
+ for (const o of document.querySelectorAll('schmancy-overlay')) {
402
+ const d = o.shadowRoot?.querySelector('schmancy-date-range-dialog')
403
+ if (d) return d
404
+ }
405
+ throw new Error('dialog not mounted yet')
406
+ },
407
+ { timeout: 2000 },
408
+ )
409
+
410
+ // Dispatch the calendar `change` event on the schmancy-calendar element inside
411
+ // the dialog's shadow root so it routes through handleCalendarChange, which is
412
+ // responsible for converting YYYY-MM-DD → YYYY-MM-DDTHH:mm when type="datetime-local".
413
+ const calendar = dialog.shadowRoot?.querySelector('schmancy-calendar')
414
+ expect(calendar, 'schmancy-calendar must be in the dialog shadow root').not.toBeNull()
415
+
416
+ const changeReceived: CustomEvent[] = []
417
+ el.addEventListener('change', (e) => changeReceived.push(e as CustomEvent))
418
+
419
+ calendar!.dispatchEvent(
420
+ new CustomEvent('change', {
421
+ detail: { value: null, start: '2026-06-10', end: '2026-06-20' },
422
+ bubbles: true,
423
+ composed: true,
424
+ }),
425
+ )
426
+ await el.updateComplete
427
+
428
+ expect(changeReceived.length, 'change must fire after calendar pick').toBeGreaterThan(0)
429
+ const detail = changeReceived[changeReceived.length - 1].detail as {
430
+ start: string | null
431
+ end: string | null
432
+ preset: string | null
433
+ }
434
+ expect(detail.start).toBe('2026-06-10T00:00')
435
+ expect(detail.end).toBe('2026-06-20T23:59')
436
+ expect(detail.preset).toBeNull()
437
+ })
438
+
439
+ // Typed path edits time without moving the date.
440
+ it('typed datetime-local input replaces time component without moving the date', async () => {
441
+ const host = await mount('<schmancy-date-range name="dtw" type="datetime-local"></schmancy-date-range>')
442
+ const el = dr(host)
443
+ el.start = '2026-06-10T00:00'
444
+ el.end = '2026-06-20T23:59'
445
+ await el.updateComplete
446
+
447
+ // Open the picker.
448
+ const btn = el.shadowRoot!.querySelector('schmancy-button') as HTMLElement
449
+ document.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true, composed: true, clientX: 10, clientY: 10 }))
450
+ btn.click()
451
+ await el.updateComplete
452
+ await nextUpdate()
453
+
454
+ const dialog = await vi.waitFor(
455
+ () => {
456
+ for (const o of document.querySelectorAll('schmancy-overlay')) {
457
+ const d = o.shadowRoot?.querySelector('schmancy-date-range-dialog')
458
+ if (d) return d
459
+ }
460
+ throw new Error('dialog not mounted yet')
461
+ },
462
+ { timeout: 2000 },
463
+ )
464
+
465
+ // Simulate the typed From input changing the time (same date, different time).
466
+ // handleFromChange dispatches `calendar-change` directly with the full datetime
467
+ // value from the input, preserving the date part and replacing the time.
468
+ // We dispatch `calendar-change` at the dialog bridge seam (same approach used
469
+ // in the existing `input event` tests) to verify the contract end-to-end.
470
+ const changeReceived: CustomEvent[] = []
471
+ el.addEventListener('change', (e) => changeReceived.push(e as CustomEvent))
472
+
473
+ dialog.dispatchEvent(
474
+ new CustomEvent('calendar-change', {
475
+ // The typed input produces a full YYYY-MM-DDTHH:mm value; the dialog
476
+ // passes this through unchanged (no T-injection since it already has T).
477
+ detail: { start: '2026-06-10T09:30', end: '2026-06-20T23:59' },
478
+ bubbles: true,
479
+ composed: true,
480
+ }),
481
+ )
482
+ await el.updateComplete
483
+
484
+ expect(changeReceived.length).toBeGreaterThan(0)
485
+ const detail = changeReceived[changeReceived.length - 1].detail as {
486
+ start: string | null
487
+ end: string | null
488
+ }
489
+ // Date part preserved; time replaced.
490
+ expect(detail.start).toBe('2026-06-10T09:30')
491
+ expect(detail.end).toBe('2026-06-20T23:59')
492
+ })
493
+
494
+ // FormData carries YYYY-MM-DDTHH:mm ISO entries.
495
+ it('FormData ${name}.start and ${name}.end carry datetime ISO strings', async () => {
496
+ const host = await mount(
497
+ '<form><schmancy-date-range name="dtw" type="datetime-local"></schmancy-date-range></form>',
498
+ )
499
+ const form = host.querySelector('form') as HTMLFormElement
500
+ const el = dr(host)
501
+ el.start = '2026-06-10T09:30'
502
+ el.end = '2026-06-20T18:00'
503
+ await el.updateComplete
504
+ const fd = new FormData(form)
505
+ expect(fd.get('dtw.start')).toBe('2026-06-10T09:30')
506
+ expect(fd.get('dtw.end')).toBe('2026-06-20T18:00')
507
+ })
508
+
509
+ // Default presets are rebuilt with datetime format when type changes.
510
+ it('default presets use YYYY-MM-DDTHH:mm format when type="datetime-local"', async () => {
511
+ const host = await mount('<schmancy-date-range name="dtw"></schmancy-date-range>')
512
+ const el = dr(host)
513
+ // Initially type=date; presets are YYYY-MM-DD.
514
+ expect(el.presets[0].start).toMatch(/^\d{4}-\d{2}-\d{2}$/)
515
+
516
+ // Switch to datetime-local; presets should rebuild.
517
+ el.type = 'datetime-local'
518
+ await el.updateComplete
519
+
520
+ expect(el.presets[0].start).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/)
521
+ expect(el.presets[0].end).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/)
522
+ })
523
+
524
+ // usingDefaultPresets race: setting type + presets in the same willUpdate cycle
525
+ // must leave the consumer's presets intact (not overwritten by rebuilt defaults).
526
+ it('consumer presets survive when type and presets are set together', async () => {
527
+ const host = await mount('<schmancy-date-range name="dtw"></schmancy-date-range>')
528
+ const el = dr(host)
529
+ await el.updateComplete
530
+
531
+ const customPresets = [
532
+ { id: 'q1', label: 'Q1 2026', start: '2026-01-01', end: '2026-03-31' },
533
+ { id: 'q2', label: 'Q2 2026', start: '2026-04-01', end: '2026-06-30' },
534
+ ]
535
+
536
+ // Set both type and presets in the same microtask so they arrive in one willUpdate.
537
+ el.type = 'datetime-local'
538
+ el.presets = customPresets
539
+ await el.updateComplete
540
+
541
+ // Consumer's presets must survive — not replaced by datetime-formatted defaults.
542
+ expect(el.presets).toHaveLength(2)
543
+ expect(el.presets[0].id).toBe('q1')
544
+ expect(el.presets[0].start).toBe('2026-01-01')
545
+ expect(el.presets[1].id).toBe('q2')
546
+ })
547
+
548
+ // Calendar pick in datetime mode — no double T insertion if already includes T.
549
+ it('dialog passes through already-formatted datetime values unchanged', async () => {
550
+ const host = await mount('<schmancy-date-range name="dtw" type="datetime-local"></schmancy-date-range>')
551
+ const el = dr(host)
552
+ el.start = '2026-06-10T00:00'
553
+ el.end = '2026-06-20T23:59'
554
+ await el.updateComplete
555
+
556
+ const btn = el.shadowRoot!.querySelector('schmancy-button') as HTMLElement
557
+ document.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true, composed: true, clientX: 10, clientY: 10 }))
558
+ btn.click()
559
+ await el.updateComplete
560
+ await nextUpdate()
561
+
562
+ const dialog = await vi.waitFor(
563
+ () => {
564
+ for (const o of document.querySelectorAll('schmancy-overlay')) {
565
+ const d = o.shadowRoot?.querySelector('schmancy-date-range-dialog')
566
+ if (d) return d
567
+ }
568
+ throw new Error('dialog not mounted yet')
569
+ },
570
+ { timeout: 2000 },
571
+ )
572
+
573
+ const calendar = dialog.shadowRoot?.querySelector('schmancy-calendar')
574
+ expect(calendar, 'schmancy-calendar must be in the dialog shadow root').not.toBeNull()
575
+
576
+ const changeReceived: CustomEvent[] = []
577
+ el.addEventListener('change', (e) => changeReceived.push(e as CustomEvent))
578
+
579
+ // Dispatch calendar change with a value that already contains T — must NOT
580
+ // become 2026-06-10T00:00T00:00. The dialog's handleCalendarChange guards with
581
+ // `!start.includes('T')` so already-formatted values pass through unchanged.
582
+ calendar!.dispatchEvent(
583
+ new CustomEvent('change', {
584
+ detail: { value: null, start: '2026-06-10T00:00', end: '2026-06-20T23:59' },
585
+ bubbles: true,
586
+ composed: true,
587
+ }),
588
+ )
589
+ await el.updateComplete
590
+
591
+ expect(changeReceived.length).toBeGreaterThan(0)
592
+ const detail = changeReceived[changeReceived.length - 1].detail as {
593
+ start: string | null
594
+ end: string | null
595
+ }
596
+ expect(detail.start).toBe('2026-06-10T00:00')
597
+ expect(detail.end).toBe('2026-06-20T23:59')
598
+ })
599
+ })
383
600
  })
@@ -28,55 +28,56 @@ dayjs.extend(quarterOfYear)
28
28
  // Default built-in presets
29
29
  // ---------------------------------------------------------------------------
30
30
 
31
- function buildDefaultPresets(): DateRangeDialogPreset[] {
31
+ function buildDefaultPresets(type: 'date' | 'datetime-local' = 'date'): DateRangeDialogPreset[] {
32
+ const fmt = type === 'datetime-local' ? 'YYYY-MM-DDTHH:mm' : 'YYYY-MM-DD'
32
33
  return [
33
34
  {
34
35
  id: 'today',
35
36
  label: 'Today',
36
- start: dayjs().startOf('day').format('YYYY-MM-DD'),
37
- end: dayjs().endOf('day').format('YYYY-MM-DD'),
37
+ start: dayjs().startOf('day').format(fmt),
38
+ end: dayjs().endOf('day').format(fmt),
38
39
  },
39
40
  {
40
41
  id: 'yesterday',
41
42
  label: 'Yesterday',
42
- start: dayjs().subtract(1, 'day').startOf('day').format('YYYY-MM-DD'),
43
- end: dayjs().subtract(1, 'day').endOf('day').format('YYYY-MM-DD'),
43
+ start: dayjs().subtract(1, 'day').startOf('day').format(fmt),
44
+ end: dayjs().subtract(1, 'day').endOf('day').format(fmt),
44
45
  },
45
46
  {
46
47
  id: 'last7',
47
48
  label: 'Last 7 days',
48
- start: dayjs().subtract(6, 'day').startOf('day').format('YYYY-MM-DD'),
49
- end: dayjs().endOf('day').format('YYYY-MM-DD'),
49
+ start: dayjs().subtract(6, 'day').startOf('day').format(fmt),
50
+ end: dayjs().endOf('day').format(fmt),
50
51
  },
51
52
  {
52
53
  id: 'last30',
53
54
  label: 'Last 30 days',
54
- start: dayjs().subtract(29, 'day').startOf('day').format('YYYY-MM-DD'),
55
- end: dayjs().endOf('day').format('YYYY-MM-DD'),
55
+ start: dayjs().subtract(29, 'day').startOf('day').format(fmt),
56
+ end: dayjs().endOf('day').format(fmt),
56
57
  },
57
58
  {
58
59
  id: 'thisWeek',
59
60
  label: 'This week',
60
- start: dayjs().startOf('week').format('YYYY-MM-DD'),
61
- end: dayjs().endOf('week').format('YYYY-MM-DD'),
61
+ start: dayjs().startOf('week').format(fmt),
62
+ end: dayjs().endOf('week').format(fmt),
62
63
  },
63
64
  {
64
65
  id: 'thisMonth',
65
66
  label: 'This month',
66
- start: dayjs().startOf('month').format('YYYY-MM-DD'),
67
- end: dayjs().endOf('month').format('YYYY-MM-DD'),
67
+ start: dayjs().startOf('month').format(fmt),
68
+ end: dayjs().endOf('month').format(fmt),
68
69
  },
69
70
  {
70
71
  id: 'lastMonth',
71
72
  label: 'Last month',
72
- start: dayjs().subtract(1, 'month').startOf('month').format('YYYY-MM-DD'),
73
- end: dayjs().subtract(1, 'month').endOf('month').format('YYYY-MM-DD'),
73
+ start: dayjs().subtract(1, 'month').startOf('month').format(fmt),
74
+ end: dayjs().subtract(1, 'month').endOf('month').format(fmt),
74
75
  },
75
76
  {
76
77
  id: 'thisYear',
77
78
  label: 'This year',
78
- start: dayjs().startOf('year').format('YYYY-MM-DD'),
79
- end: dayjs().endOf('year').format('YYYY-MM-DD'),
79
+ start: dayjs().startOf('year').format(fmt),
80
+ end: dayjs().endOf('year').format(fmt),
80
81
  },
81
82
  ]
82
83
  }
@@ -121,7 +122,13 @@ export class SchmancyDateRange extends SchmancyFormField() {
121
122
  @property() start: string | null = null
122
123
  @property() end: string | null = null
123
124
 
124
- @property({ type: Array }) presets: DateRangeDialogPreset[] = buildDefaultPresets()
125
+ /** Reference to the last array produced by buildDefaultPresets; used to detect consumer ownership. */
126
+ private defaultPresetsRef: DateRangeDialogPreset[] = buildDefaultPresets()
127
+
128
+ @property({ type: Array }) presets: DateRangeDialogPreset[] = this.defaultPresetsRef
129
+
130
+ /** True while the component holds the built-in default preset list (not user-supplied). */
131
+ private usingDefaultPresets = true
125
132
 
126
133
  /** Selected preset id; null = custom range. Reflects to attribute. */
127
134
  @property({ reflect: true }) preset: string | null = null
@@ -230,6 +237,23 @@ export class SchmancyDateRange extends SchmancyFormField() {
230
237
 
231
238
  override willUpdate(changed: PropertyValues): void {
232
239
  super.willUpdate(changed)
240
+ // Consumer ownership detection must run before the type-change rebuild so that
241
+ // when both `type` and `presets` arrive in the same willUpdate cycle (e.g. simultaneous
242
+ // attribute/property initialisation), the consumer's presets are not overwritten.
243
+ //
244
+ // A `presets` change signals consumer ownership when the incoming value is not the
245
+ // array reference produced by the internal default-builder (defaultPresetsRef).
246
+ // Since buildDefaultPresets always allocates a new array, defaultPresetsRef is the
247
+ // only reference that could match; any other reference came from the consumer.
248
+ if (changed.has('presets') && this.presets !== this.defaultPresetsRef) {
249
+ this.usingDefaultPresets = false
250
+ }
251
+ // Rebuild built-in presets when type changes, but only while the consumer has never
252
+ // supplied their own presets array.
253
+ if (changed.has('type') && this.usingDefaultPresets) {
254
+ this.defaultPresetsRef = buildDefaultPresets(this.type)
255
+ this.presets = this.defaultPresetsRef
256
+ }
233
257
  if (changed.has('start') || changed.has('end') || changed.has('name') || changed.has('disabled')) {
234
258
  if (this.name && !this.disabled) {
235
259
  const fd = new FormData()
@@ -26,7 +26,11 @@ export declare class SchmancyDateRange extends SchmancyDateRange_base {
26
26
  type: 'date' | 'datetime-local';
27
27
  start: string | null;
28
28
  end: string | null;
29
+ /** Reference to the last array produced by buildDefaultPresets; used to detect consumer ownership. */
30
+ private defaultPresetsRef;
29
31
  presets: DateRangeDialogPreset[];
32
+ /** True while the component holds the built-in default preset list (not user-supplied). */
33
+ private usingDefaultPresets;
30
34
  /** Selected preset id; null = custom range. Reflects to attribute. */
31
35
  preset: string | null;
32
36
  min?: string;
@@ -1,138 +0,0 @@
1
- const e=require(`./chunk-CncqDLb2.cjs`),t=require(`./SchmancyElement-CeKrBW2j.cjs`),n=require(`./mixins-Cjn20BQH.cjs`),r=require(`./overlay.service-MMTiW2T3.cjs`),i=require(`./dayjs.min-CvRZTfam.cjs`);let a=require(`rxjs`),o=require(`lit/decorators.js`),s=require(`lit`),c=require(`lit/directives/if-defined.js`),l=require(`lit/directives/repeat.js`),u=require(`lit/directives/when.js`);var d=e.t((e,t)=>{var n=e,r=function(){"use strict";var e=`month`,t=`quarter`;return function(n,r){var i=r.prototype;i.quarter=function(e){return this.$utils().u(e)?Math.ceil((this.month()+1)/3):this.month(this.month()%3+3*(e-1))};var a=i.add;i.add=function(n,r){return n=Number(n),this.$utils().p(r)===t?this.add(3*n,e):a.bind(this)(n,r)};var o=i.startOf;i.startOf=function(n,r){var i=this.$utils(),a=!!i.u(r)||r;if(i.p(n)===t){var s=this.quarter()-1;return a?this.month(3*s).startOf(e).startOf(`day`):this.month(3*s+2).endOf(e).endOf(`day`)}return o.bind(this)(n,r)}}};typeof e==`object`&&t!==void 0?t.exports=r():typeof define==`function`&&define.amd?define(r):(n=typeof globalThis<`u`?globalThis:n||self).dayjs_plugin_quarterOfYear=r()}),f=e.r(d(),1),p=e.r(i.t(),1),m=class extends t.t{constructor(...e){super(...e),this.type=`date`,this.start=null,this.end=null,this.preset=null,this.presets=[]}static{this.styles=[s.css`
2
- :host {
3
- display: block;
4
- }
5
- `]}handleCalendarInput(e){e.stopPropagation(),this.dispatchEvent(new CustomEvent(`calendar-input`,{detail:{start:e.detail.start,end:e.detail.end},bubbles:!0,composed:!0}))}handleCalendarChange(e){e.stopPropagation(),this.dispatchEvent(new CustomEvent(`calendar-change`,{detail:{start:e.detail.start,end:e.detail.end},bubbles:!0,composed:!0}))}handlePresetClick(e){this.dispatchEvent(new CustomEvent(`preset-select`,{detail:e,bubbles:!0,composed:!0}))}handleFromChange(e){let t=e.target.value;if(!t)return;let n=t,r=this.end&&(0,p.default)(this.end).isBefore((0,p.default)(n))?n:this.end??null;this.dispatchEvent(new CustomEvent(`calendar-change`,{detail:{start:n,end:r},bubbles:!0,composed:!0}))}handleToChange(e){let t=e.target.value;t&&this.dispatchEvent(new CustomEvent(`calendar-change`,{detail:{start:this.start??null,end:t},bubbles:!0,composed:!0}))}render(){return s.html`
6
- <div class="flex flex-col w-full" style="min-width:280px; max-width:360px">
7
- <!-- Sticky chip quick-rail -->
8
- <div
9
- part="presets"
10
- class="sticky top-0 z-20 bg-surface-default flex flex-wrap gap-2 p-3 border-b border-outline-variant/40"
11
- >
12
- ${(0,u.when)(this.presets.length>0,()=>s.html`
13
- ${(0,l.repeat)(this.presets,e=>e.id,e=>s.html`
14
- <schmancy-filter-chip
15
- part="preset ${this.preset===e.id?`preset-selected`:``}"
16
- .value=${e.id}
17
- .selected=${this.preset===e.id}
18
- title="${e.start} — ${e.end}"
19
- @click=${()=>this.handlePresetClick(e)}
20
- >
21
- ${e.label}
22
- </schmancy-filter-chip>
23
- `)}
24
- `,()=>s.nothing)}
25
- </div>
26
-
27
- <!-- Calendar (continuous-scroll range picker) -->
28
- <div part="calendar" class="overflow-y-auto" style="max-height:320px">
29
- <schmancy-calendar
30
- mode="range"
31
- .type=${this.type}
32
- .start=${this.start}
33
- .end=${this.end}
34
- min=${(0,c.ifDefined)(this.min)}
35
- max=${(0,c.ifDefined)(this.max)}
36
- @input=${e=>this.handleCalendarInput(e)}
37
- @change=${e=>this.handleCalendarChange(e)}
38
- ></schmancy-calendar>
39
- </div>
40
-
41
- <!-- Secondary typed-entry path -->
42
- <div class="flex gap-2 p-3 border-t border-outline-variant/40 flex-wrap">
43
- <div class="flex-1 min-w-30">
44
- <schmancy-input
45
- .type=${this.type}
46
- .label=${`From`}
47
- .value=${this.start??``}
48
- min=${(0,c.ifDefined)(this.min)}
49
- max=${(0,c.ifDefined)(this.max)}
50
- @change=${this.handleFromChange}
51
- ></schmancy-input>
52
- </div>
53
- <div class="flex-1 min-w-30">
54
- <schmancy-input
55
- .type=${this.type}
56
- .label=${`To`}
57
- .value=${this.end??``}
58
- min=${(0,c.ifDefined)(this.start??this.min)}
59
- max=${(0,c.ifDefined)(this.max)}
60
- @change=${this.handleToChange}
61
- ></schmancy-input>
62
- </div>
63
- </div>
64
- </div>
65
- `}};t.u([(0,o.property)()],m.prototype,`type`,void 0),t.u([(0,o.property)()],m.prototype,`start`,void 0),t.u([(0,o.property)()],m.prototype,`end`,void 0),t.u([(0,o.property)()],m.prototype,`min`,void 0),t.u([(0,o.property)()],m.prototype,`max`,void 0),t.u([(0,o.property)()],m.prototype,`preset`,void 0),t.u([(0,o.property)({type:Array})],m.prototype,`presets`,void 0),m=t.u([(0,o.customElement)(`schmancy-date-range-dialog`)],m),p.default.extend(f.default);var h=class extends n.o(){constructor(...e){super(...e),this.type=`date`,this.start=null,this.end=null,this.presets=[{id:`today`,label:`Today`,start:(0,p.default)().startOf(`day`).format(`YYYY-MM-DD`),end:(0,p.default)().endOf(`day`).format(`YYYY-MM-DD`)},{id:`yesterday`,label:`Yesterday`,start:(0,p.default)().subtract(1,`day`).startOf(`day`).format(`YYYY-MM-DD`),end:(0,p.default)().subtract(1,`day`).endOf(`day`).format(`YYYY-MM-DD`)},{id:`last7`,label:`Last 7 days`,start:(0,p.default)().subtract(6,`day`).startOf(`day`).format(`YYYY-MM-DD`),end:(0,p.default)().endOf(`day`).format(`YYYY-MM-DD`)},{id:`last30`,label:`Last 30 days`,start:(0,p.default)().subtract(29,`day`).startOf(`day`).format(`YYYY-MM-DD`),end:(0,p.default)().endOf(`day`).format(`YYYY-MM-DD`)},{id:`thisWeek`,label:`This week`,start:(0,p.default)().startOf(`week`).format(`YYYY-MM-DD`),end:(0,p.default)().endOf(`week`).format(`YYYY-MM-DD`)},{id:`thisMonth`,label:`This month`,start:(0,p.default)().startOf(`month`).format(`YYYY-MM-DD`),end:(0,p.default)().endOf(`month`).format(`YYYY-MM-DD`)},{id:`lastMonth`,label:`Last month`,start:(0,p.default)().subtract(1,`month`).startOf(`month`).format(`YYYY-MM-DD`),end:(0,p.default)().subtract(1,`month`).endOf(`month`).format(`YYYY-MM-DD`)},{id:`thisYear`,label:`This year`,start:(0,p.default)().startOf(`year`).format(`YYYY-MM-DD`),end:(0,p.default)().endOf(`year`).format(`YYYY-MM-DD`)}],this.preset=null,this.placeholder=`Select date range`,this.clearable=!0,this.collapse=!1,this.open$=new a.Subject,this.close$=new a.Subject,this.announce$=new a.Subject,this.isOpen=!1,this.announceMessage=``,this.startDefault=null,this.endDefault=null,this.presetDefault=null}disconnectedCallback(){super.disconnectedCallback(),this.isOpen=!1}connectedCallback(){super.connectedCallback(),(0,a.merge)(this.open$.pipe((0,a.tap)(()=>{this.isOpen=!0}),(0,a.exhaustMap)(e=>r.o(()=>s.html`
66
- <schmancy-date-range-dialog
67
- .type=${this.type}
68
- .start=${this.start}
69
- .end=${this.end}
70
- .min=${this.min}
71
- .max=${this.max}
72
- .preset=${this.preset}
73
- .presets=${this.presets}
74
- @calendar-input=${e=>{e.stopPropagation(),this.dispatchEvent(new CustomEvent(`input`,{detail:{start:e.detail.start,end:e.detail.end},bubbles:!0,composed:!0}))}}
75
- @calendar-change=${e=>{e.stopPropagation(),this.commitRange(e.detail.start,e.detail.end,null),e.detail.start&&e.detail.end&&e.target?.dispatchEvent(new CustomEvent(`close`,{bubbles:!0,composed:!0}))}}
76
- @preset-select=${e=>{e.stopPropagation(),this.commitRange(e.detail.start,e.detail.end,e.detail.id),e.target?.dispatchEvent(new CustomEvent(`close`,{bubbles:!0,composed:!0}))}}
77
- ></schmancy-date-range-dialog>
78
- `,{anchor:e}).pipe((0,a.takeUntil)(this.close$),(0,a.finalize)(()=>{this.isOpen=!1})))),this.announce$.pipe((0,a.switchMap)(e=>(0,a.concat)((0,a.of)(e),(0,a.timer)(1500).pipe((0,a.map)(()=>``)))),(0,a.tap)(e=>{this.announceMessage=e})),(0,a.fromEvent)(document,`keydown`).pipe((0,a.tap)(e=>this.handleKeyDown(e)))).pipe((0,a.takeUntil)(this.disconnecting)).subscribe()}willUpdate(e){if(super.willUpdate(e),e.has(`start`)||e.has(`end`)||e.has(`name`)||e.has(`disabled`)){if(this.name&&!this.disabled){let e=new FormData;this.start&&e.append(`${this.name}.start`,this.start),this.end&&e.append(`${this.name}.end`,this.end),this.internals?.setFormValue(e.has(`${this.name}.start`)||e.has(`${this.name}.end`)?e:null)}else this.internals?.setFormValue(null);this.checkValidity()}e.has(`required`)&&this.checkValidity()}checkValidity(){if(this.disabled)return this.internals?.setValidity({}),!0;if(this.required&&(!this.start||!this.end)){let e=`Please select a complete date range.`;return this.internals?.setValidity({valueMissing:!0},e),this.shouldShowError()&&(this.error=!0,this.validationMessage=e),!1}if(this.start&&this.end&&this.end<this.start){let e=`End date must be on or after start date.`;return this.internals?.setValidity({customError:!0},e),this.shouldShowError()&&(this.error=!0,this.validationMessage=e),!1}return this.internals?.setValidity({}),this.shouldShowError()&&(this.error=!1,this.validationMessage=``),!0}toFormEntries(){if(!this.name||this.disabled)return[];let e=[];return this.start&&e.push([`${this.name}.start`,this.start]),this.end&&e.push([`${this.name}.end`,this.end]),e}get dirty(){return this.start!==this.startDefault||this.end!==this.endDefault}firstUpdated(e){super.firstUpdated(e),this.startDefault=this.start,this.endDefault=this.end,this.presetDefault=this.preset}resetForm(){this.start=this.startDefault,this.end=this.endDefault,this.preset=this.presetDefault,this.error=!1,this.validationMessage=``,this.touched=!1,this.submitted=!1,this.internals?.setValidity({})}commitRange(e,t,n){this.start=e,this.end=t,this.preset=n,this.announce$.next(`Date range: ${this.displayLabel()}`),this.emitChange({start:e,end:t,preset:n})}displayLabel(){if(this.preset){let e=this.presets.find(e=>e.id===this.preset);if(e)return e.label}return function(e,t,n,r){if(!e||!t)return r;let i=(0,p.default)(e),a=(0,p.default)(t);if(!i.isValid()||!a.isValid())return r;let o=n===`datetime-local`?i.format(` h:mm A`):``,s=n===`datetime-local`?a.format(` h:mm A`):``;return i.isSame(a,`day`)?`${i.format(`ddd, MMM D, YYYY`)}${o}`:i.isSame(a,`month`)&&i.isSame(a,`year`)?`${i.format(`ddd MMM D`)} - ${a.format(`ddd D, YYYY`)}${s}`:i.isSame(a,`year`)?`${i.format(`ddd MMM D`)} - ${a.format(`ddd MMM D, YYYY`)}${s}`:`${i.format(`ddd MMM D, YYYY`)}${o} - ${a.format(`ddd MMM D, YYYY`)}${s}`}(this.start??``,this.end??``,this.type,this.placeholder)}toggleDropdown(e){e.stopPropagation(),this.disabled||this.step!==void 0||(this.isOpen?this.close$.next():this.open$.next(e))}shiftDateRange(e,t){if(t.stopPropagation(),!this.start||!this.end)return;let n=(0,p.default)(this.start),r=(0,p.default)(this.end);if(!n.isValid()||!r.isValid())return;let i=this.type===`date`?`YYYY-MM-DD`:`YYYY-MM-DDTHH:mm`,a=e>0?1:-1,o=r.diff(n,`day`)+1,s,c;if(this.step!==void 0)typeof this.step==`number`?(s=a*this.step,c=`day`):this.step===`day`?(s=a*o,c=`day`):(s=a,c=this.step);else{let e=function(e,t){return{isFullMonth:e.date()===1&&t.isSame(e.endOf(`month`),`day`),isFullQuarter:e.isSame(e.startOf(`quarter`),`day`)&&t.isSame(t.endOf(`quarter`),`day`),isFullYear:e.isSame(e.startOf(`year`),`day`)&&t.isSame(t.endOf(`year`),`day`),isFullWeek:e.day()===0&&t.day()===6&&t.diff(e,`days`)===6}}(n,r);e.isFullYear?(s=a,c=`year`):e.isFullMonth?(s=a,c=`month`):e.isFullWeek?(s=a,c=`week`):(s=a*o,c=`day`)}let l=n.add(s,c),u=r.add(s,c);this.min&&l.isBefore((0,p.default)(this.min))||this.max&&u.isAfter((0,p.default)(this.max))||this.commitRange(l.format(i),u.format(i),null)}handleKeyDown(e){if(!this.start||!this.end||this.disabled)return;let t=e.target;if(t===this||this.contains(t))switch(e.key){case`PageUp`:this.shiftDateRange(-1,e),e.preventDefault();break;case`PageDown`:this.shiftDateRange(1,e),e.preventDefault();break;case`Home`:if(e.ctrlKey){let t=this.type===`date`?`YYYY-MM-DD`:`YYYY-MM-DDTHH:mm`,n=(0,p.default)(this.start),r=(0,p.default)(this.end),i=n.startOf(`month`);this.commitRange(i.format(t),i.add(r.diff(n,`day`),`day`).format(t),null),e.preventDefault()}break;case`End`:if(e.ctrlKey){let t=this.type===`date`?`YYYY-MM-DD`:`YYYY-MM-DDTHH:mm`,n=(0,p.default)(this.start),r=(0,p.default)(this.end),i=r.endOf(`month`);this.commitRange(i.subtract(r.diff(n,`day`),`day`).format(t),i.format(t),null),e.preventDefault()}}}canNavigateBackward(){return!this.start||!this.min||(0,p.default)(this.start).isAfter((0,p.default)(this.min))}canNavigateForward(){return!this.end||!this.max||(0,p.default)(this.end).isBefore((0,p.default)(this.max))}render(){let e=this.error&&!!this.validationMessage,t=e?` rounded outline outline-2 outline-error-default`:``,n=this.displayLabel();return s.html`
79
- <div class="relative ${this.disabled?`opacity-60 pointer-events-none`:``}">
80
- <!-- Screen reader announcements -->
81
- <div class="sr-only" role="status" aria-live="polite" aria-atomic="true">${this.announceMessage}</div>
82
-
83
- <!-- Collapsed: icon-only on narrow viewports when collapse=true -->
84
- <schmancy-icon-button
85
- class="${this.collapse?`lg:hidden`:`hidden`}${t}"
86
- variant="outlined"
87
- type="button"
88
- aria-invalid=${e?`true`:`false`}
89
- aria-label="Select date range. Current: ${n}"
90
- @click=${e=>this.toggleDropdown(e)}
91
- ?disabled=${this.disabled}
92
- >
93
- date_range
94
- </schmancy-icon-button>
95
-
96
- <!-- Full trigger row: [← | range label | →] -->
97
- <section
98
- @click=${e=>e.stopPropagation()}
99
- aria-invalid=${e?`true`:`false`}
100
- class="${this.collapse?`hidden lg:flex`:`flex`}${t}"
101
- >
102
- <schmancy-icon-button
103
- type="button"
104
- aria-label="Previous ${this.preset??`date range`}"
105
- @click=${e=>this.shiftDateRange(-1,e)}
106
- ?disabled=${this.disabled||!this.start||!this.end||!this.canNavigateBackward()}
107
- >
108
- arrow_left
109
- </schmancy-icon-button>
110
-
111
- <schmancy-button
112
- class="w-max"
113
- variant="outlined"
114
- type="button"
115
- aria-haspopup="dialog"
116
- aria-expanded=${this.isOpen}
117
- aria-label="Select date range. Current: ${n}"
118
- aria-readonly="${this.step!==void 0}"
119
- @click=${e=>this.toggleDropdown(e)}
120
- ?disabled=${this.disabled}
121
- style="${this.step===void 0?``:`cursor:default;`}"
122
- >
123
- ${n}
124
- </schmancy-button>
125
-
126
- <schmancy-icon-button
127
- type="button"
128
- aria-label="Next ${this.preset??`date range`}"
129
- @click=${e=>this.shiftDateRange(1,e)}
130
- ?disabled=${this.disabled||!this.start||!this.end||!this.canNavigateForward()}
131
- >
132
- arrow_right
133
- </schmancy-icon-button>
134
- </section>
135
-
136
- ${e?s.html`<div role="alert" class="text-error-default text-sm mt-1">${this.validationMessage}</div>`:s.nothing}
137
- </div>
138
- `}};t.u([(0,o.property)()],h.prototype,`type`,void 0),t.u([(0,o.property)()],h.prototype,`start`,void 0),t.u([(0,o.property)()],h.prototype,`end`,void 0),t.u([(0,o.property)({type:Array})],h.prototype,`presets`,void 0),t.u([(0,o.property)({reflect:!0})],h.prototype,`preset`,void 0),t.u([(0,o.property)()],h.prototype,`min`,void 0),t.u([(0,o.property)()],h.prototype,`max`,void 0),t.u([(0,o.property)()],h.prototype,`placeholder`,void 0),t.u([(0,o.property)({type:Boolean})],h.prototype,`clearable`,void 0),t.u([(0,o.property)()],h.prototype,`step`,void 0),t.u([(0,o.property)({type:Boolean})],h.prototype,`collapse`,void 0),t.u([(0,o.state)()],h.prototype,`isOpen`,void 0),t.u([(0,o.state)()],h.prototype,`announceMessage`,void 0),h=t.u([(0,o.customElement)(`schmancy-date-range`)],h),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return h}});
@@ -1 +0,0 @@
1
- {"version":3,"file":"date-range-CVAWMdar.cjs","names":[],"sources":["../node_modules/dayjs/plugin/quarterOfYear.js","../src/form/fields/date-range/date-range-helpers.ts","../src/form/fields/date-range/date-range-dialog.ts","../src/form/fields/date-range/date-range.ts"],"sourcesContent":["!function(t,n){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=n():\"function\"==typeof define&&define.amd?define(n):(t=\"undefined\"!=typeof globalThis?globalThis:t||self).dayjs_plugin_quarterOfYear=n()}(this,(function(){\"use strict\";var t=\"month\",n=\"quarter\";return function(e,i){var r=i.prototype;r.quarter=function(t){return this.$utils().u(t)?Math.ceil((this.month()+1)/3):this.month(this.month()%3+3*(t-1))};var s=r.add;r.add=function(e,i){return e=Number(e),this.$utils().p(i)===n?this.add(3*e,t):s.bind(this)(e,i)};var u=r.startOf;r.startOf=function(e,i){var r=this.$utils(),s=!!r.u(i)||i;if(r.p(e)===n){var o=this.quarter()-1;return s?this.month(3*o).startOf(t).startOf(\"day\"):this.month(3*o+2).endOf(t).endOf(\"day\")}return u.bind(this)(e,i)}}}));","import dayjs from 'dayjs'\n\n/**\n * Format a date range into a human-readable string\n */\nexport function formatDateRange(\n\tfromValue: string,\n\ttoValue: string,\n\ttype: 'date' | 'datetime-local',\n\tplaceholder: string,\n): string {\n\tif (!fromValue || !toValue) {\n\t\treturn placeholder\n\t}\n\n\tconst fromDate = dayjs(fromValue)\n\tconst toDate = dayjs(toValue)\n\n\tif (!fromDate.isValid() || !toDate.isValid()) {\n\t\treturn placeholder\n\t}\n\n\t// Format times if needed (for datetime-local)\n\tconst fromTime = type === 'datetime-local' ? fromDate.format(' h:mm A') : ''\n\tconst toTime = type === 'datetime-local' ? toDate.format(' h:mm A') : ''\n\n\t// Check if same day\n\tif (fromDate.isSame(toDate, 'day')) {\n\t\treturn `${fromDate.format('ddd, MMM D, YYYY')}${fromTime}`\n\t}\n\n\t// Check if same month and year\n\tif (fromDate.isSame(toDate, 'month') && fromDate.isSame(toDate, 'year')) {\n\t\treturn `${fromDate.format('ddd MMM D')} - ${toDate.format('ddd D, YYYY')}${toTime}`\n\t}\n\n\t// Check if same year\n\tif (fromDate.isSame(toDate, 'year')) {\n\t\treturn `${fromDate.format('ddd MMM D')} - ${toDate.format('ddd MMM D, YYYY')}${toTime}`\n\t}\n\n\t// Different years\n\treturn `${fromDate.format('ddd MMM D, YYYY')}${fromTime} - ${toDate.format('ddd MMM D, YYYY')}${toTime}`\n}\n\n/**\n * Detect the type of date range (full month, full quarter, etc.)\n */\nexport interface DateRangeType {\n\tisFullMonth: boolean\n\tisFullQuarter: boolean\n\tisFullYear: boolean\n\tisFullWeek: boolean\n}\n\nexport function detectDateRangeType(fromDate: dayjs.Dayjs, toDate: dayjs.Dayjs): DateRangeType {\n\treturn {\n\t\tisFullMonth: fromDate.date() === 1 && toDate.isSame(fromDate.endOf('month'), 'day'),\n\t\tisFullQuarter: fromDate.isSame(fromDate.startOf('quarter'), 'day') && toDate.isSame(toDate.endOf('quarter'), 'day'),\n\t\tisFullYear: fromDate.isSame(fromDate.startOf('year'), 'day') && toDate.isSame(toDate.endOf('year'), 'day'),\n\t\tisFullWeek: fromDate.day() === 0 && toDate.day() === 6 && toDate.diff(fromDate, 'days') === 6,\n\t}\n}\n","import { SchmancyElement } from '@mixins/index'\nimport dayjs from 'dayjs'\nimport { css, html, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { repeat } from 'lit/directives/repeat.js'\nimport { when } from 'lit/directives/when.js'\nimport type { SchmancyCalendarChangeEvent, SchmancyCalendarInputEvent } from '../../../calendar/calendar'\n\nexport interface DateRangeDialogPreset {\n\tid: string\n\tlabel: string\n\tstart: string\n\tend: string\n}\n\n/**\n * Picker panel for `<schmancy-date-range>`.\n *\n * Layout: sticky chip quick-rail → continuous-scroll calendar → secondary typed path.\n * Emits composed events that `<schmancy-date-range>` bridges into its own\n * `input`/`change` events.\n *\n * @element schmancy-date-range-dialog\n * @fires calendar-input - Provisional sweep from the calendar { start, end }\n * @fires calendar-change - Committed endpoint from the calendar { start, end }\n * @fires preset-select - A chip was clicked { id, label, start, end }\n */\n@customElement('schmancy-date-range-dialog')\nexport class SchmancyDateRangeDialog extends SchmancyElement {\n\tstatic styles = [\n\t\tcss`\n\t\t\t:host {\n\t\t\t\tdisplay: block;\n\t\t\t}\n\t\t`,\n\t]\n\n\t@property() type: 'date' | 'datetime-local' = 'date'\n\t@property() start: string | null = null\n\t@property() end: string | null = null\n\t@property() min?: string\n\t@property() max?: string\n\t@property() preset: string | null = null\n\t@property({ type: Array }) presets: DateRangeDialogPreset[] = []\n\n\tprivate handleCalendarInput(e: SchmancyCalendarInputEvent) {\n\t\te.stopPropagation()\n\t\tthis.dispatchEvent(\n\t\t\tnew CustomEvent('calendar-input', {\n\t\t\t\tdetail: { start: e.detail.start, end: e.detail.end },\n\t\t\t\tbubbles: true,\n\t\t\t\tcomposed: true,\n\t\t\t}),\n\t\t)\n\t}\n\n\tprivate handleCalendarChange(e: SchmancyCalendarChangeEvent) {\n\t\te.stopPropagation()\n\t\tthis.dispatchEvent(\n\t\t\tnew CustomEvent('calendar-change', {\n\t\t\t\tdetail: { start: e.detail.start, end: e.detail.end },\n\t\t\t\tbubbles: true,\n\t\t\t\tcomposed: true,\n\t\t\t}),\n\t\t)\n\t}\n\n\tprivate handlePresetClick(p: DateRangeDialogPreset) {\n\t\tthis.dispatchEvent(\n\t\t\tnew CustomEvent('preset-select', {\n\t\t\t\tdetail: p,\n\t\t\t\tbubbles: true,\n\t\t\t\tcomposed: true,\n\t\t\t}),\n\t\t)\n\t}\n\n\tprivate handleFromChange(e: Event) {\n\t\tconst value = (e.target as HTMLInputElement).value\n\t\tif (!value) return\n\t\t// Swap if end is earlier than the new start\n\t\tconst newStart = value\n\t\tconst newEnd =\n\t\t\tthis.end && dayjs(this.end).isBefore(dayjs(newStart)) ? newStart : (this.end ?? null)\n\t\tthis.dispatchEvent(\n\t\t\tnew CustomEvent('calendar-change', {\n\t\t\t\tdetail: { start: newStart, end: newEnd },\n\t\t\t\tbubbles: true,\n\t\t\t\tcomposed: true,\n\t\t\t}),\n\t\t)\n\t}\n\n\tprivate handleToChange(e: Event) {\n\t\tconst value = (e.target as HTMLInputElement).value\n\t\tif (!value) return\n\t\tthis.dispatchEvent(\n\t\t\tnew CustomEvent('calendar-change', {\n\t\t\t\tdetail: { start: this.start ?? null, end: value },\n\t\t\t\tbubbles: true,\n\t\t\t\tcomposed: true,\n\t\t\t}),\n\t\t)\n\t}\n\n\trender() {\n\t\treturn html`\n\t\t\t<div class=\"flex flex-col w-full\" style=\"min-width:280px; max-width:360px\">\n\t\t\t\t<!-- Sticky chip quick-rail -->\n\t\t\t\t<div\n\t\t\t\t\tpart=\"presets\"\n\t\t\t\t\tclass=\"sticky top-0 z-20 bg-surface-default flex flex-wrap gap-2 p-3 border-b border-outline-variant/40\"\n\t\t\t\t>\n\t\t\t\t\t${when(\n\t\t\t\t\t\tthis.presets.length > 0,\n\t\t\t\t\t\t() => html`\n\t\t\t\t\t\t\t${repeat(\n\t\t\t\t\t\t\t\tthis.presets,\n\t\t\t\t\t\t\t\tp => p.id,\n\t\t\t\t\t\t\t\tp => html`\n\t\t\t\t\t\t\t\t\t<schmancy-filter-chip\n\t\t\t\t\t\t\t\t\t\tpart=\"preset ${this.preset === p.id ? 'preset-selected' : ''}\"\n\t\t\t\t\t\t\t\t\t\t.value=${p.id}\n\t\t\t\t\t\t\t\t\t\t.selected=${this.preset === p.id}\n\t\t\t\t\t\t\t\t\t\ttitle=\"${p.start} — ${p.end}\"\n\t\t\t\t\t\t\t\t\t\t@click=${() => this.handlePresetClick(p)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t${p.label}\n\t\t\t\t\t\t\t\t\t</schmancy-filter-chip>\n\t\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t`,\n\t\t\t\t\t\t() => nothing,\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t<!-- Calendar (continuous-scroll range picker) -->\n\t\t\t\t<div part=\"calendar\" class=\"overflow-y-auto\" style=\"max-height:320px\">\n\t\t\t\t\t<schmancy-calendar\n\t\t\t\t\t\tmode=\"range\"\n\t\t\t\t\t\t.type=${this.type}\n\t\t\t\t\t\t.start=${this.start}\n\t\t\t\t\t\t.end=${this.end}\n\t\t\t\t\t\tmin=${ifDefined(this.min)}\n\t\t\t\t\t\tmax=${ifDefined(this.max)}\n\t\t\t\t\t\t@input=${(e: SchmancyCalendarInputEvent) => this.handleCalendarInput(e)}\n\t\t\t\t\t\t@change=${(e: SchmancyCalendarChangeEvent) => this.handleCalendarChange(e)}\n\t\t\t\t\t></schmancy-calendar>\n\t\t\t\t</div>\n\n\t\t\t\t<!-- Secondary typed-entry path -->\n\t\t\t\t<div class=\"flex gap-2 p-3 border-t border-outline-variant/40 flex-wrap\">\n\t\t\t\t\t<div class=\"flex-1 min-w-30\">\n\t\t\t\t\t\t<schmancy-input\n\t\t\t\t\t\t\t.type=${this.type}\n\t\t\t\t\t\t\t.label=${'From'}\n\t\t\t\t\t\t\t.value=${this.start ?? ''}\n\t\t\t\t\t\t\tmin=${ifDefined(this.min)}\n\t\t\t\t\t\t\tmax=${ifDefined(this.max)}\n\t\t\t\t\t\t\t@change=${this.handleFromChange}\n\t\t\t\t\t\t></schmancy-input>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"flex-1 min-w-30\">\n\t\t\t\t\t\t<schmancy-input\n\t\t\t\t\t\t\t.type=${this.type}\n\t\t\t\t\t\t\t.label=${'To'}\n\t\t\t\t\t\t\t.value=${this.end ?? ''}\n\t\t\t\t\t\t\tmin=${ifDefined(this.start ?? this.min)}\n\t\t\t\t\t\t\tmax=${ifDefined(this.max)}\n\t\t\t\t\t\t\t@change=${this.handleToChange}\n\t\t\t\t\t\t></schmancy-input>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-date-range-dialog': SchmancyDateRangeDialog\n\t}\n}\n","import dayjs from 'dayjs'\nimport quarterOfYear from 'dayjs/plugin/quarterOfYear'\nimport { html, nothing, PropertyValues } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport {\n\tconcat,\n\texhaustMap,\n\tfinalize,\n\tfromEvent,\n\tmap,\n\tmerge,\n\tof,\n\tSubject,\n\tswitchMap,\n\ttakeUntil,\n\ttap,\n\ttimer,\n} from 'rxjs'\nimport { SchmancyFormField } from '@mixins/index'\nimport { show } from '../../../overlay/overlay.service'\nimport { detectDateRangeType, formatDateRange } from './date-range-helpers'\nimport './date-range-dialog'\nimport type { DateRangeDialogPreset } from './date-range-dialog'\n\ndayjs.extend(quarterOfYear)\n\n// ---------------------------------------------------------------------------\n// Default built-in presets\n// ---------------------------------------------------------------------------\n\nfunction buildDefaultPresets(): DateRangeDialogPreset[] {\n\treturn [\n\t\t{\n\t\t\tid: 'today',\n\t\t\tlabel: 'Today',\n\t\t\tstart: dayjs().startOf('day').format('YYYY-MM-DD'),\n\t\t\tend: dayjs().endOf('day').format('YYYY-MM-DD'),\n\t\t},\n\t\t{\n\t\t\tid: 'yesterday',\n\t\t\tlabel: 'Yesterday',\n\t\t\tstart: dayjs().subtract(1, 'day').startOf('day').format('YYYY-MM-DD'),\n\t\t\tend: dayjs().subtract(1, 'day').endOf('day').format('YYYY-MM-DD'),\n\t\t},\n\t\t{\n\t\t\tid: 'last7',\n\t\t\tlabel: 'Last 7 days',\n\t\t\tstart: dayjs().subtract(6, 'day').startOf('day').format('YYYY-MM-DD'),\n\t\t\tend: dayjs().endOf('day').format('YYYY-MM-DD'),\n\t\t},\n\t\t{\n\t\t\tid: 'last30',\n\t\t\tlabel: 'Last 30 days',\n\t\t\tstart: dayjs().subtract(29, 'day').startOf('day').format('YYYY-MM-DD'),\n\t\t\tend: dayjs().endOf('day').format('YYYY-MM-DD'),\n\t\t},\n\t\t{\n\t\t\tid: 'thisWeek',\n\t\t\tlabel: 'This week',\n\t\t\tstart: dayjs().startOf('week').format('YYYY-MM-DD'),\n\t\t\tend: dayjs().endOf('week').format('YYYY-MM-DD'),\n\t\t},\n\t\t{\n\t\t\tid: 'thisMonth',\n\t\t\tlabel: 'This month',\n\t\t\tstart: dayjs().startOf('month').format('YYYY-MM-DD'),\n\t\t\tend: dayjs().endOf('month').format('YYYY-MM-DD'),\n\t\t},\n\t\t{\n\t\t\tid: 'lastMonth',\n\t\t\tlabel: 'Last month',\n\t\t\tstart: dayjs().subtract(1, 'month').startOf('month').format('YYYY-MM-DD'),\n\t\t\tend: dayjs().subtract(1, 'month').endOf('month').format('YYYY-MM-DD'),\n\t\t},\n\t\t{\n\t\t\tid: 'thisYear',\n\t\t\tlabel: 'This year',\n\t\t\tstart: dayjs().startOf('year').format('YYYY-MM-DD'),\n\t\t\tend: dayjs().endOf('year').format('YYYY-MM-DD'),\n\t\t},\n\t]\n}\n\n// ---------------------------------------------------------------------------\n// Event types\n// ---------------------------------------------------------------------------\n\nexport type SchmancyDateRangeInputEvent = CustomEvent<{\n\tstart: string | null\n\tend: string | null\n}>\n\nexport type SchmancyDateRangeChangeEvent = CustomEvent<{\n\tstart: string | null\n\tend: string | null\n\tpreset: string | null\n}>\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * A date range selector composing `<schmancy-calendar mode=\"range\">` with a\n * sticky preset chip quick-rail and a secondary typed-entry path.\n *\n * Public API: flat ISO `start`/`end`, `preset` read-back, `presets` array.\n * FormData: `${name}.start` / `${name}.end` (empty endpoint omitted).\n *\n * @element schmancy-date-range\n * @fires input - Provisional sweep preview { start, end }\n * @fires change - Committed range change { start, end, preset }\n */\n@customElement('schmancy-date-range')\nexport class SchmancyDateRange extends SchmancyFormField() {\n\t// `name`, `disabled`, `required`, `error`, `validationMessage`, `id`,\n\t// `validateOn`, `touched`, `submitted`, `markTouched`, `markSubmitted`,\n\t// FACE wiring, FIELD_CONNECT_EVENT dispatch — all from the mixin.\n\n\t@property() type: 'date' | 'datetime-local' = 'date'\n\t@property() start: string | null = null\n\t@property() end: string | null = null\n\n\t@property({ type: Array }) presets: DateRangeDialogPreset[] = buildDefaultPresets()\n\n\t/** Selected preset id; null = custom range. Reflects to attribute. */\n\t@property({ reflect: true }) preset: string | null = null\n\n\t@property() min?: string\n\t@property() max?: string\n\t@property() placeholder = 'Select date range'\n\t@property({ type: Boolean }) clearable = true\n\t@property() step?: 'day' | 'week' | 'month' | 'year' | number\n\t/** Collapses to an icon-only button on narrow viewports. */\n\t@property({ type: Boolean }) collapse = false\n\n\t// Session subjects — ONE_PIPELINE_ONE_SUBSCRIBE in connectedCallback.\n\tprivate readonly open$ = new Subject<MouseEvent | undefined>()\n\tprivate readonly close$ = new Subject<void>()\n\tprivate readonly announce$ = new Subject<string>()\n\n\t@state() private isOpen = false\n\t@state() private announceMessage = ''\n\n\t// Default-capture for formResetCallback\n\tprivate startDefault: string | null = null\n\tprivate endDefault: string | null = null\n\tprivate presetDefault: string | null = null\n\n\toverride disconnectedCallback(): void {\n\t\tsuper.disconnectedCallback()\n\t\tthis.isOpen = false\n\t}\n\n\toverride connectedCallback(): void {\n\t\tsuper.connectedCallback()\n\n\t\t// One pipeline (rxjs ONE_PIPELINE_ONE_SUBSCRIBE).\n\t\tmerge(\n\t\t\t// Overlay session (rxjs SESSIONS_USE_HIGHER_ORDER_OBSERVABLES).\n\t\t\tthis.open$.pipe(\n\t\t\t\ttap(() => {\n\t\t\t\t\tthis.isOpen = true\n\t\t\t\t}),\n\t\t\t\texhaustMap(anchor =>\n\t\t\t\t\tshow(\n\t\t\t\t\t\t// Reactive factory — closed-over props read fresh on each mount.\n\t\t\t\t\t\t() => html`\n\t\t\t\t\t\t\t<schmancy-date-range-dialog\n\t\t\t\t\t\t\t\t.type=${this.type}\n\t\t\t\t\t\t\t\t.start=${this.start}\n\t\t\t\t\t\t\t\t.end=${this.end}\n\t\t\t\t\t\t\t\t.min=${this.min}\n\t\t\t\t\t\t\t\t.max=${this.max}\n\t\t\t\t\t\t\t\t.preset=${this.preset}\n\t\t\t\t\t\t\t\t.presets=${this.presets}\n\t\t\t\t\t\t\t\t@calendar-input=${(ev: CustomEvent<{ start: string | null; end: string | null }>) => {\n\t\t\t\t\t\t\t\t\tev.stopPropagation()\n\t\t\t\t\t\t\t\t\tthis.dispatchEvent(\n\t\t\t\t\t\t\t\t\t\tnew CustomEvent('input', {\n\t\t\t\t\t\t\t\t\t\t\tdetail: { start: ev.detail.start, end: ev.detail.end },\n\t\t\t\t\t\t\t\t\t\t\tbubbles: true,\n\t\t\t\t\t\t\t\t\t\t\tcomposed: true,\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t@calendar-change=${(ev: CustomEvent<{ start: string | null; end: string | null }>) => {\n\t\t\t\t\t\t\t\t\tev.stopPropagation()\n\t\t\t\t\t\t\t\t\tthis.commitRange(ev.detail.start, ev.detail.end, null)\n\t\t\t\t\t\t\t\t\t// Two endpoints set → close overlay\n\t\t\t\t\t\t\t\t\tif (ev.detail.start && ev.detail.end) {\n\t\t\t\t\t\t\t\t\t\tev.target?.dispatchEvent(new CustomEvent('close', { bubbles: true, composed: true }))\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t@preset-select=${(ev: CustomEvent<DateRangeDialogPreset>) => {\n\t\t\t\t\t\t\t\t\tev.stopPropagation()\n\t\t\t\t\t\t\t\t\tthis.commitRange(ev.detail.start, ev.detail.end, ev.detail.id)\n\t\t\t\t\t\t\t\t\tev.target?.dispatchEvent(new CustomEvent('close', { bubbles: true, composed: true }))\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t></schmancy-date-range-dialog>\n\t\t\t\t\t\t`,\n\t\t\t\t\t\t{ anchor },\n\t\t\t\t\t).pipe(\n\t\t\t\t\t\ttakeUntil(this.close$),\n\t\t\t\t\t\tfinalize(() => {\n\t\t\t\t\t\t\tthis.isOpen = false\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\n\t\t\t// Screen-reader announcements.\n\t\t\tthis.announce$.pipe(\n\t\t\t\tswitchMap(message => concat(of(message), timer(1500).pipe(map(() => '')))),\n\t\t\t\ttap(message => {\n\t\t\t\t\tthis.announceMessage = message\n\t\t\t\t}),\n\t\t\t),\n\n\t\t\t// Document keyboard navigation.\n\t\t\tfromEvent<KeyboardEvent>(document, 'keydown').pipe(tap(ev => this.handleKeyDown(ev))),\n\t\t)\n\t\t\t.pipe(takeUntil(this.disconnecting))\n\t\t\t.subscribe()\n\t}\n\n\t// -------------------------------------------------------------------------\n\t// Mixin overrides — FormData, validity, dirty, reset\n\t// -------------------------------------------------------------------------\n\n\toverride willUpdate(changed: PropertyValues): void {\n\t\tsuper.willUpdate(changed)\n\t\tif (changed.has('start') || changed.has('end') || changed.has('name') || changed.has('disabled')) {\n\t\t\tif (this.name && !this.disabled) {\n\t\t\t\tconst fd = new FormData()\n\t\t\t\tif (this.start) fd.append(`${this.name}.start`, this.start)\n\t\t\t\tif (this.end) fd.append(`${this.name}.end`, this.end)\n\t\t\t\tthis.internals?.setFormValue(fd.has(`${this.name}.start`) || fd.has(`${this.name}.end`) ? fd : null)\n\t\t\t} else {\n\t\t\t\tthis.internals?.setFormValue(null)\n\t\t\t}\n\t\t\tthis.checkValidity()\n\t\t}\n\t\tif (changed.has('required')) {\n\t\t\tthis.checkValidity()\n\t\t}\n\t}\n\n\toverride checkValidity(): boolean {\n\t\tif (this.disabled) {\n\t\t\tthis.internals?.setValidity({})\n\t\t\treturn true\n\t\t}\n\t\tif (this.required && (!this.start || !this.end)) {\n\t\t\tconst msg = 'Please select a complete date range.'\n\t\t\tthis.internals?.setValidity({ valueMissing: true }, msg)\n\t\t\tif (this.shouldShowError()) {\n\t\t\t\tthis.error = true\n\t\t\t\tthis.validationMessage = msg\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t\tif (this.start && this.end && this.end < this.start) {\n\t\t\tconst msg = 'End date must be on or after start date.'\n\t\t\tthis.internals?.setValidity({ customError: true }, msg)\n\t\t\tif (this.shouldShowError()) {\n\t\t\t\tthis.error = true\n\t\t\t\tthis.validationMessage = msg\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t\tthis.internals?.setValidity({})\n\t\tif (this.shouldShowError()) {\n\t\t\tthis.error = false\n\t\t\tthis.validationMessage = ''\n\t\t}\n\t\treturn true\n\t}\n\n\toverride toFormEntries(): Array<[string, FormDataEntryValue]> {\n\t\tif (!this.name || this.disabled) return []\n\t\tconst entries: Array<[string, FormDataEntryValue]> = []\n\t\tif (this.start) entries.push([`${this.name}.start`, this.start])\n\t\tif (this.end) entries.push([`${this.name}.end`, this.end])\n\t\treturn entries\n\t}\n\n\toverride get dirty(): boolean {\n\t\treturn this.start !== this.startDefault || this.end !== this.endDefault\n\t}\n\n\toverride firstUpdated(changed: PropertyValues): void {\n\t\tsuper.firstUpdated(changed)\n\t\tthis.startDefault = this.start\n\t\tthis.endDefault = this.end\n\t\tthis.presetDefault = this.preset\n\t}\n\n\toverride resetForm(): void {\n\t\tthis.start = this.startDefault\n\t\tthis.end = this.endDefault\n\t\tthis.preset = this.presetDefault\n\t\tthis.error = false\n\t\tthis.validationMessage = ''\n\t\tthis.touched = false\n\t\tthis.submitted = false\n\t\tthis.internals?.setValidity({})\n\t}\n\n\t// -------------------------------------------------------------------------\n\t// Internal helpers\n\t// -------------------------------------------------------------------------\n\n\tprivate commitRange(start: string | null, end: string | null, presetId: string | null): void {\n\t\tthis.start = start\n\t\tthis.end = end\n\t\tthis.preset = presetId\n\t\tthis.announce$.next(`Date range: ${this.displayLabel()}`)\n\t\tthis.emitChange({ start, end, preset: presetId })\n\t}\n\n\tprivate displayLabel(): string {\n\t\tif (this.preset) {\n\t\t\tconst p = this.presets.find(x => x.id === this.preset)\n\t\t\tif (p) return p.label\n\t\t}\n\t\treturn formatDateRange(this.start ?? '', this.end ?? '', this.type, this.placeholder)\n\t}\n\n\tprivate toggleDropdown(e: MouseEvent) {\n\t\te.stopPropagation()\n\t\tif (this.disabled || this.step !== undefined) return\n\t\tif (this.isOpen) {\n\t\t\tthis.close$.next()\n\t\t} else {\n\t\t\tthis.open$.next(e)\n\t\t}\n\t}\n\n\tprivate shiftDateRange(direction: number, e: Event) {\n\t\te.stopPropagation()\n\t\tif (!this.start || !this.end) return\n\n\t\tconst fromDate = dayjs(this.start)\n\t\tconst toDate = dayjs(this.end)\n\t\tif (!fromDate.isValid() || !toDate.isValid()) return\n\n\t\tconst dateFormat = this.type === 'date' ? 'YYYY-MM-DD' : 'YYYY-MM-DDTHH:mm'\n\t\tconst dir = direction > 0 ? 1 : -1\n\t\tconst daysDiff = toDate.diff(fromDate, 'day') + 1\n\n\t\tlet amount: number\n\t\tlet unit: dayjs.ManipulateType\n\n\t\tif (this.step !== undefined) {\n\t\t\tif (typeof this.step === 'number') {\n\t\t\t\tamount = dir * this.step\n\t\t\t\tunit = 'day'\n\t\t\t} else if (this.step === 'day') {\n\t\t\t\tamount = dir * daysDiff\n\t\t\t\tunit = 'day'\n\t\t\t} else {\n\t\t\t\tamount = dir\n\t\t\t\tunit = this.step\n\t\t\t}\n\t\t} else {\n\t\t\tconst rangeType = detectDateRangeType(fromDate, toDate)\n\t\t\tif (rangeType.isFullYear) {\n\t\t\t\tamount = dir\n\t\t\t\tunit = 'year'\n\t\t\t} else if (rangeType.isFullMonth) {\n\t\t\t\tamount = dir\n\t\t\t\tunit = 'month'\n\t\t\t} else if (rangeType.isFullWeek) {\n\t\t\t\tamount = dir\n\t\t\t\tunit = 'week'\n\t\t\t} else {\n\t\t\t\tamount = dir * daysDiff\n\t\t\t\tunit = 'day'\n\t\t\t}\n\t\t}\n\n\t\tconst newFrom = fromDate.add(amount, unit)\n\t\tconst newTo = toDate.add(amount, unit)\n\n\t\tif (this.min && newFrom.isBefore(dayjs(this.min))) return\n\t\tif (this.max && newTo.isAfter(dayjs(this.max))) return\n\n\t\tthis.commitRange(newFrom.format(dateFormat), newTo.format(dateFormat), null)\n\t}\n\n\tprivate handleKeyDown(ev: KeyboardEvent) {\n\t\tif (!this.start || !this.end || this.disabled) return\n\t\tconst target = ev.target as Node | null\n\t\tif (target !== this && !this.contains(target)) return\n\n\t\tswitch (ev.key) {\n\t\t\tcase 'PageUp':\n\t\t\t\tthis.shiftDateRange(-1, ev)\n\t\t\t\tev.preventDefault()\n\t\t\t\tbreak\n\t\t\tcase 'PageDown':\n\t\t\t\tthis.shiftDateRange(1, ev)\n\t\t\t\tev.preventDefault()\n\t\t\t\tbreak\n\t\t\tcase 'Home':\n\t\t\t\tif (ev.ctrlKey) {\n\t\t\t\t\tconst fmt = this.type === 'date' ? 'YYYY-MM-DD' : 'YYYY-MM-DDTHH:mm'\n\t\t\t\t\tconst from = dayjs(this.start)\n\t\t\t\t\tconst to = dayjs(this.end)\n\t\t\t\t\tconst monthStart = from.startOf('month')\n\t\t\t\t\tthis.commitRange(\n\t\t\t\t\t\tmonthStart.format(fmt),\n\t\t\t\t\t\tmonthStart.add(to.diff(from, 'day'), 'day').format(fmt),\n\t\t\t\t\t\tnull,\n\t\t\t\t\t)\n\t\t\t\t\tev.preventDefault()\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\tcase 'End':\n\t\t\t\tif (ev.ctrlKey) {\n\t\t\t\t\tconst fmt = this.type === 'date' ? 'YYYY-MM-DD' : 'YYYY-MM-DDTHH:mm'\n\t\t\t\t\tconst from = dayjs(this.start)\n\t\t\t\t\tconst to = dayjs(this.end)\n\t\t\t\t\tconst monthEnd = to.endOf('month')\n\t\t\t\t\tthis.commitRange(\n\t\t\t\t\t\tmonthEnd.subtract(to.diff(from, 'day'), 'day').format(fmt),\n\t\t\t\t\t\tmonthEnd.format(fmt),\n\t\t\t\t\t\tnull,\n\t\t\t\t\t)\n\t\t\t\t\tev.preventDefault()\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tprivate canNavigateBackward(): boolean {\n\t\tif (!this.start || !this.min) return true\n\t\treturn dayjs(this.start).isAfter(dayjs(this.min))\n\t}\n\n\tprivate canNavigateForward(): boolean {\n\t\tif (!this.end || !this.max) return true\n\t\treturn dayjs(this.end).isBefore(dayjs(this.max))\n\t}\n\n\t// -------------------------------------------------------------------------\n\t// Render\n\t// -------------------------------------------------------------------------\n\n\trender() {\n\t\tconst showError = this.error && !!this.validationMessage\n\t\tconst errorRing = showError ? ' rounded outline outline-2 outline-error-default' : ''\n\t\tconst label = this.displayLabel()\n\n\t\treturn html`\n\t\t\t<div class=\"relative ${this.disabled ? 'opacity-60 pointer-events-none' : ''}\">\n\t\t\t\t<!-- Screen reader announcements -->\n\t\t\t\t<div class=\"sr-only\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">${this.announceMessage}</div>\n\n\t\t\t\t<!-- Collapsed: icon-only on narrow viewports when collapse=true -->\n\t\t\t\t<schmancy-icon-button\n\t\t\t\t\tclass=\"${this.collapse ? 'lg:hidden' : 'hidden'}${errorRing}\"\n\t\t\t\t\tvariant=\"outlined\"\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\taria-invalid=${showError ? 'true' : 'false'}\n\t\t\t\t\taria-label=\"Select date range. Current: ${label}\"\n\t\t\t\t\t@click=${(e: MouseEvent) => this.toggleDropdown(e)}\n\t\t\t\t\t?disabled=${this.disabled}\n\t\t\t\t>\n\t\t\t\t\tdate_range\n\t\t\t\t</schmancy-icon-button>\n\n\t\t\t\t<!-- Full trigger row: [← | range label | →] -->\n\t\t\t\t<section\n\t\t\t\t\t@click=${(ev: Event) => ev.stopPropagation()}\n\t\t\t\t\taria-invalid=${showError ? 'true' : 'false'}\n\t\t\t\t\tclass=\"${this.collapse ? 'hidden lg:flex' : 'flex'}${errorRing}\"\n\t\t\t\t>\n\t\t\t\t\t<schmancy-icon-button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\taria-label=\"Previous ${this.preset ?? 'date range'}\"\n\t\t\t\t\t\t@click=${(e: Event) => this.shiftDateRange(-1, e)}\n\t\t\t\t\t\t?disabled=${this.disabled || !this.start || !this.end || !this.canNavigateBackward()}\n\t\t\t\t\t>\n\t\t\t\t\t\tarrow_left\n\t\t\t\t\t</schmancy-icon-button>\n\n\t\t\t\t\t<schmancy-button\n\t\t\t\t\t\tclass=\"w-max\"\n\t\t\t\t\t\tvariant=\"outlined\"\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\taria-haspopup=\"dialog\"\n\t\t\t\t\t\taria-expanded=${this.isOpen}\n\t\t\t\t\t\taria-label=\"Select date range. Current: ${label}\"\n\t\t\t\t\t\taria-readonly=\"${this.step !== undefined}\"\n\t\t\t\t\t\t@click=${(e: MouseEvent) => this.toggleDropdown(e)}\n\t\t\t\t\t\t?disabled=${this.disabled}\n\t\t\t\t\t\tstyle=\"${this.step !== undefined ? 'cursor:default;' : ''}\"\n\t\t\t\t\t>\n\t\t\t\t\t\t${label}\n\t\t\t\t\t</schmancy-button>\n\n\t\t\t\t\t<schmancy-icon-button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\taria-label=\"Next ${this.preset ?? 'date range'}\"\n\t\t\t\t\t\t@click=${(e: Event) => this.shiftDateRange(1, e)}\n\t\t\t\t\t\t?disabled=${this.disabled || !this.start || !this.end || !this.canNavigateForward()}\n\t\t\t\t\t>\n\t\t\t\t\t\tarrow_right\n\t\t\t\t\t</schmancy-icon-button>\n\t\t\t\t</section>\n\n\t\t\t\t${showError\n\t\t\t\t\t? html`<div role=\"alert\" class=\"text-error-default text-sm mt-1\">${this.validationMessage}</div>`\n\t\t\t\t\t: nothing}\n\t\t\t</div>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-date-range': SchmancyDateRange\n\t}\n}\n"],"x_google_ignoreList":[0],"mappings":"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"}