kmaterialize 2.3.3-1.0.2 → 2.3.3-1.0.21

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 (42) hide show
  1. package/README.md +4 -4
  2. package/components/air-datepicker/_air-datepicker.scss +137 -0
  3. package/components/air-datepicker/air-datepicker.ts +192 -0
  4. package/components/alert/_alerts.scss +130 -0
  5. package/components/alert/alert.ts +73 -0
  6. package/components/appbar/appbar.css +301 -4
  7. package/components/button/_buttons.scss +39 -1
  8. package/components/card/_cards.scss +9 -1
  9. package/components/checkbox/_checkboxes.scss +120 -229
  10. package/components/collapsible/_collapsible.scss +50 -0
  11. package/components/color-input/_color-input.scss +124 -0
  12. package/components/color-input/color-input.ts +203 -0
  13. package/components/dropdown/dropdown.ts +1 -1
  14. package/components/file-input/_file-input-enhanced.scss +61 -0
  15. package/components/file-input/file-input.ts +203 -0
  16. package/components/kanban/_kanban.scss +148 -0
  17. package/components/kanban/kanban.ts +133 -0
  18. package/components/list/_collection.scss +10 -2
  19. package/components/number-input/number-input.ts +103 -0
  20. package/components/password-input/password-input.ts +72 -0
  21. package/components/slider/_range.scss +5 -1
  22. package/components/switch/_switches.scss +5 -0
  23. package/components/textfield/_input-fields.scss +4 -4
  24. package/components/textfield/_select.scss +54 -0
  25. package/components/tom-select/_tom-select-field.scss +256 -0
  26. package/components/tom-select/tom-select-field.ts +175 -0
  27. package/components/toolbar/_toolbar.scss +324 -0
  28. package/components/toolbar/toolbar.ts +152 -0
  29. package/dist/css/materialize.colors.min.css +2 -2
  30. package/dist/css/materialize.css +10575 -711
  31. package/dist/css/materialize.min.css +2 -2
  32. package/dist/css/materialize.min.css.map +1 -1
  33. package/dist/js/materialize.cjs.js +1136 -45
  34. package/dist/js/materialize.d.ts +227 -2
  35. package/dist/js/materialize.js +1136 -45
  36. package/dist/js/materialize.min.js +2 -2
  37. package/dist/js/materialize.mjs +1128 -46
  38. package/package.json +45 -1
  39. package/sass/_colors.scss +191 -5
  40. package/sass/_global.scss +240 -1
  41. package/sass/materialize.scss +14 -1
  42. package/sass/mixins.module.scss +6 -6
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Materialize v2.3.3-1.0.2 (https://materializeweb.com)
2
+ * Materialize v2.3.3-1.0.21 (https://materializeweb.com)
3
3
  * Copyright 2014-2026 Materialize
4
4
  * MIT License (https://raw.githubusercontent.com/materializecss/materialize/master/LICENSE)
5
5
  */
@@ -400,7 +400,7 @@ var M = (function (exports) {
400
400
  }
401
401
  }
402
402
 
403
- const _defaults$o = {
403
+ const _defaults$x = {
404
404
  alignment: 'left',
405
405
  autoFocus: true,
406
406
  constrainWidth: true,
@@ -453,7 +453,7 @@ var M = (function (exports) {
453
453
  this._setupEventHandlers();
454
454
  }
455
455
  static get defaults() {
456
- return _defaults$o;
456
+ return _defaults$x;
457
457
  }
458
458
  /**
459
459
  * Initializes instances of Dropdown.
@@ -545,7 +545,7 @@ var M = (function (exports) {
545
545
  // isTouchMoving to check if scrolling on mobile.
546
546
  this.close();
547
547
  }
548
- else if (!target.closest('.dropdown-content')) {
548
+ else if (!target.closest('.dropdown-content') && !target.closest('.dropdown-trigger')) {
549
549
  // Do this one frame later so that if the element clicked also triggers _handleClick
550
550
  // For example, if a label for a select was clicked, that we don't close/open the dropdown
551
551
  setTimeout(() => {
@@ -904,7 +904,7 @@ var M = (function (exports) {
904
904
  };
905
905
  }
906
906
 
907
- const _defaults$n = {
907
+ const _defaults$w = {
908
908
  data: [], // Autocomplete data set
909
909
  onAutocomplete: null, // Callback for when autocompleted
910
910
  dropdownOptions: {
@@ -964,7 +964,7 @@ var M = (function (exports) {
964
964
  this._setupEventHandlers();
965
965
  }
966
966
  static get defaults() {
967
- return _defaults$n;
967
+ return _defaults$w;
968
968
  }
969
969
  /**
970
970
  * Initializes instances of Autocomplete.
@@ -1372,7 +1372,177 @@ var M = (function (exports) {
1372
1372
  }
1373
1373
  }
1374
1374
 
1375
- const _defaults$m = {
1375
+ const _defaults$v = {
1376
+ dismissible: true
1377
+ };
1378
+ /** A persistent, contextual feedback banner. */
1379
+ class Alert extends Component {
1380
+ _closeButton = null;
1381
+ _onClose = () => this.dismiss();
1382
+ constructor(el, options) {
1383
+ super(el, options, Alert);
1384
+ this.options = { ...Alert.defaults, ...options };
1385
+ this.el['M_Alert'] = this;
1386
+ this._bindCloseButton();
1387
+ }
1388
+ static get defaults() {
1389
+ return _defaults$v;
1390
+ }
1391
+ static init(els, options = {}) {
1392
+ return super.init(els, options, Alert);
1393
+ }
1394
+ static getInstance(el) {
1395
+ return el['M_Alert'];
1396
+ }
1397
+ _bindCloseButton() {
1398
+ this._closeButton = this.el.querySelector('.alert-close');
1399
+ if (this.options.dismissible && this._closeButton) {
1400
+ this._closeButton.addEventListener('click', this._onClose);
1401
+ }
1402
+ }
1403
+ /** Hide and remove the alert from the document. */
1404
+ dismiss() {
1405
+ if (!this.el.isConnected)
1406
+ return;
1407
+ this.el.classList.add('alert-dismissing');
1408
+ const remove = () => {
1409
+ this.el.removeEventListener('transitionend', remove);
1410
+ this.el.hidden = true;
1411
+ this.options.onDismiss?.(this);
1412
+ };
1413
+ if (getComputedStyle(this.el).transitionDuration === '0s')
1414
+ remove();
1415
+ else
1416
+ this.el.addEventListener('transitionend', remove, { once: true });
1417
+ }
1418
+ /** Show an alert that was previously dismissed. */
1419
+ open() {
1420
+ this.el.hidden = false;
1421
+ this.el.classList.remove('alert-dismissing');
1422
+ }
1423
+ destroy() {
1424
+ this._closeButton?.removeEventListener('click', this._onClose);
1425
+ delete this.el['M_Alert'];
1426
+ }
1427
+ }
1428
+
1429
+ const _defaults$u = {
1430
+ draggable: true
1431
+ };
1432
+ /** A lightweight, dependency-free board for columns of draggable cards. */
1433
+ class Kanban extends Component {
1434
+ _draggedCard = null;
1435
+ _dragSourceColumn = null;
1436
+ _onDragStart = (event) => {
1437
+ const card = event.target?.closest('.kanban-card');
1438
+ if (!card || !this.options.draggable)
1439
+ return;
1440
+ this._draggedCard = card;
1441
+ this._dragSourceColumn = card.closest('.kanban-column');
1442
+ card.classList.add('is-dragging');
1443
+ event.dataTransfer?.setData('text/plain', card.dataset.kanbanCard || '');
1444
+ if (event.dataTransfer)
1445
+ event.dataTransfer.effectAllowed = 'move';
1446
+ };
1447
+ _onDragOver = (event) => {
1448
+ if (!this._draggedCard)
1449
+ return;
1450
+ const column = event.target?.closest('.kanban-column');
1451
+ if (!column || !this.el.contains(column))
1452
+ return;
1453
+ event.preventDefault();
1454
+ if (event.dataTransfer)
1455
+ event.dataTransfer.dropEffect = 'move';
1456
+ this.el.querySelectorAll('.kanban-column.is-drag-over').forEach((item) => item.classList.remove('is-drag-over'));
1457
+ column.classList.add('is-drag-over');
1458
+ };
1459
+ _onDrop = (event) => {
1460
+ if (!this._draggedCard)
1461
+ return;
1462
+ const column = event.target?.closest('.kanban-column');
1463
+ if (!column || !this.el.contains(column))
1464
+ return;
1465
+ event.preventDefault();
1466
+ const body = column.querySelector('.kanban-column-body') || column;
1467
+ const targetCard = event.target?.closest('.kanban-card');
1468
+ const source = this._dragSourceColumn;
1469
+ if (targetCard && targetCard !== this._draggedCard && targetCard.parentElement === body) {
1470
+ const box = targetCard.getBoundingClientRect();
1471
+ body.insertBefore(this._draggedCard, event.clientY < box.top + box.height / 2 ? targetCard : targetCard.nextSibling);
1472
+ }
1473
+ else {
1474
+ body.appendChild(this._draggedCard);
1475
+ }
1476
+ this._clearDragState();
1477
+ this._updateCounts();
1478
+ if (source && source !== column)
1479
+ this.options.onMove?.({ card: this._draggedCard, from: source, to: column });
1480
+ };
1481
+ _onDragEnd = () => this._clearDragState();
1482
+ constructor(el, options) {
1483
+ super(el, options, Kanban);
1484
+ this.options = { ...Kanban.defaults, ...options };
1485
+ this.el['M_Kanban'] = this;
1486
+ this._prepareMarkup();
1487
+ if (this.options.draggable)
1488
+ this._bindEvents();
1489
+ }
1490
+ static get defaults() {
1491
+ return _defaults$u;
1492
+ }
1493
+ static init(els, options = {}) {
1494
+ return super.init(els, options, Kanban);
1495
+ }
1496
+ static getInstance(el) {
1497
+ return el['M_Kanban'];
1498
+ }
1499
+ _prepareMarkup() {
1500
+ this.el.setAttribute('role', 'region');
1501
+ this.el.querySelectorAll('.kanban-column').forEach((column) => {
1502
+ column.setAttribute('role', 'group');
1503
+ const body = column.querySelector('.kanban-column-body');
1504
+ if (body)
1505
+ body.setAttribute('role', 'list');
1506
+ column.querySelectorAll('.kanban-card').forEach((card) => {
1507
+ card.setAttribute('role', 'listitem');
1508
+ card.setAttribute('tabindex', '0');
1509
+ if (this.options.draggable)
1510
+ card.draggable = true;
1511
+ });
1512
+ });
1513
+ this._updateCounts();
1514
+ }
1515
+ _bindEvents() {
1516
+ this.el.addEventListener('dragstart', this._onDragStart);
1517
+ this.el.addEventListener('dragover', this._onDragOver);
1518
+ this.el.addEventListener('drop', this._onDrop);
1519
+ this.el.addEventListener('dragend', this._onDragEnd);
1520
+ }
1521
+ _clearDragState() {
1522
+ this._draggedCard?.classList.remove('is-dragging');
1523
+ this.el.querySelectorAll('.kanban-column.is-drag-over').forEach((item) => item.classList.remove('is-drag-over'));
1524
+ this._draggedCard = null;
1525
+ this._dragSourceColumn = null;
1526
+ }
1527
+ _updateCounts() {
1528
+ this.el.querySelectorAll('.kanban-column').forEach((column) => {
1529
+ const count = column.querySelector('.kanban-column-count');
1530
+ const body = column.querySelector('.kanban-column-body');
1531
+ if (count && body)
1532
+ count.textContent = String(body.querySelectorAll(':scope > .kanban-card').length);
1533
+ });
1534
+ }
1535
+ destroy() {
1536
+ this._clearDragState();
1537
+ this.el.removeEventListener('dragstart', this._onDragStart);
1538
+ this.el.removeEventListener('dragover', this._onDragOver);
1539
+ this.el.removeEventListener('drop', this._onDrop);
1540
+ this.el.removeEventListener('dragend', this._onDragEnd);
1541
+ delete this.el['M_Kanban'];
1542
+ }
1543
+ }
1544
+
1545
+ const _defaults$t = {
1376
1546
  direction: 'top',
1377
1547
  hoverEnabled: true,
1378
1548
  toolbarEnabled: false
@@ -1419,7 +1589,7 @@ var M = (function (exports) {
1419
1589
  this.#setupEventHandlers();
1420
1590
  }
1421
1591
  static get defaults() {
1422
- return _defaults$m;
1592
+ return _defaults$t;
1423
1593
  }
1424
1594
  /**
1425
1595
  * Initializes instances of FloatingActionButton.
@@ -1590,7 +1760,7 @@ var M = (function (exports) {
1590
1760
  }
1591
1761
  }
1592
1762
 
1593
- const _defaults$l = {
1763
+ const _defaults$s = {
1594
1764
  onOpen: null,
1595
1765
  onClose: null,
1596
1766
  inDuration: 225,
@@ -1626,7 +1796,7 @@ var M = (function (exports) {
1626
1796
  }
1627
1797
  }
1628
1798
  static get defaults() {
1629
- return _defaults$l;
1799
+ return _defaults$s;
1630
1800
  }
1631
1801
  /**
1632
1802
  * Initializes instances of Cards.
@@ -1737,7 +1907,7 @@ var M = (function (exports) {
1737
1907
  }
1738
1908
  }
1739
1909
 
1740
- const _defaults$k = {
1910
+ const _defaults$r = {
1741
1911
  duration: 200, // ms
1742
1912
  dist: -100, // zoom scale TODO: make this more intuitive as an option
1743
1913
  shift: 0, // spacing for center image
@@ -1839,7 +2009,7 @@ var M = (function (exports) {
1839
2009
  this._scroll(this.offset);
1840
2010
  }
1841
2011
  static get defaults() {
1842
- return _defaults$k;
2012
+ return _defaults$r;
1843
2013
  }
1844
2014
  /**
1845
2015
  * Initializes instances of Carousel.
@@ -2311,7 +2481,7 @@ var M = (function (exports) {
2311
2481
  }
2312
2482
 
2313
2483
  var _a;
2314
- const _defaults$j = {
2484
+ const _defaults$q = {
2315
2485
  data: [],
2316
2486
  placeholder: '',
2317
2487
  secondaryPlaceholder: '',
@@ -2365,7 +2535,7 @@ var M = (function (exports) {
2365
2535
  }
2366
2536
  }
2367
2537
  static get defaults() {
2368
- return _defaults$j;
2538
+ return _defaults$q;
2369
2539
  }
2370
2540
  /**
2371
2541
  * Initializes instances of Chips.
@@ -2648,7 +2818,7 @@ var M = (function (exports) {
2648
2818
  }
2649
2819
  _a = Chips;
2650
2820
 
2651
- const _defaults$i = {
2821
+ const _defaults$p = {
2652
2822
  accordion: true,
2653
2823
  onOpenStart: null,
2654
2824
  onOpenEnd: null,
@@ -2684,7 +2854,7 @@ var M = (function (exports) {
2684
2854
  }
2685
2855
  }
2686
2856
  static get defaults() {
2687
- return _defaults$i;
2857
+ return _defaults$p;
2688
2858
  }
2689
2859
  /**
2690
2860
  * Initializes instances of Collapsible.
@@ -2803,7 +2973,7 @@ var M = (function (exports) {
2803
2973
  };
2804
2974
  }
2805
2975
 
2806
- const _defaults$h = {
2976
+ const _defaults$o = {
2807
2977
  classes: '',
2808
2978
  dropdownOptions: {}
2809
2979
  };
@@ -2843,7 +3013,7 @@ var M = (function (exports) {
2843
3013
  this._setupEventHandlers();
2844
3014
  }
2845
3015
  static get defaults() {
2846
- return _defaults$h;
3016
+ return _defaults$o;
2847
3017
  }
2848
3018
  /**
2849
3019
  * Initializes instances of FormSelect.
@@ -3186,7 +3356,7 @@ var M = (function (exports) {
3186
3356
  }
3187
3357
  }
3188
3358
 
3189
- const _defaults$g = {
3359
+ const _defaults$n = {
3190
3360
  margin: 5,
3191
3361
  transition: 10,
3192
3362
  duration: 250,
@@ -3203,7 +3373,7 @@ var M = (function (exports) {
3203
3373
  constructor(el, container, options) {
3204
3374
  this.el = el;
3205
3375
  this.options = {
3206
- ..._defaults$g,
3376
+ ..._defaults$n,
3207
3377
  ...options
3208
3378
  };
3209
3379
  this.container = document.createElement('div');
@@ -3265,7 +3435,7 @@ var M = (function (exports) {
3265
3435
  };
3266
3436
  }
3267
3437
 
3268
- const _defaults$f = {
3438
+ const _defaults$m = {
3269
3439
  classList: ['modal'],
3270
3440
  title: null,
3271
3441
  onOpen: null,
@@ -3280,7 +3450,7 @@ var M = (function (exports) {
3280
3450
  constructor(el, container, options) {
3281
3451
  this.el = el;
3282
3452
  this.options = {
3283
- ..._defaults$f,
3453
+ ..._defaults$m,
3284
3454
  ...options,
3285
3455
  };
3286
3456
  this.container = document.createElement('dialog');
@@ -3338,7 +3508,7 @@ var M = (function (exports) {
3338
3508
  };
3339
3509
  }
3340
3510
 
3341
- const _defaults$e = {
3511
+ const _defaults$l = {
3342
3512
  // the default output format for the input field value
3343
3513
  format: 'mmm dd, yyyy',
3344
3514
  // Used to create date object from current input string
@@ -3488,7 +3658,7 @@ var M = (function (exports) {
3488
3658
  this._pickerSetup();
3489
3659
  }
3490
3660
  static get defaults() {
3491
- return _defaults$e;
3661
+ return _defaults$l;
3492
3662
  }
3493
3663
  /**
3494
3664
  * Initializes instances of Datepicker.
@@ -4541,7 +4711,7 @@ var M = (function (exports) {
4541
4711
  }
4542
4712
  }
4543
4713
 
4544
- const _defaults$d = {
4714
+ const _defaults$k = {
4545
4715
  inDuration: 275,
4546
4716
  outDuration: 200,
4547
4717
  onOpenStart: null,
@@ -4593,7 +4763,7 @@ var M = (function (exports) {
4593
4763
  this._setupEventHandlers();
4594
4764
  }
4595
4765
  static get defaults() {
4596
- return _defaults$d;
4766
+ return _defaults$k;
4597
4767
  }
4598
4768
  /**
4599
4769
  * Initializes instances of MaterialBox.
@@ -4917,7 +5087,7 @@ var M = (function (exports) {
4917
5087
  };
4918
5088
  }
4919
5089
 
4920
- const _defaults$c = {
5090
+ const _defaults$j = {
4921
5091
  opacity: 0.5,
4922
5092
  inDuration: 250,
4923
5093
  outDuration: 250,
@@ -4942,7 +5112,7 @@ var M = (function (exports) {
4942
5112
  this._setupEventHandlers();
4943
5113
  }
4944
5114
  static get defaults() {
4945
- return _defaults$c;
5115
+ return _defaults$j;
4946
5116
  }
4947
5117
  static init(els, options = {}) {
4948
5118
  return super.init(els, options, Modal);
@@ -4985,7 +5155,7 @@ var M = (function (exports) {
4985
5155
  static { }
4986
5156
  }
4987
5157
 
4988
- const _defaults$b = {
5158
+ const _defaults$i = {
4989
5159
  edge: 'left',
4990
5160
  draggable: true,
4991
5161
  dragTargetWidth: '10px',
@@ -5041,7 +5211,7 @@ var M = (function (exports) {
5041
5211
  Sidenav._sidenavs.push(this);
5042
5212
  }
5043
5213
  static get defaults() {
5044
- return _defaults$b;
5214
+ return _defaults$i;
5045
5215
  }
5046
5216
  /**
5047
5217
  * Initializes instances of Sidenav.
@@ -5438,7 +5608,7 @@ var M = (function (exports) {
5438
5608
  }
5439
5609
  }
5440
5610
 
5441
- const _defaults$a = {
5611
+ const _defaults$h = {
5442
5612
  indicators: true,
5443
5613
  height: 400,
5444
5614
  duration: 500,
@@ -5530,7 +5700,7 @@ var M = (function (exports) {
5530
5700
  this.start();
5531
5701
  }
5532
5702
  static get defaults() {
5533
- return _defaults$a;
5703
+ return _defaults$h;
5534
5704
  }
5535
5705
  /**
5536
5706
  * Initializes instances of Slider.
@@ -5777,7 +5947,7 @@ var M = (function (exports) {
5777
5947
  };
5778
5948
  }
5779
5949
 
5780
- const _defaults$9 = {
5950
+ const _defaults$g = {
5781
5951
  duration: 300,
5782
5952
  onShow: null,
5783
5953
  swipeable: false,
@@ -5814,7 +5984,7 @@ var M = (function (exports) {
5814
5984
  this._setupEventHandlers();
5815
5985
  }
5816
5986
  static get defaults() {
5817
- return _defaults$9;
5987
+ return _defaults$g;
5818
5988
  }
5819
5989
  /**
5820
5990
  * Initializes instances of Tabs.
@@ -6065,7 +6235,7 @@ var M = (function (exports) {
6065
6235
  }
6066
6236
  }
6067
6237
 
6068
- const _defaults$8 = {
6238
+ const _defaults$f = {
6069
6239
  dialRadius: 135,
6070
6240
  outerRadius: 105,
6071
6241
  innerRadius: 70,
@@ -6152,7 +6322,7 @@ var M = (function (exports) {
6152
6322
  this._pickerSetup();
6153
6323
  }
6154
6324
  static get defaults() {
6155
- return _defaults$8;
6325
+ return _defaults$f;
6156
6326
  }
6157
6327
  /**
6158
6328
  * Initializes instances of Timepicker.
@@ -6758,7 +6928,7 @@ var M = (function (exports) {
6758
6928
  }
6759
6929
  }
6760
6930
 
6761
- const _defaults$7 = {
6931
+ const _defaults$e = {
6762
6932
  text: '',
6763
6933
  displayLength: 4000,
6764
6934
  inDuration: 300,
@@ -6811,7 +6981,7 @@ var M = (function (exports) {
6811
6981
  this._setTimer();
6812
6982
  }
6813
6983
  static get defaults() {
6814
- return _defaults$7;
6984
+ return _defaults$e;
6815
6985
  }
6816
6986
  static getInstance(el) {
6817
6987
  return el['M_Toast'];
@@ -7003,7 +7173,7 @@ var M = (function (exports) {
7003
7173
  }
7004
7174
  }
7005
7175
 
7006
- const _defaults$6 = {
7176
+ const _defaults$d = {
7007
7177
  exitDelay: 200,
7008
7178
  enterDelay: 0,
7009
7179
  text: '',
@@ -7047,7 +7217,7 @@ var M = (function (exports) {
7047
7217
  this._setupEventHandlers();
7048
7218
  }
7049
7219
  static get defaults() {
7050
- return _defaults$6;
7220
+ return _defaults$d;
7051
7221
  }
7052
7222
  /**
7053
7223
  * Initializes instances of Tooltip.
@@ -7272,7 +7442,7 @@ var M = (function (exports) {
7272
7442
  }
7273
7443
  }
7274
7444
 
7275
- const _defaults$5 = {};
7445
+ const _defaults$c = {};
7276
7446
  // TODO: !!!!!
7277
7447
  class Range extends Component {
7278
7448
  _mousedown;
@@ -7290,7 +7460,7 @@ var M = (function (exports) {
7290
7460
  this._setupEventHandlers();
7291
7461
  }
7292
7462
  static get defaults() {
7293
- return _defaults$5;
7463
+ return _defaults$c;
7294
7464
  }
7295
7465
  /**
7296
7466
  * Initializes instances of Range.
@@ -7441,6 +7611,896 @@ var M = (function (exports) {
7441
7611
  }
7442
7612
  }
7443
7613
 
7614
+ const _defaults$b = {};
7615
+ // @implement /Users/kzarshenas/Sites/RodeoFx/rodeo_toolkit_2/app/Environment/Partials/PlanningToolbar.ts
7616
+ // Generic version of that file's track-indicator sliding and expandable
7617
+ // search behavior, decoupled from the page-specific filter/state-binding
7618
+ // system (UtilityFilter) the source used - here it's just plain DOM state.
7619
+ class Toolbar extends Component {
7620
+ _tracks;
7621
+ constructor(el, options) {
7622
+ super(el, options, Toolbar);
7623
+ this.el.M_Toolbar = this;
7624
+ this.options = {
7625
+ ...Toolbar.defaults,
7626
+ ...options
7627
+ };
7628
+ this._tracks = Array.from(this.el.querySelectorAll('.toolbar-track'));
7629
+ this._setupEventHandlers();
7630
+ this._tracks.forEach((track) => this._moveIndicator(track, false));
7631
+ // A custom/web font can still be loading at construction time; its
7632
+ // metrics landing after this first measurement would leave the
7633
+ // indicator very slightly offset from the (now differently-sized)
7634
+ // text it's supposed to sit behind. Re-measure once fonts are ready.
7635
+ if (typeof document !== 'undefined' && document.fonts) {
7636
+ document.fonts.ready.then(() => {
7637
+ this._tracks.forEach((track) => this._moveIndicator(track, false));
7638
+ });
7639
+ }
7640
+ }
7641
+ static get defaults() {
7642
+ return _defaults$b;
7643
+ }
7644
+ static init(els, options = {}) {
7645
+ return super.init(els, options, Toolbar);
7646
+ }
7647
+ static getInstance(el) {
7648
+ return el.M_Toolbar;
7649
+ }
7650
+ destroy() {
7651
+ this._removeEventHandlers();
7652
+ this.el.M_Toolbar = undefined;
7653
+ }
7654
+ /**
7655
+ * Re-measure and reposition every track's sliding indicator - call this
7656
+ * after changing which .toolbar-track-item is active from your own code,
7657
+ * or after anything that could have changed the toolbar's layout/width.
7658
+ */
7659
+ updateIndicators() {
7660
+ this._tracks.forEach((track) => this._moveIndicator(track, true));
7661
+ }
7662
+ _setupEventHandlers() {
7663
+ this.el.addEventListener('click', this._handleTrackClick);
7664
+ this.el.addEventListener('focusin', this._handleSearchFocusIn);
7665
+ this.el.addEventListener('focusout', this._handleSearchFocusOut);
7666
+ this.el.addEventListener('input', this._handleSearchInput);
7667
+ this.el.addEventListener('keydown', this._handleSearchKeydown);
7668
+ window.addEventListener('resize', this._handleWindowResize);
7669
+ }
7670
+ _removeEventHandlers() {
7671
+ this.el.removeEventListener('click', this._handleTrackClick);
7672
+ this.el.removeEventListener('focusin', this._handleSearchFocusIn);
7673
+ this.el.removeEventListener('focusout', this._handleSearchFocusOut);
7674
+ this.el.removeEventListener('input', this._handleSearchInput);
7675
+ this.el.removeEventListener('keydown', this._handleSearchKeydown);
7676
+ window.removeEventListener('resize', this._handleWindowResize);
7677
+ }
7678
+ _handleTrackClick = (e) => {
7679
+ const item = e.target.closest('.toolbar-track-item');
7680
+ if (!item)
7681
+ return;
7682
+ const track = item.closest('.toolbar-track');
7683
+ if (!track || !this._tracks.includes(track))
7684
+ return;
7685
+ track.querySelectorAll('.toolbar-track-item.is-active').forEach((el) => el.classList.remove('is-active'));
7686
+ item.classList.add('is-active');
7687
+ this._moveIndicator(track, true);
7688
+ };
7689
+ _handleSearchFocusIn = (e) => {
7690
+ const search = e.target.closest('.toolbar-search');
7691
+ if (search)
7692
+ search.classList.add('is-expanded');
7693
+ };
7694
+ _handleSearchFocusOut = (e) => {
7695
+ const search = e.target.closest('.toolbar-search');
7696
+ if (!search)
7697
+ return;
7698
+ const input = search.querySelector('.toolbar-search-input');
7699
+ if (input && input.value === '')
7700
+ search.classList.remove('is-expanded');
7701
+ };
7702
+ _handleSearchInput = (e) => {
7703
+ const input = e.target;
7704
+ if (!input.classList.contains('toolbar-search-input'))
7705
+ return;
7706
+ const search = input.closest('.toolbar-search');
7707
+ if (search)
7708
+ search.classList.toggle('is-expanded', input.value !== '' || document.activeElement === input);
7709
+ };
7710
+ _handleSearchKeydown = (e) => {
7711
+ if (e.key !== 'Escape')
7712
+ return;
7713
+ const input = e.target.closest('.toolbar-search')?.querySelector('.toolbar-search-input');
7714
+ if (!input)
7715
+ return;
7716
+ input.value = '';
7717
+ input.blur();
7718
+ };
7719
+ _handleWindowResize = () => {
7720
+ this._tracks.forEach((track) => this._moveIndicator(track, false));
7721
+ };
7722
+ _moveIndicator(track, animate) {
7723
+ const indicator = track.querySelector('.toolbar-track-indicator');
7724
+ const active = track.querySelector('.toolbar-track-item.is-active');
7725
+ if (!indicator || !active)
7726
+ return;
7727
+ if (!animate)
7728
+ indicator.style.transition = 'none';
7729
+ // No "- track.clientLeft" here: offsetLeft is already relative to the
7730
+ // offsetParent's padding edge, same origin as the indicator's own
7731
+ // `left: 0` (an absolutely positioned element's containing block is
7732
+ // its ancestor's padding box) - subtracting the border width again
7733
+ // was double-counting it, nudging the indicator a px too far left.
7734
+ indicator.style.transform = `translateX(${active.offsetLeft}px)`;
7735
+ indicator.style.width = `${active.offsetWidth}px`;
7736
+ track.classList.add('is-armed');
7737
+ if (!animate) {
7738
+ // Force layout so the transition-less move above actually applies
7739
+ // before re-enabling transitions on the next frame.
7740
+ void indicator.offsetWidth;
7741
+ requestAnimationFrame(() => {
7742
+ indicator.style.transition = '';
7743
+ });
7744
+ }
7745
+ }
7746
+ }
7747
+
7748
+ const _defaults$a = {};
7749
+ // @implement /Users/kzarshenas/Sites/CrazyProject/CrazyPHP/src/Front/Library/Utility/Form/Password.ts
7750
+ // Show/hide toggle for a password input - no third-party dependency, just
7751
+ // Materialize's own .prefix/.suffix icon-slot convention (see
7752
+ // components/textfield/_input-fields.scss), so unlike the other new form
7753
+ // enhancements in this batch this one needs no peer-loader/dynamic import.
7754
+ class PasswordInput extends Component {
7755
+ _suffixEl;
7756
+ constructor(el, options) {
7757
+ super(el, options, PasswordInput);
7758
+ this.el.M_PasswordInput = this;
7759
+ this.options = {
7760
+ ...PasswordInput.defaults,
7761
+ ...options
7762
+ };
7763
+ this._suffixEl = this.el.parentElement?.querySelector('[data-password-toggle-icon]') ?? null;
7764
+ if (!this.el.dataset.passwordVisible)
7765
+ this.el.dataset.passwordVisible = '0';
7766
+ this._setupEventHandlers();
7767
+ }
7768
+ static get defaults() {
7769
+ return _defaults$a;
7770
+ }
7771
+ static init(els, options = {}) {
7772
+ return super.init(els, options, PasswordInput);
7773
+ }
7774
+ static getInstance(el) {
7775
+ return el.M_PasswordInput;
7776
+ }
7777
+ destroy() {
7778
+ this._removeEventHandlers();
7779
+ this.el.M_PasswordInput = undefined;
7780
+ }
7781
+ _setupEventHandlers() {
7782
+ this._suffixEl?.addEventListener('click', this._handleToggleClick);
7783
+ }
7784
+ _removeEventHandlers() {
7785
+ this._suffixEl?.removeEventListener('click', this._handleToggleClick);
7786
+ }
7787
+ _handleToggleClick = () => {
7788
+ const visible = this.el.dataset.passwordVisible === '1';
7789
+ this.el.type = visible ? 'password' : 'text';
7790
+ this.el.dataset.passwordVisible = visible ? '0' : '1';
7791
+ const iconEl = this._suffixEl?.querySelector('i');
7792
+ if (iconEl)
7793
+ iconEl.textContent = visible ? 'visibility' : 'visibility_off';
7794
+ };
7795
+ }
7796
+
7797
+ const _cache = new Map();
7798
+ async function loadPeer(spec, importer) {
7799
+ if (_cache.has(spec.specifier))
7800
+ return _cache.get(spec.specifier);
7801
+ try {
7802
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
7803
+ const mod = await importer();
7804
+ const resolved = mod?.default ?? mod;
7805
+ _cache.set(spec.specifier, resolved);
7806
+ return resolved;
7807
+ }
7808
+ catch {
7809
+ // fall through to the global-scope lookup below
7810
+ }
7811
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
7812
+ const globalScope = typeof window !== 'undefined' ? window : undefined;
7813
+ if (globalScope && globalScope[spec.globalName]) {
7814
+ const resolved = globalScope[spec.globalName];
7815
+ _cache.set(spec.specifier, resolved);
7816
+ return resolved;
7817
+ }
7818
+ throw new Error(`kmaterialize's ${spec.feature} requires "${spec.specifier}", which isn't installed/loaded.\n` +
7819
+ `- If you're using a bundler: npm/pnpm/yarn install "${spec.specifier}".\n` +
7820
+ `- If you're using the plain <script> (no-bundler) build: add\n` +
7821
+ ` ${spec.cdnHint}\n` +
7822
+ ` before initializing this component, so window.${spec.globalName} is defined.`);
7823
+ }
7824
+
7825
+ const _defaults$9 = {
7826
+ thousandsSeparator: ' ',
7827
+ radix: '.',
7828
+ mapToRadix: [',']
7829
+ };
7830
+ // @implement /Users/kzarshenas/Sites/CrazyProject/CrazyPHP/src/Front/Library/Utility/Form/Number.ts
7831
+ // Masked/formatted numeric input via IMask (thousands separator, decimal
7832
+ // scale, min/max) - deliberately opts in on `type="text" data-type="number"`
7833
+ // rather than `type="number"`, so IMask can format the display value
7834
+ // (thousands separators etc.) that a native number input wouldn't allow.
7835
+ //
7836
+ // IMask is an optional peerDependency, loaded on demand via peer-loader -
7837
+ // see that file for the bundler/no-bundler resolution strategy.
7838
+ class NumberInput extends Component {
7839
+ mask;
7840
+ ready;
7841
+ constructor(el, options) {
7842
+ super(el, options, NumberInput);
7843
+ this.el.M_NumberInput = this;
7844
+ this.options = {
7845
+ ...NumberInput.defaults,
7846
+ ...options
7847
+ };
7848
+ this.ready = this._setup();
7849
+ }
7850
+ static get defaults() {
7851
+ return _defaults$9;
7852
+ }
7853
+ static init(els, options = {}) {
7854
+ return super.init(els, options, NumberInput);
7855
+ }
7856
+ static getInstance(el) {
7857
+ return el.M_NumberInput;
7858
+ }
7859
+ destroy() {
7860
+ this.mask?.destroy();
7861
+ this.el.M_NumberInput = undefined;
7862
+ }
7863
+ async _setup() {
7864
+ const IMask = await loadPeer({
7865
+ specifier: 'imask',
7866
+ globalName: 'IMask',
7867
+ feature: 'Number input (IMask) enhancement',
7868
+ cdnHint: '<script src="path/to/imask.min.js"></script> (self-hosted - copy from node_modules/imask/dist/imask.min.js, or a CDN of your choice)'
7869
+ }, () => import('imask'));
7870
+ const maskOptions = {
7871
+ mask: Number,
7872
+ skipInvalid: true,
7873
+ thousandsSeparator: this.options.thousandsSeparator,
7874
+ radix: this.options.radix,
7875
+ mapToRadix: this.options.mapToRadix,
7876
+ autofix: true
7877
+ };
7878
+ const max = this.options.max ?? (this.el.hasAttribute('max') ? Number(this.el.getAttribute('max')) : undefined);
7879
+ if (max !== undefined && !Number.isNaN(max))
7880
+ maskOptions.max = max;
7881
+ const min = this.options.min ?? (this.el.hasAttribute('min') ? Number(this.el.getAttribute('min')) : undefined);
7882
+ if (min !== undefined && !Number.isNaN(min))
7883
+ maskOptions.min = min;
7884
+ const step = this.el.getAttribute('step');
7885
+ const scale = this.options.scale ?? (step?.includes('.') ? step.split('.').at(-1)?.length : undefined);
7886
+ if (scale !== undefined)
7887
+ maskOptions.scale = scale;
7888
+ this.mask = IMask(this.el, maskOptions);
7889
+ }
7890
+ }
7891
+
7892
+ // @implement /Users/kzarshenas/Sites/CrazyProject/CrazyPHP/src/Front/Library/Utility/Form/Color.ts
7893
+ // Built-in French translation for Pickr's UI strings, activated by
7894
+ // `data-color-locale="fr-fr"` alone - no separate options object required
7895
+ // from the consumer, unlike a fully custom `options.locale` override.
7896
+ const FR_FR = {
7897
+ 'ui:dialog': 'boîte de dialogue du sélecteur de couleur',
7898
+ 'btn:toggle': 'basculer la boîte de dialogue du sélecteur de couleur',
7899
+ 'btn:swatch': 'échantillon de couleur',
7900
+ 'btn:last-color': 'utiliser la couleur précédente',
7901
+ 'btn:save': 'Enregistrer',
7902
+ 'btn:cancel': 'Annuler',
7903
+ 'btn:clear': 'Effacer',
7904
+ 'aria:btn:save': 'enregistrer et fermer',
7905
+ 'aria:btn:cancel': 'annuler et fermer',
7906
+ 'aria:btn:clear': 'effacer et fermer',
7907
+ 'aria:input': 'champ de saisie de couleur',
7908
+ 'aria:palette': 'zone de sélection des couleurs',
7909
+ 'aria:hue': 'curseur de sélection de teinte',
7910
+ 'aria:opacity': "curseur de sélection d'opacité"
7911
+ };
7912
+ const _defaults$8 = {
7913
+ theme: 'classic',
7914
+ opacity: true,
7915
+ swatches: [
7916
+ 'rgba(244, 67, 54, 1)',
7917
+ 'rgba(233, 30, 99, 0.95)',
7918
+ 'rgba(156, 39, 176, 0.9)',
7919
+ 'rgba(103, 58, 183, 0.85)',
7920
+ 'rgba(63, 81, 181, 0.8)',
7921
+ 'rgba(33, 150, 243, 0.75)',
7922
+ 'rgba(3, 169, 244, 0.7)',
7923
+ 'rgba(0, 188, 212, 0.7)',
7924
+ 'rgba(0, 150, 136, 0.75)',
7925
+ 'rgba(76, 175, 80, 0.8)',
7926
+ 'rgba(139, 195, 74, 0.85)',
7927
+ 'rgba(205, 220, 57, 0.9)',
7928
+ 'rgba(255, 235, 59, 0.95)',
7929
+ 'rgba(255, 193, 7, 1)'
7930
+ ]
7931
+ };
7932
+ // @implement /Users/kzarshenas/Sites/CrazyProject/CrazyPHP/src/Front/Library/Utility/Form/Color.ts
7933
+ // Enhances a native `<input type="color" data-color-picker="pickr">` with a
7934
+ // full Pickr popup (palette, hue/opacity sliders, swatches, hex/rgba/hsla).
7935
+ // If `data-color-picker` is absent the input is left completely untouched -
7936
+ // still a plain native color swatch, matching CrazyPHP's own fallback.
7937
+ //
7938
+ // Pickr remains an optional peerDependency and is loaded on demand via peer-loader.
7939
+ class ColorInput extends Component {
7940
+ pickr;
7941
+ ready;
7942
+ _swatchEl;
7943
+ _labels;
7944
+ constructor(el, options) {
7945
+ super(el, options, ColorInput);
7946
+ this.el.M_ColorInput = this;
7947
+ this.options = {
7948
+ ...ColorInput.defaults,
7949
+ ...options
7950
+ };
7951
+ this._swatchEl = document.createElement('div');
7952
+ this.el.after(this._swatchEl);
7953
+ this.el.classList.add('hide');
7954
+ this.el.addEventListener('change', this._handleInputChange);
7955
+ this._labels = Array.from(document.querySelectorAll('label')).filter(label => label.htmlFor === this.el.id);
7956
+ this._labels.forEach(label => label.addEventListener('click', this._handleLabelClick));
7957
+ this.ready = this._setup();
7958
+ }
7959
+ static get defaults() {
7960
+ return _defaults$8;
7961
+ }
7962
+ static init(els, options = {}) {
7963
+ return super.init(els, options, ColorInput);
7964
+ }
7965
+ static getInstance(el) {
7966
+ return el.M_ColorInput;
7967
+ }
7968
+ destroy() {
7969
+ this.el.removeEventListener('change', this._handleInputChange);
7970
+ this._labels.forEach(label => label.removeEventListener('click', this._handleLabelClick));
7971
+ this.pickr?.destroyAndRemove();
7972
+ this._swatchEl.remove();
7973
+ this.el.classList.remove('hide');
7974
+ this.el.M_ColorInput = undefined;
7975
+ }
7976
+ _handleInputChange = () => {
7977
+ this.pickr?.setColor(this.el.value);
7978
+ };
7979
+ _handleLabelClick = (event) => {
7980
+ // A label associated with a hidden input[type=color] otherwise opens
7981
+ // the browser's native picker (notably in Firefox). Route the same
7982
+ // accessible label activation to Pickr instead.
7983
+ event.preventDefault();
7984
+ void this.ready.then(() => this.pickr?.show());
7985
+ };
7986
+ async _setup() {
7987
+ const Pickr = await loadPeer({
7988
+ specifier: '@simonwep/pickr',
7989
+ globalName: 'Pickr',
7990
+ feature: 'Color input (Pickr) enhancement',
7991
+ cdnHint: '<link rel="stylesheet" href="path/to/pickr-classic.min.css">\n' +
7992
+ ' <script src="path/to/pickr.min.js"></script>\n' +
7993
+ ' (self-hosted - copy from node_modules/@simonwep/pickr/dist/, or a CDN of your choice)'
7994
+ }, () => import('@simonwep/pickr'));
7995
+ const dataset = this.el.dataset;
7996
+ const theme = (['classic', 'monolith', 'nano'].includes(dataset.colorTheme ?? '')
7997
+ ? dataset.colorTheme
7998
+ : this.options.theme);
7999
+ const lockOpacity = dataset.colorOpacity !== undefined
8000
+ ? ['false', '0', '', 'null'].includes(dataset.colorOpacity)
8001
+ : !this.options.opacity;
8002
+ const pickrOptions = {
8003
+ el: this._swatchEl,
8004
+ theme,
8005
+ lockOpacity,
8006
+ swatches: this.options.swatches,
8007
+ components: {
8008
+ preview: true,
8009
+ opacity: true,
8010
+ hue: true,
8011
+ interaction: {
8012
+ hex: true,
8013
+ rgba: true,
8014
+ hsla: true,
8015
+ hsva: true,
8016
+ cmyk: true,
8017
+ input: true,
8018
+ clear: true,
8019
+ save: true
8020
+ }
8021
+ }
8022
+ };
8023
+ if (this.options.locale) {
8024
+ pickrOptions.i18n = this.options.locale;
8025
+ }
8026
+ else if (dataset.colorLocale === 'fr-fr') {
8027
+ pickrOptions.i18n = FR_FR;
8028
+ }
8029
+ const currentValue = this.el.getAttribute('value');
8030
+ if (currentValue && currentValue !== 'randomHex()') {
8031
+ pickrOptions.default = currentValue;
8032
+ }
8033
+ else if (this.el.hasAttribute('default')) {
8034
+ const currentDefault = this.el.getAttribute('default');
8035
+ if (currentDefault === 'randomHex()') {
8036
+ const randomColor = Math.floor(Math.random() * 16777216);
8037
+ pickrOptions.default = `#${randomColor.toString(16).padStart(6, '0')}`;
8038
+ }
8039
+ else if (currentDefault) {
8040
+ pickrOptions.default = currentDefault;
8041
+ }
8042
+ }
8043
+ this.pickr = Pickr.create(pickrOptions);
8044
+ if (this.el.disabled)
8045
+ this.pickr.disable();
8046
+ this.pickr.on('save', (color, instance) => {
8047
+ const hexa = color?.toHEXA().toString();
8048
+ if (hexa) {
8049
+ this.el.value = hexa;
8050
+ this.el.dispatchEvent(new Event('change', { bubbles: true }));
8051
+ }
8052
+ instance.hide();
8053
+ });
8054
+ }
8055
+ }
8056
+
8057
+ const _defaults$7 = {};
8058
+ let activeAirDatepickerField;
8059
+ // @implement /Users/kzarshenas/Sites/CrazyProject/CrazyPHP/src/Front/Library/Utility/Form/Date.ts
8060
+ // Enhances `<input type="text" data-type="date" data-date-picker="air-datepicker">`
8061
+ // with the air-datepicker calendar/range picker - deliberately separate from
8062
+ // kmaterialize's own native `components/datepicker/` (a different, already
8063
+ // existing class-based component); this one is opted into per-input via the
8064
+ // `data-date-picker` attribute so it never collides with `.datepicker`
8065
+ // elements. The `multiple` attribute switches the picker into range mode,
8066
+ // `data-date-format`/`data-date-lang` (only "fr-FR" ported so far) mirror
8067
+ // CrazyPHP's own dataset convention.
8068
+ //
8069
+ // air-datepicker is an optional peerDependency, loaded on demand via
8070
+ // peer-loader. Its own base stylesheet (air-datepicker/air-datepicker.css)
8071
+ // must be imported separately by the consumer - see the docs page.
8072
+ class AirDatepickerField extends Component {
8073
+ picker;
8074
+ ready;
8075
+ _triggers;
8076
+ _handleOutsideClick = (e) => {
8077
+ const calendarEl = document.querySelector('.air-datepicker');
8078
+ const clickedTrigger = this._triggers.some(trigger => trigger.contains(e.target));
8079
+ if (calendarEl instanceof HTMLElement &&
8080
+ !calendarEl.contains(e.target) &&
8081
+ !this.el.contains(e.target) &&
8082
+ !clickedTrigger) {
8083
+ this.picker?.hide();
8084
+ }
8085
+ };
8086
+ constructor(el, options) {
8087
+ super(el, options, AirDatepickerField);
8088
+ this.el.M_AirDatepickerField = this;
8089
+ this.options = {
8090
+ ...AirDatepickerField.defaults,
8091
+ ...options
8092
+ };
8093
+ const labels = Array.from(document.querySelectorAll('label')).filter(label => label.htmlFor === this.el.id);
8094
+ const icons = Array.from(this.el.parentElement?.querySelectorAll('.prefix, .suffix') ?? []);
8095
+ this._triggers = [...labels, ...icons];
8096
+ this._triggers.forEach(trigger => trigger.addEventListener('click', this._handleTriggerClick));
8097
+ this.ready = this._setup();
8098
+ }
8099
+ static get defaults() {
8100
+ return _defaults$7;
8101
+ }
8102
+ static init(els, options = {}) {
8103
+ return super.init(els, options, AirDatepickerField);
8104
+ }
8105
+ static getInstance(el) {
8106
+ return el.M_AirDatepickerField;
8107
+ }
8108
+ destroy() {
8109
+ document.removeEventListener('click', this._handleOutsideClick);
8110
+ this._triggers.forEach(trigger => trigger.removeEventListener('click', this._handleTriggerClick));
8111
+ this.picker?.destroy();
8112
+ if (activeAirDatepickerField === this)
8113
+ activeAirDatepickerField = undefined;
8114
+ this.el.M_AirDatepickerField = undefined;
8115
+ }
8116
+ _handleTriggerClick = (event) => {
8117
+ event.preventDefault();
8118
+ event.stopPropagation();
8119
+ void this.ready.then(() => this.picker?.show());
8120
+ };
8121
+ async _setup() {
8122
+ const AirDatepicker = await loadPeer({
8123
+ specifier: 'air-datepicker',
8124
+ globalName: 'AirDatepicker',
8125
+ feature: 'Date input (air-datepicker) enhancement',
8126
+ cdnHint: '<link rel="stylesheet" href="path/to/air-datepicker.css">\n' +
8127
+ ' <script src="path/to/air-datepicker.js"></script>\n' +
8128
+ ' (self-hosted - copy from node_modules/air-datepicker/, or a CDN of your choice)'
8129
+ }, () => import('air-datepicker'));
8130
+ const dataset = this.el.dataset;
8131
+ const builtInLocale = dataset.dateLang === 'fr-FR'
8132
+ ? (await import('air-datepicker/locale/fr')).default
8133
+ : (await import('air-datepicker/locale/en')).default;
8134
+ const pickerOptions = {
8135
+ dateFormat: dataset.dateFormat || 'yyyy-MM-dd',
8136
+ autoClose: dataset.dateAutoClose !== 'false',
8137
+ locale: (this.options.locale ?? builtInLocale),
8138
+ onShow: isAnimationComplete => {
8139
+ if (isAnimationComplete)
8140
+ return;
8141
+ if (activeAirDatepickerField && activeAirDatepickerField !== this) {
8142
+ activeAirDatepickerField.picker?.hide();
8143
+ }
8144
+ activeAirDatepickerField = this;
8145
+ },
8146
+ onHide: isAnimationComplete => {
8147
+ if (isAnimationComplete && activeAirDatepickerField === this) {
8148
+ activeAirDatepickerField = undefined;
8149
+ }
8150
+ }
8151
+ };
8152
+ let multiple = false;
8153
+ if (this.el.multiple || dataset.dateRange === 'true') {
8154
+ pickerOptions.range = true;
8155
+ pickerOptions.multipleDatesSeparator = ' - ';
8156
+ multiple = true;
8157
+ }
8158
+ const initialValue = this.el.getAttribute('value')?.trim();
8159
+ if (initialValue) {
8160
+ pickerOptions.selectedDates = multiple
8161
+ ? initialValue.split(' - ').map(value => value.trim())
8162
+ : [initialValue];
8163
+ }
8164
+ if (dataset.dateTimepicker === 'true') {
8165
+ pickerOptions.timepicker = true;
8166
+ if (dataset.dateTimeFormat)
8167
+ pickerOptions.timeFormat = dataset.dateTimeFormat;
8168
+ }
8169
+ const supportedViews = ['days', 'months', 'years'];
8170
+ if (supportedViews.includes(dataset.dateView ?? '')) {
8171
+ pickerOptions.view = dataset.dateView;
8172
+ }
8173
+ if (supportedViews.includes(dataset.dateMinView ?? '')) {
8174
+ pickerOptions.minView = dataset.dateMinView;
8175
+ }
8176
+ if (dataset.dateMobile === 'true')
8177
+ pickerOptions.isMobile = true;
8178
+ if (dataset.datePosition) {
8179
+ pickerOptions.position = dataset.datePosition;
8180
+ }
8181
+ if (dataset.dateButtons) {
8182
+ const supportedButtons = ['today', 'clear'];
8183
+ pickerOptions.buttons = dataset.dateButtons
8184
+ .split(',')
8185
+ .map(button => button.trim())
8186
+ .filter(button => supportedButtons.includes(button));
8187
+ }
8188
+ if (this.el.hasAttribute('min') && this.el.getAttribute('min')) {
8189
+ pickerOptions.minDate = new Date(this.el.getAttribute('min'));
8190
+ }
8191
+ if (this.el.hasAttribute('max') && this.el.getAttribute('max')) {
8192
+ pickerOptions.maxDate = new Date(this.el.getAttribute('max'));
8193
+ }
8194
+ if (!this.el.required && !pickerOptions.buttons) {
8195
+ pickerOptions.buttons = ['clear'];
8196
+ }
8197
+ pickerOptions.onSelect = ({ date }) => {
8198
+ if (multiple && Array.isArray(date) && date.length === 1)
8199
+ return;
8200
+ this.el.dispatchEvent(new Event('input', { bubbles: true }));
8201
+ this.el.dispatchEvent(new Event('change', { bubbles: true }));
8202
+ };
8203
+ this.picker = new AirDatepicker(this.el, pickerOptions);
8204
+ document.addEventListener('click', this._handleOutsideClick);
8205
+ }
8206
+ }
8207
+
8208
+ const _defaults$6 = {
8209
+ plugins: []
8210
+ };
8211
+ // Each plugin needs its own literal `import('literal-string')` call (see
8212
+ // peer-loader.ts) so Vite/webpack/Rollup can statically discover it - a
8213
+ // generic specifier-driven loop can't produce that, hence one entry per
8214
+ // plugin instead of building the import call from PLUGIN_SPECS's string.
8215
+ const PLUGIN_LOADERS = {
8216
+ 'image-preview': {
8217
+ specifier: 'filepond-plugin-image-preview',
8218
+ globalName: 'FilePondPluginImagePreview',
8219
+ importer: () => import('filepond-plugin-image-preview')
8220
+ },
8221
+ 'file-validate-type': {
8222
+ specifier: 'filepond-plugin-file-validate-type',
8223
+ globalName: 'FilePondPluginFileValidateType',
8224
+ importer: () => import('filepond-plugin-file-validate-type')
8225
+ },
8226
+ 'image-exif-orientation': {
8227
+ specifier: 'filepond-plugin-image-exif-orientation',
8228
+ globalName: 'FilePondPluginImageExifOrientation',
8229
+ importer: () => import('filepond-plugin-image-exif-orientation')
8230
+ }
8231
+ };
8232
+ // @implement /Users/kzarshenas/Sites/CrazyProject/CrazyPHP/src/Front/Library/Utility/Form/File.ts
8233
+ // Enhances the EXISTING `.file-field` structure in place - add
8234
+ // `data-file-picker="filepond"` (+ optional `data-file-plugins="a,b,c"`) to
8235
+ // an otherwise completely stock `.file-field`, nothing else about the
8236
+ // markup changes. FilePond.create() hides the native `<input type=file>`
8237
+ // and injects its own root as a *sibling*, it never removes anything from
8238
+ // the DOM, so the surrounding button/label/file-path-wrapper stay intact
8239
+ // at rest - only the interactive drop area swaps in visually.
8240
+ //
8241
+ // FilePond and its plugins are optional peerDependencies, loaded on demand
8242
+ // via peer-loader.
8243
+ class FileInput extends Component {
8244
+ pond;
8245
+ ready;
8246
+ _fileEl;
8247
+ _pathEl;
8248
+ constructor(el, options) {
8249
+ super(el, options, FileInput);
8250
+ this.el.M_FileInput = this;
8251
+ const pluginsAttr = this.el.dataset.filePlugins;
8252
+ this.options = {
8253
+ ...FileInput.defaults,
8254
+ plugins: pluginsAttr
8255
+ ? pluginsAttr.split(',').map((p) => p.trim())
8256
+ : FileInput.defaults.plugins,
8257
+ ...options
8258
+ };
8259
+ this._fileEl = this.el.querySelector('input[type="file"]');
8260
+ this._pathEl = this.el.querySelector('.file-path');
8261
+ this.ready = this._setup();
8262
+ }
8263
+ static get defaults() {
8264
+ return _defaults$6;
8265
+ }
8266
+ static init(els, options = {}) {
8267
+ return super.init(els, options, FileInput);
8268
+ }
8269
+ static getInstance(el) {
8270
+ return el.M_FileInput;
8271
+ }
8272
+ destroy() {
8273
+ this.el.classList.remove('file-field-enhanced');
8274
+ this.el.querySelector('.btn')?.classList.remove('hide');
8275
+ this.el.querySelector('.file-path-wrapper')?.classList.remove('hide');
8276
+ this.pond?.destroy();
8277
+ this.el.M_FileInput = undefined;
8278
+ }
8279
+ /** Convenience wrapper over the underlying FilePond instance's own getFiles(). */
8280
+ getFiles() {
8281
+ return this.pond?.getFiles() ?? [];
8282
+ }
8283
+ async _setup() {
8284
+ if (!this._fileEl) {
8285
+ console.error(Error('.file-field enhanced with data-file-picker="filepond" needs an input[type=file]'));
8286
+ return;
8287
+ }
8288
+ const FilePond = await loadPeer({
8289
+ specifier: 'filepond',
8290
+ globalName: 'FilePond',
8291
+ feature: 'File input (FilePond) enhancement',
8292
+ cdnHint: '<link rel="stylesheet" href="path/to/filepond.min.css">\n' +
8293
+ ' <script src="path/to/filepond.min.js"></script>\n' +
8294
+ ' (self-hosted - copy from node_modules/filepond/dist/, or a CDN of your choice)'
8295
+ }, () => import('filepond'));
8296
+ const pluginNames = new Set(this.options.plugins);
8297
+ // file-validate-type is auto-registered whenever the input restricts
8298
+ // `accept`, matching CrazyPHP's own convention, even if the consumer
8299
+ // didn't list it explicitly in data-file-plugins.
8300
+ if (this._fileEl.accept)
8301
+ pluginNames.add('file-validate-type');
8302
+ for (const name of pluginNames) {
8303
+ const loader = PLUGIN_LOADERS[name];
8304
+ if (!loader)
8305
+ continue;
8306
+ const plugin = await loadPeer({
8307
+ specifier: loader.specifier,
8308
+ globalName: loader.globalName,
8309
+ feature: `File input FilePond plugin "${name}"`,
8310
+ cdnHint: `<script src="path/to/${loader.specifier}.min.js"></script> (self-hosted - copy from node_modules/${loader.specifier}/dist/, or a CDN of your choice)`
8311
+ }, loader.importer);
8312
+ FilePond.registerPlugin(plugin);
8313
+ }
8314
+ const pondOptions = {};
8315
+ const { dataset } = this._fileEl;
8316
+ const readBoolean = (value) => value !== 'false';
8317
+ pondOptions.allowMultiple = this._fileEl.multiple;
8318
+ pondOptions.disabled = this._fileEl.disabled;
8319
+ if (dataset.defaultFile)
8320
+ pondOptions.files = [dataset.defaultFile];
8321
+ if (dataset.maxFiles)
8322
+ pondOptions.maxFiles = Number(dataset.maxFiles);
8323
+ if (this._fileEl.multiple)
8324
+ pondOptions.allowReorder = readBoolean(dataset.allowReorder);
8325
+ if (dataset.labelIdle)
8326
+ pondOptions.labelIdle = dataset.labelIdle;
8327
+ if (dataset.instantUpload !== undefined)
8328
+ pondOptions.instantUpload = readBoolean(dataset.instantUpload);
8329
+ if (dataset.dropValidation !== undefined)
8330
+ pondOptions.dropValidation = readBoolean(dataset.dropValidation);
8331
+ if (dataset.imagePreviewHeight)
8332
+ pondOptions.imagePreviewHeight = Number(dataset.imagePreviewHeight);
8333
+ if (dataset.stylePanelLayout) {
8334
+ pondOptions.stylePanelLayout = dataset.stylePanelLayout;
8335
+ }
8336
+ if (dataset.stylePanelAspectRatio)
8337
+ pondOptions.stylePanelAspectRatio = dataset.stylePanelAspectRatio;
8338
+ this.pond = FilePond.create(this._fileEl, pondOptions);
8339
+ // FilePond inserts its own root as a *sibling* of the input it was
8340
+ // given - but that input lives inside .btn (stock .file-field markup
8341
+ // is `.btn > input[type=file]`), so the fresh FilePond root lands
8342
+ // inside .btn too. Move it back out to be a direct child of .file-field
8343
+ // itself before hiding .btn, or hiding .btn would take the whole
8344
+ // FilePond widget down with it.
8345
+ const pondRoot = this.pond.element;
8346
+ if (pondRoot) {
8347
+ this.el.appendChild(pondRoot);
8348
+ const fileHeight = Number(dataset.fileHeight);
8349
+ if (Number.isFinite(fileHeight) && fileHeight > 0) {
8350
+ pondRoot.style.height = `${fileHeight}px`;
8351
+ }
8352
+ // Matches CrazyPHP's own File.ts behavior - FilePond's free-tier
8353
+ // "Powered by FilePond" credit link doesn't fit a themed, branded UI.
8354
+ pondRoot.querySelectorAll('.filepond--credits').forEach((el) => el.remove());
8355
+ }
8356
+ // Everything from the stock .file-field is now redundant - FilePond's
8357
+ // own drop zone is the entire upload affordance. Hidden, not removed,
8358
+ // so the .file-field structure this component promises to preserve is
8359
+ // still there, just not shown alongside FilePond's widget.
8360
+ this.el.classList.add('file-field-enhanced');
8361
+ this.el.querySelector('.btn')?.classList.add('hide');
8362
+ this.el.querySelector('.file-path-wrapper')?.classList.add('hide');
8363
+ this._syncPathInput();
8364
+ this.pond.on('updatefiles', this._syncPathInput);
8365
+ }
8366
+ _syncPathInput = () => {
8367
+ if (!this._pathEl || !this.pond)
8368
+ return;
8369
+ this._pathEl.value = this.pond
8370
+ .getFiles()
8371
+ .map((f) => f.filename)
8372
+ .join(', ');
8373
+ };
8374
+ }
8375
+
8376
+ const _defaults$5 = {};
8377
+ function readRemoteSpec(el) {
8378
+ const raw = el.dataset.selectRemote;
8379
+ if (!raw)
8380
+ return undefined;
8381
+ try {
8382
+ return JSON.parse(raw);
8383
+ }
8384
+ catch {
8385
+ return undefined;
8386
+ }
8387
+ }
8388
+ // @implement /Users/kzarshenas/Sites/CrazyProject/CrazyPHP/src/Front/Library/Utility/Form/Select.ts
8389
+ // Enhances an EXISTING native `<select class="tomselected">` with Tom
8390
+ // Select - searchable, taggable, remote-loading, dependent-field wiring,
8391
+ // clear button, drag-drop reorder. Ported in a somewhat scoped form: the
8392
+ // CrazyPHP source's remote-loading path goes through its own app-specific
8393
+ // Crazyrequest/Crazyurl HTTP-client and query-param helpers, which have no
8394
+ // equivalent in a standalone UI library - this version uses a plain
8395
+ // `fetch()` instead, keeping the same `data-select-remote` JSON shape
8396
+ // (url/value/label/search/dataKey) and the same `{{field}}` render-template
8397
+ // convention.
8398
+ //
8399
+ // Coexistence with FormSelect: `.tomselected` is a recognized exclusion
8400
+ // marker in FormSelect's own AutoInit selector (see src/index.ts), so a
8401
+ // `.tomselected` select is never picked up by FormSelect regardless of
8402
+ // init ordering. This constructor still defensively tears down any
8403
+ // FormSelect instance found on the same element, belt-and-suspenders, in
8404
+ // case that selector rule is ever violated by hand.
8405
+ //
8406
+ // Tom Select is an optional peerDependency, loaded on demand via
8407
+ // peer-loader.
8408
+ class TomSelectField extends Component {
8409
+ tomSelect;
8410
+ ready;
8411
+ _dependsOnEl = null;
8412
+ constructor(el, options) {
8413
+ super(el, options, TomSelectField);
8414
+ this.el.M_TomSelectField = this;
8415
+ FormSelect.getInstance(this.el)?.destroy();
8416
+ this.options = {
8417
+ remote: readRemoteSpec(this.el),
8418
+ ...TomSelectField.defaults,
8419
+ ...options
8420
+ };
8421
+ this.ready = this._setup();
8422
+ }
8423
+ static get defaults() {
8424
+ return _defaults$5;
8425
+ }
8426
+ static init(els, options = {}) {
8427
+ return super.init(els, options, TomSelectField);
8428
+ }
8429
+ static getInstance(el) {
8430
+ return el.M_TomSelectField;
8431
+ }
8432
+ destroy() {
8433
+ if (this._dependsOnEl)
8434
+ this._dependsOnEl.removeEventListener('change', this._handleDependencyChange);
8435
+ this.tomSelect?.destroy();
8436
+ this.el.M_TomSelectField = undefined;
8437
+ }
8438
+ _handleDependencyChange = () => {
8439
+ this.tomSelect?.clear();
8440
+ this.tomSelect?.clearOptions();
8441
+ this.tomSelect?.load?.('');
8442
+ };
8443
+ async _setup() {
8444
+ const TomSelect = await loadPeer({
8445
+ specifier: 'tom-select',
8446
+ globalName: 'TomSelect',
8447
+ feature: 'Select (Tom Select) enhancement',
8448
+ cdnHint: '<script src="path/to/tom-select.complete.min.js"></script> (self-hosted - copy from node_modules/tom-select/dist/js/, or a CDN of your choice)'
8449
+ }, () => import('tom-select'));
8450
+ const dataset = this.el.dataset;
8451
+ const settings = {
8452
+ persist: false,
8453
+ createOnBlur: true,
8454
+ create: 'selectTag' in dataset,
8455
+ plugins: {},
8456
+ ...this.options.settings
8457
+ };
8458
+ if ('selectClear' in dataset) {
8459
+ settings.plugins.clear_button = { title: dataset.selectClear || 'Clear' };
8460
+ }
8461
+ if ('selectTag' in dataset || this.el.multiple) {
8462
+ settings.plugins.caret_position = {};
8463
+ settings.plugins.drag_drop = {};
8464
+ }
8465
+ if (this.el.classList.contains('icons')) {
8466
+ const renderWithIcon = (data, escape) => {
8467
+ const icon = data.icon ? `<img src="${escape(String(data.icon))}" alt="" />` : '';
8468
+ return `<div class="ts-option-content">${icon}<span>${escape(String(data.text ?? ''))}</span></div>`;
8469
+ };
8470
+ settings.render = { ...settings.render, option: renderWithIcon, item: renderWithIcon };
8471
+ }
8472
+ const remote = this.options.remote;
8473
+ if (remote) {
8474
+ settings.valueField = remote.value;
8475
+ if (remote.search)
8476
+ settings.searchField = [remote.search];
8477
+ if (remote.label && remote.label.includes('{{') && remote.label.includes('}}')) {
8478
+ const renderTemplate = (data, escape) => `<div>${remote.label.replace(/\{\{(.*?)\}\}/g, (_m, key) => escape(String(data[key] ?? '')))}</div>`;
8479
+ settings.render = { option: renderTemplate, item: renderTemplate };
8480
+ }
8481
+ else {
8482
+ settings.labelField = remote.label;
8483
+ }
8484
+ settings.load = (query, callback) => {
8485
+ fetch(remote.url)
8486
+ .then((r) => r.json())
8487
+ .then((value) => {
8488
+ const results = remote.dataKey
8489
+ ? remote.dataKey.split('.').reduce((acc, key) => acc && acc[key], value)
8490
+ : value?.results ?? value;
8491
+ callback(Array.isArray(results) ? results : []);
8492
+ })
8493
+ .catch(() => callback([]));
8494
+ };
8495
+ }
8496
+ this.tomSelect = new TomSelect(this.el, settings);
8497
+ if (dataset.depends) {
8498
+ this._dependsOnEl = document.querySelector(dataset.depends);
8499
+ this._dependsOnEl?.addEventListener('change', this._handleDependencyChange);
8500
+ }
8501
+ }
8502
+ }
8503
+
7444
8504
  const _defaults$4 = {
7445
8505
  onOpen: null,
7446
8506
  onClose: null
@@ -8321,7 +9381,7 @@ var M = (function (exports) {
8321
9381
  }
8322
9382
 
8323
9383
  /* eslint-disable @typescript-eslint/no-unused-vars */
8324
- const version = '2.3.3-1.0.2';
9384
+ const version = '2.3.3-1.0.21';
8325
9385
  /**
8326
9386
  * Convenience helper matching v1's `M.toast({...})` call, since Toast is a
8327
9387
  * class in v2 with no bare functional equivalent of its own.
@@ -8336,6 +9396,8 @@ var M = (function (exports) {
8336
9396
  */
8337
9397
  function AutoInit(context = document.body, options) {
8338
9398
  const registry = {
9399
+ Alert: context.querySelectorAll('.alert:not(.no-autoinit)'),
9400
+ Kanban: context.querySelectorAll('.kanban-board:not(.no-autoinit)'),
8339
9401
  Autocomplete: context.querySelectorAll('.autocomplete:not(.no-autoinit)'),
8340
9402
  Cards: context.querySelectorAll('.cards:not(.no-autoinit)'),
8341
9403
  Carousel: context.querySelectorAll('.carousel:not(.no-autoinit)'),
@@ -8348,15 +9410,28 @@ var M = (function (exports) {
8348
9410
  Parallax: context.querySelectorAll('.parallax:not(.no-autoinit)'),
8349
9411
  Pushpin: context.querySelectorAll('.pushpin:not(.no-autoinit)'),
8350
9412
  ScrollSpy: context.querySelectorAll('.scrollspy:not(.no-autoinit)'),
8351
- FormSelect: context.querySelectorAll('select:not(.no-autoinit)'),
9413
+ // Excludes .tomselected - a select opted into TomSelectField instead
9414
+ // (see below), never eligible for FormSelect regardless of ordering.
9415
+ FormSelect: context.querySelectorAll('select:not(.no-autoinit):not(.tomselected)'),
8352
9416
  Sidenav: context.querySelectorAll('.sidenav:not(.no-autoinit)'),
8353
9417
  Tabs: context.querySelectorAll('.tabs:not(.no-autoinit)'),
8354
9418
  TapTarget: context.querySelectorAll('.tap-target:not(.no-autoinit)'),
8355
9419
  Timepicker: context.querySelectorAll('.timepicker:not(.no-autoinit)'),
8356
9420
  Tooltip: context.querySelectorAll('.tooltipped:not(.no-autoinit)'),
8357
- FloatingActionButton: context.querySelectorAll('.fixed-action-btn:not(.no-autoinit)')
9421
+ FloatingActionButton: context.querySelectorAll('.fixed-action-btn:not(.no-autoinit)'),
9422
+ // Excludes .fixed-action-btn.toolbar - that's an unrelated FAB display
9423
+ // mode reusing the same class name, not this component.
9424
+ Toolbar: context.querySelectorAll('.toolbar:not(.fixed-action-btn):not(.no-autoinit)'),
9425
+ PasswordInput: context.querySelectorAll('input[data-password-toggle]:not(.no-autoinit)'),
9426
+ NumberInput: context.querySelectorAll('input[data-type="number"]:not(.no-autoinit)'),
9427
+ ColorInput: context.querySelectorAll('input[type="color"][data-color-picker="pickr"]:not(.no-autoinit)'),
9428
+ AirDatepickerField: context.querySelectorAll('input[data-date-picker="air-datepicker"]:not(.no-autoinit)'),
9429
+ FileInput: context.querySelectorAll('.file-field[data-file-picker="filepond"]:not(.no-autoinit)'),
9430
+ TomSelectField: context.querySelectorAll('select.tomselected:not(.no-autoinit)')
8358
9431
  };
8359
9432
  Autocomplete.init(registry.Autocomplete, options?.Autocomplete ?? {});
9433
+ Alert.init(registry.Alert, options?.Alert ?? {});
9434
+ Kanban.init(registry.Kanban, options?.Kanban ?? {});
8360
9435
  Cards.init(registry.Cards, options?.Cards ?? {});
8361
9436
  Carousel.init(registry.Carousel, options?.Carousel ?? {});
8362
9437
  Chips.init(registry.Chips, options?.Chips ?? {});
@@ -8375,6 +9450,13 @@ var M = (function (exports) {
8375
9450
  Timepicker.init(registry.Timepicker, options?.Timepicker ?? {});
8376
9451
  Tooltip.init(registry.Tooltip, options?.Tooltip ?? {});
8377
9452
  FloatingActionButton.init(registry.FloatingActionButton, options?.FloatingActionButton ?? {});
9453
+ Toolbar.init(registry.Toolbar, options?.Toolbar ?? {});
9454
+ PasswordInput.init(registry.PasswordInput, options?.PasswordInput ?? {});
9455
+ NumberInput.init(registry.NumberInput, options?.NumberInput ?? {});
9456
+ ColorInput.init(registry.ColorInput, options?.ColorInput ?? {});
9457
+ AirDatepickerField.init(registry.AirDatepickerField, options?.AirDatepickerField ?? {});
9458
+ FileInput.init(registry.FileInput, options?.FileInput ?? {});
9459
+ TomSelectField.init(registry.TomSelectField, options?.TomSelectField ?? {});
8378
9460
  }
8379
9461
  // Init
8380
9462
  if (typeof document !== 'undefined') {
@@ -8389,6 +9471,8 @@ var M = (function (exports) {
8389
9471
  Range.Init();
8390
9472
  Cards.Init();
8391
9473
 
9474
+ exports.AirDatepickerField = AirDatepickerField;
9475
+ exports.Alert = Alert;
8392
9476
  exports.AutoInit = AutoInit;
8393
9477
  exports.Autocomplete = Autocomplete;
8394
9478
  exports.Cards = Cards;
@@ -8396,14 +9480,19 @@ var M = (function (exports) {
8396
9480
  exports.CharacterCounter = CharacterCounter;
8397
9481
  exports.Chips = Chips;
8398
9482
  exports.Collapsible = Collapsible;
9483
+ exports.ColorInput = ColorInput;
8399
9484
  exports.Datepicker = Datepicker;
8400
9485
  exports.Dropdown = Dropdown;
9486
+ exports.FileInput = FileInput;
8401
9487
  exports.FloatingActionButton = FloatingActionButton;
8402
9488
  exports.FormSelect = FormSelect;
8403
9489
  exports.Forms = Forms;
9490
+ exports.Kanban = Kanban;
8404
9491
  exports.Materialbox = Materialbox;
8405
9492
  exports.Modal = Modal;
9493
+ exports.NumberInput = NumberInput;
8406
9494
  exports.Parallax = Parallax;
9495
+ exports.PasswordInput = PasswordInput;
8407
9496
  exports.Pushpin = Pushpin;
8408
9497
  exports.Range = Range;
8409
9498
  exports.ScrollSpy = ScrollSpy;
@@ -8413,6 +9502,8 @@ var M = (function (exports) {
8413
9502
  exports.TapTarget = TapTarget;
8414
9503
  exports.Timepicker = Timepicker;
8415
9504
  exports.Toast = Toast;
9505
+ exports.TomSelectField = TomSelectField;
9506
+ exports.Toolbar = Toolbar;
8416
9507
  exports.Tooltip = Tooltip;
8417
9508
  exports.Waves = Waves;
8418
9509
  exports.toast = toast;