@keenmate/pure-admin-core 2.4.0 → 2.5.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.
Files changed (44) hide show
  1. package/README.md +11 -6
  2. package/dist/css/main.css +47 -130
  3. package/package.json +1 -1
  4. package/snippets/AUDIT.md +94 -0
  5. package/snippets/alerts.html +264 -89
  6. package/snippets/badges.html +193 -61
  7. package/snippets/buttons.html +178 -0
  8. package/snippets/callouts.html +210 -129
  9. package/snippets/cards.html +383 -200
  10. package/snippets/checkbox-lists.html +199 -65
  11. package/snippets/code.html +55 -11
  12. package/snippets/command-palette.html +401 -111
  13. package/snippets/comparison.html +144 -93
  14. package/snippets/customization.html +311 -104
  15. package/snippets/data-display.html +584 -0
  16. package/snippets/detail-panel.html +470 -138
  17. package/snippets/filter-card.html +246 -0
  18. package/snippets/forms.html +408 -308
  19. package/snippets/grid.html +253 -141
  20. package/snippets/layout.html +379 -480
  21. package/snippets/lists.html +144 -47
  22. package/snippets/loaders.html +64 -39
  23. package/snippets/manifest.json +330 -280
  24. package/snippets/modal-dialogs.html +137 -64
  25. package/snippets/modals.html +221 -151
  26. package/snippets/notifications.html +285 -0
  27. package/snippets/popconfirm.html +213 -19
  28. package/snippets/profile.html +290 -330
  29. package/snippets/statistics.html +247 -0
  30. package/snippets/tables.html +359 -150
  31. package/snippets/tabs.html +129 -45
  32. package/snippets/timeline.html +123 -56
  33. package/snippets/toasts.html +179 -31
  34. package/snippets/tooltips.html +199 -81
  35. package/snippets/typography.html +183 -58
  36. package/snippets/utilities.html +511 -415
  37. package/snippets/virtual-scroll.html +201 -75
  38. package/snippets/web-daterangepicker.html +369 -189
  39. package/snippets/web-multiselect.html +360 -124
  40. package/src/scss/core-components/_alerts.scss +51 -12
  41. package/src/scss/core-components/_pagers.scss +1 -1
  42. package/src/scss/core-components/_popconfirm.scss +35 -13
  43. package/src/scss/core-components/_tables.scss +2 -134
  44. package/src/scss/variables/_components.scss +17 -2
@@ -1,9 +1,24 @@
1
- <!-- Web Date Range Picker Component
2
- Advanced date picker web component from @keenmate/web-daterangepicker
3
- Framework-agnostic, TypeScript-based web component with excellent features
4
- Repository: https://github.com/keenmate/web-daterangepicker
1
+ <!-- ================================
2
+ WEB DATE RANGE PICKER
3
+ A framework-agnostic web component from @keenmate/web-daterangepicker
4
+ (separate package; not part of pure-admin-core's CSS).
5
+
6
+ Pure Admin's role: themes export ~45 --base-* CSS variables (see
7
+ _base-css-variables.scss + _web-components-theme.scss bridge).
8
+ The component reads them via fallback chains:
9
+
10
+ 1. Page override : web-daterangepicker { --drp-accent-color: … }
11
+ 2. Theme base value: var(--base-accent-color)
12
+ 3. Hardcoded default: built into the component
13
+
14
+ So in a Pure Admin app you usually do NOT override --drp-* — the
15
+ theme already cascades. Override --drp-* only for one-off
16
+ instance-specific tweaks.
17
+
5
18
  Package: npm install @keenmate/web-daterangepicker
6
- -->
19
+ Repo: https://github.com/keenmate/web-daterangepicker
20
+ Auto-registers as <web-daterangepicker> on import.
21
+ ================================ -->
7
22
 
8
23
  <!-- ========================================
9
24
  BASIC USAGE
@@ -24,7 +39,11 @@
24
39
  date-format-mask="YYYY-MM-DD">
25
40
  </web-daterangepicker>
26
41
 
27
- <!-- Multiple Dates/Ranges Selection -->
42
+ <!-- Multiple Dates/Ranges Selection
43
+ Note: TypeScript narrows the public selectionMode property to
44
+ 'single' | 'range', but the underlying engine accepts 'multiple'
45
+ too — used in the demo (date-picker.mustache) for cherry-picking
46
+ several dates / ranges. -->
28
47
  <web-daterangepicker
29
48
  selection-mode="multiple"
30
49
  placeholder="Select multiple dates"
@@ -181,7 +200,12 @@ pastOnly.setAttribute('max-date', yesterday.toISOString().split('T')[0]);
181
200
  <script>
182
201
  const customBadges = document.getElementById('custom-badges');
183
202
 
184
- // Add metadata to dates (holidays, events, etc.)
203
+ // Callback returns DateInfo or null. DateInfo shape:
204
+ // { isDisabled?, badgeText?, badgeClass?, badgeTooltip?,
205
+ // dayClass?, dayTooltip? }
206
+ // badgeText goes in the badge row above the day number; badgeClass /
207
+ // dayClass let you compose with predefined .holiday / .event classes
208
+ // or your own.
185
209
  customBadges.getDateMetadataCallback = (date) => {
186
210
  const day = date.getDate();
187
211
  const month = date.getMonth();
@@ -189,32 +213,41 @@ customBadges.getDateMetadataCallback = (date) => {
189
213
  // New Year's Day
190
214
  if (month === 0 && day === 1) {
191
215
  return {
192
- badge: 'primary',
193
- tooltip: 'New Year\'s Day',
194
- label: 'Holiday'
216
+ badgeText: '🎉',
217
+ badgeClass: 'holiday',
218
+ badgeTooltip: "New Year's Day",
219
+ dayTooltip: 'Public holiday'
195
220
  };
196
221
  }
197
222
 
198
223
  // Valentine's Day
199
224
  if (month === 1 && day === 14) {
200
225
  return {
201
- badge: 'danger',
202
- tooltip: 'Valentine\'s Day',
203
- label: 'Holiday'
226
+ badgeText: '❤️',
227
+ badgeClass: 'holiday',
228
+ badgeTooltip: "Valentine's Day"
204
229
  };
205
230
  }
206
231
 
207
232
  // Team meetings on Mondays
208
233
  if (date.getDay() === 1) {
209
234
  return {
210
- badge: 'warning',
211
- tooltip: 'Team Meeting at 10 AM',
212
- label: 'Meeting'
235
+ badgeText: '📅',
236
+ badgeClass: 'event',
237
+ badgeTooltip: 'Team Meeting at 10 AM'
213
238
  };
214
239
  }
215
240
 
216
241
  return null;
217
242
  };
243
+
244
+ // Alternative: pre-built specialDates array (no callback overhead).
245
+ // Property names default to date / badgeText / badgeClass / badgeTooltip
246
+ // / dayClass / dayTooltip / isDisabled — override via *Member options.
247
+ customBadges.specialDates = [
248
+ { date: '2025-12-25', badgeText: '🎄', badgeTooltip: 'Christmas', badgeClass: 'holiday' },
249
+ { date: '2025-12-31', badgeText: '🎆', badgeTooltip: "New Year's Eve" }
250
+ ];
218
251
  </script>
219
252
 
220
253
  <!-- ========================================
@@ -250,32 +283,70 @@ disabledDates.getDateMetadataCallback = (date) => {
250
283
  </script>
251
284
 
252
285
  <!-- ========================================
253
- RANGE HANDLING MODES
286
+ RANGE HANDLING MODES (disabled-dates-handling)
287
+ Five modes for what happens when a selected range overlaps
288
+ disabled dates. Set via attribute OR property.
254
289
  ======================================== -->
255
290
 
256
- <!-- Allow Mode (default): Range can include disabled dates -->
291
+ <!-- allow (default): range spans disabled dates;
292
+ event detail includes enabledDates + disabledDates arrays -->
257
293
  <web-daterangepicker
258
294
  selection-mode="range"
259
295
  visible-months-count="2"
260
296
  disabled-weekdays="0,6"
261
- placeholder="Range includes weekends"
297
+ disabled-dates-handling="allow"
298
+ placeholder="Range includes weekends (counted separately)"
262
299
  date-format-mask="YYYY-MM-DD">
263
300
  </web-daterangepicker>
264
301
 
265
- <!-- Block Mode: Range stops at disabled dates -->
302
+ <!-- block: range end snaps to last enabled date before any gap -->
266
303
  <web-daterangepicker
267
- id="block-mode"
268
304
  selection-mode="range"
269
305
  visible-months-count="2"
270
306
  disabled-weekdays="0,6"
307
+ disabled-dates-handling="block"
271
308
  placeholder="Range stops at weekends"
272
309
  date-format-mask="YYYY-MM-DD">
273
310
  </web-daterangepicker>
274
311
 
275
- <!-- Note: Range handling mode is set via JavaScript property, not attribute -->
312
+ <!-- prevent: range can't be selected at all if it would cross disabled -->
313
+ <web-daterangepicker
314
+ selection-mode="range"
315
+ visible-months-count="2"
316
+ disabled-weekdays="0,6"
317
+ disabled-dates-handling="prevent"
318
+ placeholder="Selection rejected if it crosses disabled dates"
319
+ date-format-mask="YYYY-MM-DD">
320
+ </web-daterangepicker>
321
+
322
+ <!-- split: returns multiple ranges separated by disabled gaps;
323
+ event detail.dateRanges is DateRange[] -->
324
+ <web-daterangepicker
325
+ selection-mode="range"
326
+ visible-months-count="2"
327
+ disabled-weekdays="0,6"
328
+ disabled-dates-handling="split"
329
+ placeholder="Split into weekday-only sub-ranges"
330
+ date-format-mask="YYYY-MM-DD">
331
+ </web-daterangepicker>
332
+
333
+ <!-- individual: returns a flat array of enabled dates only;
334
+ event detail.dates is Date[] -->
335
+ <web-daterangepicker
336
+ selection-mode="range"
337
+ visible-months-count="2"
338
+ disabled-weekdays="0,6"
339
+ disabled-dates-handling="individual"
340
+ placeholder="Each enabled day picked individually"
341
+ date-format-mask="YYYY-MM-DD">
342
+ </web-daterangepicker>
343
+
344
+ <!-- Equivalent JS: -->
276
345
  <script>
277
- const blockMode = document.getElementById('block-mode');
278
- // blockMode.disabledDatesHandling = 'block'; // Requires access to component API
346
+ // const picker = document.querySelector('web-daterangepicker');
347
+ // picker.setAttribute('disabled-dates-handling', 'block');
348
+ // or via the underlying picker engine:
349
+ // picker.picker.options.disabledDatesHandling = 'block';
279
350
  </script>
280
351
 
281
352
  <!-- ========================================
@@ -416,30 +487,33 @@ programmatic.addEventListener('change', (e) => {
416
487
  </web-daterangepicker>
417
488
 
418
489
  <!-- ========================================
419
- AUTO-CLOSE BEHAVIOR
490
+ AUTO-CLOSE BEHAVIOR (auto-close)
491
+ Three values: 'never' | 'selection' | 'apply'
420
492
  ======================================== -->
421
493
 
422
- <!-- Auto-close on single date selection -->
494
+ <!-- selection: close as soon as selection completes
495
+ (single date picked, or range end picked) -->
423
496
  <web-daterangepicker
424
497
  selection-mode="single"
425
- auto-close="on-select"
498
+ auto-close="selection"
426
499
  placeholder="Closes after selection"
427
500
  date-format-mask="YYYY-MM-DD">
428
501
  </web-daterangepicker>
429
502
 
430
- <!-- Auto-close on range completion -->
503
+ <!-- apply: stay open until the user clicks Apply -->
431
504
  <web-daterangepicker
432
505
  selection-mode="range"
433
- auto-close="on-select"
434
- placeholder="Closes after range selected"
506
+ show-apply-button="true"
507
+ auto-close="apply"
508
+ placeholder="Closes only when Apply clicked"
435
509
  date-format-mask="YYYY-MM-DD">
436
510
  </web-daterangepicker>
437
511
 
438
- <!-- Manual close only (use Apply button) -->
512
+ <!-- never: never auto-close; manage open/close yourself with show()/hide() -->
439
513
  <web-daterangepicker
440
514
  selection-mode="range"
441
- show-apply-button="true"
442
- placeholder="Requires Apply button"
515
+ auto-close="never"
516
+ placeholder="Stays open"
443
517
  date-format-mask="YYYY-MM-DD">
444
518
  </web-daterangepicker>
445
519
 
@@ -448,187 +522,293 @@ programmatic.addEventListener('change', (e) => {
448
522
  ======================================== -->
449
523
 
450
524
  <!--
451
- Core Attributes:
452
- - selection-mode: "single" | "range" | "multiple"
453
- - visible-months-count: Number of months to display (1-3)
454
- - placeholder: Input placeholder text
455
- - date-format-mask: Date format (YYYY-MM-DD, DD.MM.YYYY, MM/DD/YYYY, DD/MM/YYYY)
456
- - positioning-mode: "floating" (default) | "inline"
457
- - calendar-placement: Floating UI placement (bottom-start, bottom-end, etc.)
458
- - locale: Locale code (en, de, fr, es, etc.)
459
- - disabled: Disable the component
525
+ Source of truth: web-component.ts observedAttributes list. The full
526
+ set of attributes the web component accepts:
527
+
528
+ Core:
529
+ - selection-mode "single" (default) | "range" | "multiple"
530
+ - date-format-mask Format pattern. YYYY/YY, MM/M, DD/D with
531
+ separators -, /, . Default: YYYY-MM-DD
532
+ - display-format-mask Localized format shown to user (e.g.
533
+ "dd/mm/aaaa" in Spanish); validation still
534
+ uses date-format-mask
535
+ - visible-months-count Number of months on screen (default:
536
+ 1 single, 2 range)
537
+ - calendar-open-trigger "focus" (default) | "typing" | "manual"
538
+ - placeholder Input placeholder text
539
+ - value Current formatted value
540
+ - disabled Boolean attribute
541
+ - week-start-day "auto" (locale-based) | 0..6
542
+ - locale "auto" (default) | "en" | "de" | "fr" | "es" | …
543
+ - show-debug-info Boolean — enables loglevel debug output
544
+ - enable-transitions Boolean — opt-in CSS transitions
545
+
546
+ Layout (multi-month):
547
+ - positioning-mode "floating" (default) | "inline"
548
+ - calendar-placement Floating UI placement: bottom / top /
549
+ left / right / bottom-start / bottom-end / …
550
+ - month-layout "horizontal" (default) | "grid"
551
+ - grid-rows number (e.g. 2 for a 2×3 grid)
552
+ - grid-columns number (e.g. 3 for a 2×3 grid)
460
553
 
461
554
  Date Restrictions:
462
- - min-date: Minimum selectable date (YYYY-MM-DD)
463
- - max-date: Maximum selectable date (YYYY-MM-DD)
464
- - disabled-weekdays: Comma-separated day numbers (0=Sunday, 6=Saturday)
555
+ - min-date YYYY-MM-DD
556
+ - max-date YYYY-MM-DD
557
+ - disabled-weekdays "0,6" etc. (0=Sun, 6=Sat)
558
+ - disabled-dates-handling "allow" (default) | "block" | "prevent"
559
+ | "split" | "individual"
560
+ - highlight-disabled-in-range Boolean (default true)
561
+
562
+ Action Buttons (set "true" to show):
563
+ - show-today-button
564
+ - show-clear-button
565
+ - show-apply-button Defaults to true for range / multiple modes
566
+
567
+ Close Behavior:
568
+ - auto-close "never" | "selection" | "apply"
569
+ - close-on-scroll Boolean
570
+
571
+ Sizing (5-step scale, all default "md"):
572
+ - input-size xs | sm | md | lg | xl (input field)
573
+ - spacing xs | sm | md | lg | xl (calendar gaps)
574
+ - font-size xs | sm | md | lg | xl (calendar text)
575
+ - cell-size xs | sm | md | lg | xl (day cell size)
576
+ -->
465
577
 
466
- Action Buttons:
467
- - show-today-button: "true" | "false" (default)
468
- - show-clear-button: "true" | "false" (default)
469
- - show-apply-button: "true" | "false" (default)
578
+ <!-- ========================================
579
+ WRAPPER CLASSES (page-level, on a parent <div>)
580
+ Lets you scale font and spacing independently of the input-size /
581
+ spacing / font-size attributes handy when the picker lives
582
+ inside a section with its own density.
583
+ ======================================== -->
584
+
585
+ <!-- Compact spacing with large readable text -->
586
+ <div class="drp-font-lg drp-spacing-xs">
587
+ <web-daterangepicker selection-mode="single"></web-daterangepicker>
588
+ </div>
589
+
590
+ <!-- Responsive: scales font + spacing down at 1200px and 768px breakpoints -->
591
+ <div class="drp-font-md drp-spacing-md drp-responsive">
592
+ <web-daterangepicker selection-mode="range"></web-daterangepicker>
593
+ </div>
470
594
 
471
- Behavior:
472
- - auto-close: "on-select" | "manual" (default)
595
+ <!--
596
+ Wrapper class scales (multipliers defaults are 1.0×):
597
+ .drp-font-xs .drp-font-sm .drp-font-md .drp-font-lg .drp-font-xl
598
+ .drp-spacing-xs .drp-spacing-sm .drp-spacing-md .drp-spacing-lg .drp-spacing-xl
599
+ .drp-responsive — flips to a smaller scale below 1200px and again below 768px
473
600
  -->
474
601
 
602
+
475
603
  <!-- ========================================
476
- CSS THEMING (40+ Variables)
604
+ CSS CUSTOM PROPERTIES (--drp-*)
605
+ The component defines these on :host inside its shadow DOM, so
606
+ override them by targeting the element (NOT :root — :root inside
607
+ shadow DOM doesn't reach the component).
477
608
  ======================================== -->
478
609
 
479
610
  <style>
480
- /* Override CSS custom properties to match your theme */
481
- :root {
482
- /* Colors */
483
- --drp-accent-color: #007bff;
484
- --drp-primary-bg: #007bff;
485
- --drp-text-primary: #2c3e50;
486
- --drp-text-secondary: #6c757d;
487
- --drp-border-color: #e1e5e9;
488
- --drp-card-bg: #ffffff;
489
- --drp-hover-bg: #f8f9fa;
490
-
491
- /* Calendar */
492
- --drp-calendar-bg: #ffffff;
493
- --drp-calendar-shadow: 0 0 60px rgba(0, 0, 0, 0.12);
494
- --drp-calendar-border-radius: 4px;
495
- --drp-calendar-padding: 1rem;
496
-
497
- /* Days */
498
- --drp-day-size: 2.25rem;
499
- --drp-day-font-size: 0.875rem;
500
- --drp-day-border-radius: 2px;
501
- --drp-day-hover-bg: rgba(0, 123, 255, 0.1);
502
- --drp-day-selected-bg: #007bff;
503
- --drp-day-selected-text: #ffffff;
504
- --drp-day-range-bg: rgba(0, 123, 255, 0.05);
505
- --drp-day-today-border: #007bff;
506
- --drp-day-disabled-opacity: 0.65;
507
-
508
- /* Weekday Header */
509
- --drp-weekday-font-size: 0.75rem;
510
- --drp-weekday-font-weight: 600;
511
- --drp-weekday-text: #6c757d;
512
-
513
- /* Badges */
514
- --drp-badge-primary: #007bff;
515
- --drp-badge-success: #28a745;
516
- --drp-badge-warning: #ffc107;
517
- --drp-badge-danger: #dc3545;
518
- --drp-badge-info: #17a2b8;
519
-
520
- /* Input */
521
- --drp-input-bg: #ffffff;
522
- --drp-input-border: #ced4da;
523
- --drp-input-padding-v: 0.5rem;
524
- --drp-input-padding-h: 0.75rem;
525
- --drp-input-font-size: 0.875rem;
526
- --drp-input-border-radius: 4px;
527
- --drp-input-focus-border: #007bff;
528
-
529
- /* Action Buttons */
530
- --drp-action-btn-primary-bg: #007bff;
531
- --drp-action-btn-primary-text: #ffffff;
532
-
533
- /* Spacing */
534
- --drp-spacing-sm: 0.5rem;
535
- --drp-spacing-md: 0.75rem;
536
- --drp-spacing-base: 1rem;
537
-
538
- /* Animations */
539
- --drp-transition-normal: 0.15s;
540
- --drp-easing-smooth: ease;
611
+ /* Override on the element so the variables cascade into the shadow root */
612
+ web-daterangepicker {
613
+ --drp-accent-color: var(--pa-accent); /* hook into Pure Admin theme */
614
+ --drp-card-bg: var(--pa-card-bg);
615
+ --drp-text-primary: var(--pa-text-color-1);
616
+ --drp-text-secondary: var(--pa-text-color-2);
617
+ --drp-border-color: var(--pa-border-color);
618
+ --drp-border-radius: var(--pa-border-radius);
619
+ }
620
+
621
+ /* Scoped instance override (e.g. a "compact" variant on a search bar) */
622
+ web-daterangepicker.compact {
623
+ --drp-card-bg: #1e293b;
624
+ --drp-text-primary: #f1f5f9;
625
+ --drp-accent-color: #10b981;
541
626
  }
542
627
  </style>
543
628
 
629
+ <!--
630
+ Common --drp-* tokens (full list in API.md):
631
+
632
+ Colors --drp-card-bg, --drp-border-color, --drp-primary-bg,
633
+ --drp-primary-bg-hover, --drp-accent-color,
634
+ --drp-accent-color-hover, --drp-text-primary,
635
+ --drp-text-secondary, --drp-accent-text-color,
636
+ --drp-button-text-color
637
+ Spacing --drp-spacing-xs / -sm / -md / -lg / -xl
638
+ Typography --drp-font-size-{2xs..2xl}, --drp-font-weight-{medium,semibold}
639
+ Borders --drp-border-width-base, --drp-border-radius, --drp-shadow-xl
640
+ Transitions --drp-transition-fast, --drp-easing-snappy
641
+ Input sizes --drp-input-size-{xs|sm|md|lg|xl}-{font|padding-v|padding-h|height|icon-size}
642
+ Grid --drp-grid-rows, --drp-grid-columns (set automatically)
643
+
644
+ PURE ADMIN INTEGRATION:
645
+ packages/core/src/scss/core-components/_web-components-theme.scss
646
+ bridges Pure Admin's --base-* variables (set by themes) into the
647
+ daterangepicker's fallback chain. So in a Pure Admin app you usually
648
+ do NOT hand-set --drp-* — the theme already cascades. Override
649
+ --drp-* only for one-off tweaks like the .compact example above.
650
+ -->
651
+
544
652
  <!-- ========================================
545
653
  TYPESCRIPT TYPES
546
654
  ======================================== -->
547
655
 
548
656
  <!--
549
- TypeScript usage:
550
-
551
657
  import '@keenmate/web-daterangepicker';
552
- import type { DateRangePickerElement } from '@keenmate/web-daterangepicker';
553
-
554
- const picker = document.querySelector<DateRangePickerElement>('web-daterangepicker');
555
-
556
- if (picker) {
557
- // Type-safe API
558
- picker.addEventListener('date-select', (e: CustomEvent<{
559
- date?: string;
560
- dateRange?: { start: string; end: string };
561
- }>) => {
562
- console.log(e.detail);
563
- });
564
-
565
- // Validation callback
566
- picker.beforeDateSelectCallback = async (selection) => {
567
- return true; // or false to reject
568
- };
569
-
570
- // Custom rendering
571
- picker.getDateMetadataCallback = (date: Date) => {
572
- return {
573
- badge: 'primary',
574
- tooltip: 'Event',
575
- isDisabled: false
576
- };
577
- };
578
- }
579
- -->
658
+ import type { DatePickerOptions, DateRange, DecoratedDate, DateInfo }
659
+ from '@keenmate/web-daterangepicker';
580
660
 
581
- <!-- ========================================
582
- KEY FEATURES
583
- ======================================== -->
661
+ const picker = document.querySelector('web-daterangepicker');
584
662
 
585
- <!--
586
- Selection Modes: Single, range, and multiple date/range selection
587
- Keyboard Navigation: Full arrow key support with shortcuts (Ctrl+arrows, PageUp/Down, Home/End, Tab, T for today)
588
- ✅ Date Restrictions: Min/max dates, disabled weekdays, custom disabled dates
589
- ✅ Rolling Selector: Innovative month/year picker for quick navigation
590
- ✅ Custom Rendering: Badges, tooltips, and custom content for dates
591
- ✅ Validation: Async beforeDateSelectCallback for validation
592
- ✅ Action Buttons: Today, Clear, Apply buttons with customization
593
- ✅ Range Handling: 5 modes (allow, block, split, individual, prevent) for disabled dates
594
- ✅ Input Masking: Auto-format dates as user types
595
- ✅ Localization: Support for multiple languages and date formats
596
- ✅ Inline Mode: Display calendar directly on page instead of dropdown
597
- ✅ Framework Agnostic: Works with any framework or vanilla JS
598
- ✅ TypeScript: Full type definitions included
599
- ✅ Accessible: Keyboard-friendly with proper focus management
600
- ✅ Customizable: 40+ CSS variables for theming
601
- ✅ Dependencies: Only @floating-ui/dom for smart positioning
602
- -->
663
+ picker.addEventListener('date-select', (e) => {
664
+ // detail is a discriminated union by mode + disabled-dates-handling.
665
+ // See COMPONENT REFERENCE EVENTS below for the full shape.
666
+ console.log(e.detail);
667
+ });
603
668
 
604
- <!-- ========================================
605
- KEYBOARD SHORTCUTS
606
- ======================================== -->
669
+ picker.beforeDateSelectCallback = async (selection) => {
670
+ return true; // false to reject
671
+ };
607
672
 
608
- <!--
609
- Navigation:
610
- - ↑↓: Navigate by day (up/down)
611
- - ←→: Navigate by week (left/right)
612
- - Ctrl+←→: Previous/next month
613
- - PageUp/PageDown: Previous/next month
614
- - Home/End: First/last day of month
615
- - Ctrl+Home/End: First/last day of year
616
- - Tab: Switch between month columns (multi-month view)
617
- - T: Jump to today
618
-
619
- Actions:
620
- - Enter: Select focused day
621
- - Esc: Close calendar
622
- - Space: Toggle selection (in multiple mode)
673
+ picker.getDateMetadataCallback = (date) => ({
674
+ badgeText: 'E',
675
+ badgeClass: 'event',
676
+ badgeTooltip: 'Event',
677
+ isDisabled: false
678
+ });
623
679
  -->
624
680
 
625
- <!-- ========================================
626
- RESOURCES
627
- ======================================== -->
681
+
682
+ <!-- ================================
683
+ COMPONENT REFERENCE
684
+ ================================ -->
628
685
 
629
686
  <!--
630
- npm Package: @keenmate/web-daterangepicker
631
- Repository: https://github.com/keenmate/web-daterangepicker
632
- Documentation: See package README and ../../web-daterangepicker/ai/ for AI instructions
633
- Pure Admin Integration: src/scss/core-components/_web-components-theme.scss
687
+ SELECTION MODES:
688
+ single One date.
689
+ range Two dates with a fill in between.
690
+ multiple Cherry-pick individual dates / mini-ranges (TS narrows
691
+ public type to 'single' | 'range', but the engine
692
+ handles 'multiple' too — used in date-picker demo).
693
+
694
+ DATE METADATA — TWO PATHS:
695
+ 1. specialDates property (preferred for static data)
696
+ picker.specialDates = [
697
+ { date: '2025-12-25', badgeText: '🎄', badgeTooltip: 'Christmas' },
698
+
699
+ ];
700
+ Property names default to date / badgeText / badgeClass /
701
+ badgeTooltip / dayClass / dayTooltip / isDisabled — re-map via
702
+ dateMember / badgeTextMember / etc. when consuming an existing
703
+ dataset shape.
704
+
705
+ 2. getDateMetadataCallback (computed per render)
706
+ picker.getDateMetadataCallback = (date) => DateInfo | null;
707
+ DateInfo = { isDisabled?, badgeText?, badgeClass?, badgeTooltip?,
708
+ dayClass?, dayTooltip? }
709
+ Predefined classes you can hand to badgeClass / dayClass:
710
+ .holiday (red tint) and .event (green tint). Plus any custom class.
711
+
712
+ VALIDATION HOOK:
713
+ picker.beforeDateSelectCallback = async (selection) => boolean
714
+ Async-supported. Return false to reject; the calendar reverts.
715
+
716
+ EVENTS (both bubble, both composed — use either):
717
+ date-select Always fires on selection change.
718
+ change Alias of date-select.
719
+
720
+ event.detail shape varies by mode:
721
+ formattedValue always present
722
+ date single mode
723
+ dateRange { start, end } range mode (allow / block)
724
+ dateRanges DateRange[] range mode + split
725
+ dates Date[] range mode + split / individual
726
+ enabledDates / disabledDates range mode + allow
727
+ getEnabledDateCount() / getTotalDays() range + allow helpers
728
+
729
+ PUBLIC METHODS (on <web-daterangepicker> element):
730
+ show() / hide() / toggle() floating mode visibility
731
+ clearSelection() wipe all selections + input
732
+ getInputValue() current formatted string
733
+ setInputValue(v) set value + sync calendar
734
+ picker the underlying PureDatePicker
735
+ instance (deeper API: formatDate,
736
+ isDateDisabledInternal,
737
+ getEnabledDatesInRange, etc.)
738
+
739
+ SIZING:
740
+ Two coordinated paths:
741
+ a) Attributes (single instance):
742
+ input-size, spacing, font-size, cell-size — each xs..xl, default md.
743
+ b) Wrapper classes (parent <div>):
744
+ .drp-font-{xs..xl}, .drp-spacing-{xs..xl}, .drp-responsive
745
+
746
+ KEYBOARD:
747
+ Arrow keys navigate by day; up/down moves by week
748
+ Ctrl/Cmd + ←/→ or PgUp/PgDn prev / next month (keep day position)
749
+ Home / End first / last day of month (press again
750
+ for adjacent month)
751
+ Ctrl/Cmd + Home / End Jan 1 / Dec 31 of current year
752
+ Tab / Shift+Tab switch month column in multi-month view
753
+ Enter select focused day
754
+ Space toggle (multiple mode)
755
+ T / t jump to today
756
+ Esc close (floating mode)
757
+
758
+ CSS VARIABLE NAMESPACES:
759
+ --drp-* Component runtime tokens. Set on the element (not
760
+ :root — :root inside shadow DOM doesn't reach the
761
+ component).
762
+ --base-* Pure Admin theme bridge. Themes export ~45 of these
763
+ via output-base-css-variables; the component falls
764
+ back from --drp-* → var(--base-*, hardcoded). So
765
+ themes "just work"; only override --drp-* for one-off
766
+ instances.
767
+
768
+ LOAD ORDER:
769
+ Import the component once (auto-registers the custom element):
770
+ import '@keenmate/web-daterangepicker';
771
+ import '@keenmate/web-daterangepicker/style.css';
772
+ Pure Admin's CSS provides the --base-* values; the component picks
773
+ them up automatically.
774
+
775
+ STRUCTURE PATTERNS:
776
+
777
+ Basic single-date input:
778
+ <web-daterangepicker selection-mode="single"
779
+ date-format-mask="DD.MM.YYYY"
780
+ placeholder="Select date">
781
+ </web-daterangepicker>
782
+
783
+ Range with weekend block + apply button + auto-close on apply:
784
+ <web-daterangepicker selection-mode="range"
785
+ visible-months-count="2"
786
+ disabled-weekdays="0,6"
787
+ disabled-dates-handling="block"
788
+ show-apply-button="true"
789
+ auto-close="apply">
790
+ </web-daterangepicker>
791
+
792
+ 6-month inline grid for big picture views:
793
+ <web-daterangepicker selection-mode="single"
794
+ positioning-mode="inline"
795
+ visible-months-count="6"
796
+ month-layout="grid"
797
+ grid-rows="2" grid-columns="3">
798
+ </web-daterangepicker>
799
+
800
+ Localized display (validates ISO, displays Spanish):
801
+ <web-daterangepicker selection-mode="single"
802
+ locale="es"
803
+ date-format-mask="YYYY-MM-DD"
804
+ display-format-mask="dd/mm/aaaa">
805
+ </web-daterangepicker>
806
+
807
+ RESOURCES:
808
+ npm @keenmate/web-daterangepicker
809
+ Repository https://github.com/keenmate/web-daterangepicker
810
+ API docs ../../web-daterangepicker/API.md
811
+ AI guides ../../web-daterangepicker/ai/
812
+ Pure Admin src/scss/core-components/_web-components-theme.scss
813
+ bridges --base-* into the component's fallback chain.
634
814
  -->