admin-lte 4.1.0 → 4.3.1

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 (57) hide show
  1. package/CHANGELOG.md +57 -1
  2. package/README.md +23 -7
  3. package/dist/css/adminlte-docs.css +1 -1
  4. package/dist/css/adminlte-docs.css.map +1 -1
  5. package/dist/css/adminlte-docs.min.css +1 -1
  6. package/dist/css/adminlte-docs.min.css.map +1 -1
  7. package/dist/css/adminlte-docs.rtl.css +1 -1
  8. package/dist/css/adminlte-docs.rtl.css.map +1 -1
  9. package/dist/css/adminlte-docs.rtl.min.css +1 -1
  10. package/dist/css/adminlte-docs.rtl.min.css.map +1 -1
  11. package/dist/css/adminlte-select2.css +329 -0
  12. package/dist/css/adminlte-select2.css.map +1 -0
  13. package/dist/css/adminlte-select2.min.css +12 -0
  14. package/dist/css/adminlte-select2.min.css.map +1 -0
  15. package/dist/css/adminlte-select2.rtl.css +328 -0
  16. package/dist/css/adminlte-select2.rtl.css.map +1 -0
  17. package/dist/css/adminlte-select2.rtl.min.css +12 -0
  18. package/dist/css/adminlte-select2.rtl.min.css.map +1 -0
  19. package/dist/css/adminlte.css +332 -131
  20. package/dist/css/adminlte.css.map +1 -1
  21. package/dist/css/adminlte.min.css +2 -2
  22. package/dist/css/adminlte.min.css.map +1 -1
  23. package/dist/css/adminlte.rtl.css +332 -131
  24. package/dist/css/adminlte.rtl.css.map +1 -1
  25. package/dist/css/adminlte.rtl.min.css +2 -2
  26. package/dist/css/adminlte.rtl.min.css.map +1 -1
  27. package/dist/js/adminlte.esm.js +300 -109
  28. package/dist/js/adminlte.esm.js.map +1 -1
  29. package/dist/js/adminlte.esm.min.js +2 -2
  30. package/dist/js/adminlte.esm.min.js.map +1 -1
  31. package/dist/js/adminlte.js +302 -108
  32. package/dist/js/adminlte.js.map +1 -1
  33. package/dist/js/adminlte.min.js +2 -2
  34. package/dist/js/adminlte.min.js.map +1 -1
  35. package/dist/js/types/adminlte.d.ts +3 -1
  36. package/dist/js/types/base-component.d.ts +24 -0
  37. package/dist/js/types/color-mode.d.ts +24 -6
  38. package/dist/js/types/push-menu.d.ts +21 -0
  39. package/dist/js/types/sidebar-search.d.ts +46 -0
  40. package/dist/js/types/util/index.d.ts +38 -1
  41. package/package.json +24 -23
  42. package/src/scss/_app-sidebar.scss +12 -0
  43. package/src/scss/_ribbon.scss +75 -0
  44. package/src/scss/_variables.scss +28 -0
  45. package/src/scss/_widgets.scss +192 -0
  46. package/src/scss/adminlte-docs.scss +1 -1
  47. package/src/scss/adminlte-select2.scss +31 -0
  48. package/src/scss/adminlte.scss +1 -1
  49. package/src/scss/compat/_select2.scss +476 -0
  50. package/src/scss/parts/_extra-components.scss +2 -0
  51. package/src/ts/accessibility.ts +31 -15
  52. package/src/ts/adminlte.ts +7 -3
  53. package/src/ts/base-component.ts +30 -3
  54. package/src/ts/color-mode.ts +100 -20
  55. package/src/ts/push-menu.ts +37 -7
  56. package/src/ts/sidebar-search.ts +252 -0
  57. package/src/ts/util/index.ts +79 -15
@@ -0,0 +1,476 @@
1
+ //
2
+ // Compatibility: Select2
3
+ //
4
+ // Styling only. AdminLTE bundles neither Select2 nor jQuery — this sheet
5
+ // exists for projects that cannot drop Select2 yet (server-rendered ERP
6
+ // forms, vendor plugins that initialise it for you) and want it to look like
7
+ // the rest of a Bootstrap 5.3 form.
8
+ //
9
+ // New code should use Tom Select instead; see the Recommended Integrations
10
+ // docs page for the API mapping.
11
+ //
12
+ // Load order matters — this sheet layers on top of Select2's own CSS:
13
+ //
14
+ // <link rel="stylesheet" href="adminlte.min.css">
15
+ // <link rel="stylesheet" href="select2.min.css">
16
+ // <link rel="stylesheet" href="adminlte-select2.min.css">
17
+ //
18
+ // Everything resolves through Bootstrap CSS variables at runtime, so
19
+ // `data-bs-theme` switches and reskins need no recompile. Selectors are
20
+ // scoped to `.select2-container--default` (Select2's built-in theme) to win
21
+ // against the rules in select2.css without `!important`.
22
+ //
23
+ // Markup target: Select2 4.1.x, with fallbacks for 4.0.x choice markup.
24
+ //
25
+
26
+ // Sits above .modal (1055) but below .popover (1070) so a Select2 dropdown
27
+ // opened inside a modal is visible — the single most-reported Select2 +
28
+ // Bootstrap 5 problem, and the reason `dropdownParent` is usually needed.
29
+ $lte-select2-zindex: $zindex-modal + 5 !default;
30
+
31
+ $lte-select2-choice-bg: var(--#{$prefix}secondary-bg) !default;
32
+ $lte-select2-choice-color: var(--#{$prefix}body-color) !default;
33
+ $lte-select2-choice-border-color: var(--#{$prefix}border-color) !default;
34
+ $lte-select2-choice-gap: .25rem !default;
35
+ $lte-select2-choice-padding-y: .0625rem !default;
36
+ $lte-select2-choice-padding-x: .375rem !default;
37
+
38
+ //
39
+ // Container
40
+ //
41
+ // Select2 writes an inline `width` on the container, so sizing is left alone;
42
+ // only the box model needs aligning with a block-level form control.
43
+ //
44
+ .select2-container {
45
+ max-width: 100%;
46
+ vertical-align: top;
47
+ }
48
+
49
+ //
50
+ // Single select — mirrors `.form-select`
51
+ //
52
+ .select2-container--default {
53
+ .select2-selection--single {
54
+ // Bootstrap's chevron, swapped for the light-on-dark variant further down.
55
+ --#{$lte-prefix}select2-bg-img: #{escape-svg($form-select-indicator)};
56
+
57
+ height: auto;
58
+ padding: $form-select-padding-y $form-select-indicator-padding $form-select-padding-y $form-select-padding-x;
59
+ font-family: $form-select-font-family;
60
+ @include font-size($form-select-font-size);
61
+ font-weight: $form-select-font-weight;
62
+ line-height: $form-select-line-height;
63
+ color: $form-select-color;
64
+ background-color: $form-select-bg;
65
+ background-image: var(--#{$lte-prefix}select2-bg-img);
66
+ background-repeat: no-repeat;
67
+ background-position: $form-select-bg-position;
68
+ background-size: $form-select-bg-size;
69
+ border: $form-select-border-width solid $form-select-border-color;
70
+ @include border-radius($form-select-border-radius, 0);
71
+ @include box-shadow($form-select-box-shadow);
72
+ @include transition($form-select-transition);
73
+
74
+ .select2-selection__rendered {
75
+ padding: 0;
76
+ line-height: inherit;
77
+ color: inherit;
78
+ }
79
+
80
+ .select2-selection__placeholder {
81
+ color: $input-placeholder-color;
82
+ }
83
+
84
+ // Bootstrap's chevron replaces the bordered triangle.
85
+ .select2-selection__arrow {
86
+ display: none;
87
+ }
88
+ }
89
+
90
+ //
91
+ // Multi select — mirrors `.form-control`, with choices as pills
92
+ //
93
+ .select2-selection--multiple {
94
+ display: flex;
95
+ flex-wrap: wrap;
96
+ gap: $lte-select2-choice-gap;
97
+ align-items: center;
98
+ min-height: $input-height;
99
+ padding: ($input-padding-y - $lte-select2-choice-padding-y) $input-padding-x;
100
+ font-family: $input-font-family;
101
+ @include font-size($input-font-size);
102
+ font-weight: $input-font-weight;
103
+ line-height: $input-line-height;
104
+ color: $input-color;
105
+ background-color: $input-bg;
106
+ border: $input-border-width solid $input-border-color;
107
+ @include border-radius($input-border-radius, 0);
108
+ @include box-shadow($input-box-shadow);
109
+ @include transition($input-transition);
110
+
111
+ // Select2 wraps the choices in a <ul> but leaves the inline search field
112
+ // as that list's *sibling*, so a flex context on the list alone would
113
+ // stack the search on its own row and double the control's height.
114
+ // `display: contents` promotes the individual choices to flex items of
115
+ // the control, letting the search field flow after the last one.
116
+ .select2-selection__rendered {
117
+ display: contents;
118
+ padding: 0;
119
+ margin: 0;
120
+ line-height: inherit;
121
+ }
122
+
123
+ .select2-selection__choice {
124
+ display: inline-flex;
125
+ align-items: center;
126
+ max-width: 100%;
127
+ padding: 0;
128
+ margin: 0;
129
+ overflow: hidden;
130
+ @include font-size($font-size-sm);
131
+ color: $lte-select2-choice-color;
132
+ background-color: $lte-select2-choice-bg;
133
+ border: $input-border-width solid $lte-select2-choice-border-color;
134
+ @include border-radius($border-radius-sm);
135
+ }
136
+
137
+ // 4.1.x wraps the label in its own element; 4.0.x leaves it as a bare
138
+ // text node, hence the padding on the choice itself further down.
139
+ .select2-selection__choice__display {
140
+ padding: $lte-select2-choice-padding-y $lte-select2-choice-padding-x;
141
+ margin: 0;
142
+ overflow: hidden;
143
+ text-overflow: ellipsis;
144
+ white-space: nowrap;
145
+ }
146
+
147
+ .select2-selection__choice__remove {
148
+ position: static;
149
+ display: flex;
150
+ align-items: center;
151
+ align-self: stretch;
152
+ padding: 0 $lte-select2-choice-padding-x;
153
+ color: var(--#{$prefix}secondary-color);
154
+ background-color: transparent;
155
+ border: 0;
156
+ border-right: $input-border-width solid $lte-select2-choice-border-color;
157
+ @include border-radius(0);
158
+ @include transition(color .15s ease-in-out, background-color .15s ease-in-out);
159
+
160
+ &:hover,
161
+ &:focus-visible {
162
+ color: var(--#{$prefix}danger-text-emphasis);
163
+ background-color: var(--#{$prefix}danger-bg-subtle);
164
+ }
165
+
166
+ &:focus-visible {
167
+ outline: 0;
168
+ box-shadow: $focus-ring-box-shadow;
169
+ }
170
+ }
171
+
172
+ .select2-search--inline {
173
+ display: flex;
174
+ flex: 1 1 auto;
175
+ align-items: center;
176
+ min-width: 3rem;
177
+ }
178
+
179
+ // Select2 renders the inline search as a `rows="2"` <textarea>, so its
180
+ // height has to be pinned to one line — `height: auto` would resolve to
181
+ // two rows and double the control's height. Placeholder text lives in
182
+ // this field rather than a dedicated element.
183
+ .select2-search--inline .select2-search__field {
184
+ height: $input-line-height * 1em;
185
+ min-height: 0;
186
+ padding: 0;
187
+ margin: 0;
188
+ font-family: inherit;
189
+ @include font-size($input-font-size);
190
+ line-height: $input-line-height;
191
+ color: inherit;
192
+
193
+ &::placeholder {
194
+ color: $input-placeholder-color;
195
+ }
196
+ }
197
+ }
198
+
199
+ //
200
+ // Clear ("remove all") button
201
+ //
202
+ .select2-selection__clear {
203
+ padding: 0;
204
+ margin: 0;
205
+ color: var(--#{$prefix}secondary-color);
206
+ background-color: transparent;
207
+ border: 0;
208
+
209
+ &:hover {
210
+ color: var(--#{$prefix}danger);
211
+ }
212
+ }
213
+
214
+ .select2-selection--single .select2-selection__clear {
215
+ float: right;
216
+ margin-right: $lte-select2-choice-gap;
217
+ }
218
+
219
+ .select2-selection--multiple .select2-selection__clear {
220
+ top: $input-padding-y;
221
+ margin-top: 0;
222
+ margin-right: $lte-select2-choice-gap;
223
+ }
224
+
225
+ //
226
+ // Focus and open states — Bootstrap's focus ring, not Select2's outline
227
+ //
228
+ &.select2-container--focus,
229
+ &.select2-container--open {
230
+ .select2-selection--single,
231
+ .select2-selection--multiple {
232
+ border-color: $input-focus-border-color;
233
+ outline: 0;
234
+
235
+ @if $enable-shadows {
236
+ @include box-shadow($input-box-shadow, $input-focus-box-shadow);
237
+ } @else {
238
+ box-shadow: $input-focus-box-shadow;
239
+ }
240
+ }
241
+ }
242
+
243
+ //
244
+ // Disabled
245
+ //
246
+ &.select2-container--disabled {
247
+ .select2-selection--single,
248
+ .select2-selection--multiple {
249
+ color: $form-select-disabled-color;
250
+ cursor: default;
251
+ background-color: $form-select-disabled-bg;
252
+ border-color: $form-select-disabled-border-color;
253
+ }
254
+
255
+ .select2-selection__choice__remove {
256
+ display: none;
257
+ }
258
+ }
259
+
260
+ //
261
+ // Dropdown panel
262
+ //
263
+ .select2-dropdown {
264
+ color: var(--#{$prefix}body-color);
265
+ background-color: var(--#{$prefix}body-bg);
266
+ border-color: $input-focus-border-color;
267
+ @include border-radius($dropdown-border-radius);
268
+ @include box-shadow($dropdown-box-shadow);
269
+ }
270
+
271
+ // Square off the edge that meets the control so the two read as one shape.
272
+ .select2-dropdown--below {
273
+ @include border-top-radius(0);
274
+ }
275
+
276
+ .select2-dropdown--above {
277
+ @include border-bottom-radius(0);
278
+ }
279
+
280
+ //
281
+ // Dropdown search field — mirrors `.form-control-sm`
282
+ //
283
+ .select2-search--dropdown {
284
+ padding: $dropdown-padding-y $dropdown-item-padding-x;
285
+
286
+ .select2-search__field {
287
+ padding: $input-padding-y-sm $input-padding-x-sm;
288
+ @include font-size($input-font-size-sm);
289
+ line-height: $input-line-height;
290
+ color: $input-color;
291
+ background-color: $input-bg;
292
+ border: $input-border-width solid $input-border-color;
293
+ @include border-radius($input-border-radius-sm);
294
+ @include transition($input-transition);
295
+
296
+ &:focus {
297
+ border-color: $input-focus-border-color;
298
+ outline: 0;
299
+
300
+ @if $enable-shadows {
301
+ @include box-shadow($input-box-shadow, $input-focus-box-shadow);
302
+ } @else {
303
+ box-shadow: $input-focus-box-shadow;
304
+ }
305
+ }
306
+ }
307
+ }
308
+
309
+ //
310
+ // Results
311
+ //
312
+ // Only the top-level list scrolls; nested group lists must not.
313
+ .select2-results > .select2-results__options {
314
+ max-height: 15rem;
315
+ }
316
+
317
+ .select2-results__option {
318
+ padding: $dropdown-item-padding-y $dropdown-item-padding-x;
319
+ @include font-size($font-size-base);
320
+ color: var(--#{$prefix}body-color);
321
+ }
322
+
323
+ .select2-results__option--selected {
324
+ color: var(--#{$prefix}emphasis-color);
325
+ background-color: var(--#{$prefix}tertiary-bg);
326
+ }
327
+
328
+ .select2-results__option--highlighted.select2-results__option--selectable {
329
+ color: $component-active-color;
330
+ background-color: $component-active-bg;
331
+ }
332
+
333
+ .select2-results__option--disabled {
334
+ color: var(--#{$prefix}secondary-color);
335
+ }
336
+
337
+ // Option groups: an unpadded <li> holding a label plus a nested list.
338
+ .select2-results__option--group {
339
+ padding: 0;
340
+ }
341
+
342
+ .select2-results__group {
343
+ padding: $dropdown-item-padding-y $dropdown-item-padding-x;
344
+ @include font-size($font-size-sm);
345
+ font-weight: $font-weight-semibold;
346
+ color: var(--#{$prefix}secondary-color);
347
+ text-transform: uppercase;
348
+ letter-spacing: .03em;
349
+ }
350
+ }
351
+
352
+ //
353
+ // Dark mode — only the caret is a baked-in colour; every other value above
354
+ // already reads a Bootstrap CSS variable and follows `data-bs-theme` for free.
355
+ //
356
+ @if $enable-dark-mode {
357
+ @include color-mode(dark, true) {
358
+ .select2-container--default .select2-selection--single {
359
+ --#{$lte-prefix}select2-bg-img: #{escape-svg($form-select-indicator-dark)};
360
+ }
361
+ }
362
+ }
363
+
364
+ //
365
+ // Sizing — driven by the class already on the original <select>, which Select2
366
+ // leaves in the DOM immediately before the container it generates. No extra
367
+ // `containerCssClass` option needed.
368
+ //
369
+ .form-select-sm,
370
+ .form-control-sm {
371
+ + .select2-container--default .select2-selection--single {
372
+ padding-top: $form-select-padding-y-sm;
373
+ padding-bottom: $form-select-padding-y-sm;
374
+ padding-left: $form-select-padding-x-sm;
375
+ @include font-size($form-select-font-size-sm);
376
+ @include border-radius($form-select-border-radius-sm);
377
+ }
378
+
379
+ + .select2-container--default .select2-selection--multiple {
380
+ min-height: $input-height-sm;
381
+ padding: ($input-padding-y-sm - $lte-select2-choice-padding-y) $input-padding-x-sm;
382
+ @include font-size($input-font-size-sm);
383
+ @include border-radius($input-border-radius-sm);
384
+ }
385
+ }
386
+
387
+ .form-select-lg,
388
+ .form-control-lg {
389
+ + .select2-container--default .select2-selection--single {
390
+ padding-top: $form-select-padding-y-lg;
391
+ padding-bottom: $form-select-padding-y-lg;
392
+ padding-left: $form-select-padding-x-lg;
393
+ @include font-size($form-select-font-size-lg);
394
+ @include border-radius($form-select-border-radius-lg);
395
+ }
396
+
397
+ + .select2-container--default .select2-selection--multiple {
398
+ min-height: $input-height-lg;
399
+ padding: ($input-padding-y-lg - $lte-select2-choice-padding-y) $input-padding-x-lg;
400
+ @include font-size($input-font-size-lg);
401
+ @include border-radius($input-border-radius-lg);
402
+ }
403
+ }
404
+
405
+ //
406
+ // Validation states — same trigger as Bootstrap's, `.is-invalid` / `.is-valid`
407
+ // on the field itself.
408
+ //
409
+ .is-invalid + .select2-container--default {
410
+ .select2-selection--single,
411
+ .select2-selection--multiple {
412
+ border-color: var(--#{$prefix}form-invalid-border-color);
413
+ }
414
+
415
+ &.select2-container--focus,
416
+ &.select2-container--open {
417
+ .select2-selection--single,
418
+ .select2-selection--multiple {
419
+ box-shadow: 0 0 $input-btn-focus-blur $input-focus-width rgba(var(--#{$prefix}danger-rgb), $input-btn-focus-color-opacity);
420
+ }
421
+ }
422
+ }
423
+
424
+ .is-valid + .select2-container--default {
425
+ .select2-selection--single,
426
+ .select2-selection--multiple {
427
+ border-color: var(--#{$prefix}form-valid-border-color);
428
+ }
429
+
430
+ &.select2-container--focus,
431
+ &.select2-container--open {
432
+ .select2-selection--single,
433
+ .select2-selection--multiple {
434
+ box-shadow: 0 0 $input-btn-focus-blur $input-focus-width rgba(var(--#{$prefix}success-rgb), $input-btn-focus-color-opacity);
435
+ }
436
+ }
437
+ }
438
+
439
+ //
440
+ // Input groups — the container has to behave like the `.form-control` it
441
+ // replaced, and only the outer corners stay rounded.
442
+ //
443
+ .input-group > .select2-container--default {
444
+ flex: 1 1 auto;
445
+ // Select2 writes `width` as an inline style, so `!important` is the only way
446
+ // to hand sizing back to the flex container. Matches `.form-control`'s own
447
+ // input-group sizing.
448
+ width: 1% !important;
449
+ min-width: 0;
450
+
451
+ &:not(:last-child) .select2-selection {
452
+ @include border-end-radius(0);
453
+ }
454
+
455
+ &:not(:first-child) .select2-selection {
456
+ @include border-start-radius(0);
457
+ }
458
+
459
+ // An open dropdown has to sit above the neighbouring input-group children,
460
+ // which Bootstrap raises to z-index 5 on focus.
461
+ &.select2-container--open {
462
+ z-index: 5;
463
+ }
464
+ }
465
+
466
+ //
467
+ // Stacking — Select2 appends the dropdown's container to <body> at z-index
468
+ // 1051, which is below Bootstrap 5's modal (1055).
469
+ //
470
+ .select2-container--open {
471
+ z-index: $lte-select2-zindex;
472
+ }
473
+
474
+ .select2-close-mask {
475
+ z-index: $lte-select2-zindex - 1;
476
+ }
@@ -7,3 +7,5 @@
7
7
  @import "../timeline";
8
8
  @import "../direct-chat";
9
9
  @import "../toasts";
10
+ @import "../ribbon";
11
+ @import "../widgets";
@@ -115,20 +115,32 @@ export class AccessibilityManager {
115
115
  }
116
116
 
117
117
  private ensureSkipTargets(): void {
118
- const main = document.querySelector('#main, main, [role="main"]')
119
- if (main && !main.id) {
120
- main.id = 'main'
121
- }
122
- if (main && !main.hasAttribute('tabindex')) {
123
- main.setAttribute('tabindex', '-1')
124
- }
118
+ // An element the page already gave the id to always wins. This used to be
119
+ // one querySelector over `#navigation, nav, [role="navigation"]`, but a
120
+ // selector list returns the first match in *document order* rather than
121
+ // the first selector that matched — so a page whose sidebar menu carried
122
+ // `id="navigation"` had the id stamped a second time onto the header
123
+ // <nav> that precedes it, leaving a duplicate id and pointing both the
124
+ // skip link and any `#navigation` lookup at the wrong element.
125
+ const targets: Array<[string, string]> = [
126
+ ['main', 'main, [role="main"]'],
127
+ ['navigation', 'nav, [role="navigation"]']
128
+ ]
125
129
 
126
- const nav = document.querySelector('#navigation, nav, [role="navigation"]')
127
- if (nav && !nav.id) {
128
- nav.id = 'navigation'
129
- }
130
- if (nav && !nav.hasAttribute('tabindex')) {
131
- nav.setAttribute('tabindex', '-1')
130
+ for (const [id, fallbackSelector] of targets) {
131
+ const target = document.getElementById(id) ?? document.querySelector(fallbackSelector)
132
+
133
+ if (!target) {
134
+ continue
135
+ }
136
+
137
+ if (!target.id) {
138
+ target.id = id
139
+ }
140
+
141
+ if (!target.hasAttribute('tabindex')) {
142
+ target.setAttribute('tabindex', '-1')
143
+ }
132
144
  }
133
145
  }
134
146
 
@@ -357,11 +369,15 @@ export class AccessibilityManager {
357
369
  }
358
370
 
359
371
  // Handle invalid state unless the element explicitly opts out via the
360
- // 'disable-adminlte-validations' class.
372
+ // 'disable-adminlte-validations' class. Registered with the lifecycle
373
+ // signal: this runs once per cycle, and under a framework that
374
+ // re-initialises against a persistent <body> (initialize()) the inputs
375
+ // survive the cycle — an unsignalled listener would stack one handler
376
+ // per re-init on every field.
361
377
  if (!htmlInput.classList.contains('disable-adminlte-validations')) {
362
378
  htmlInput.addEventListener('invalid', () => {
363
379
  this.handleFormError(htmlInput)
364
- })
380
+ }, { signal: this.signal })
365
381
  }
366
382
  })
367
383
  }
@@ -1,4 +1,4 @@
1
- import { onDOMContentLoaded } from './util/index.js'
1
+ import { initialize, teardown, onDOMContentLoaded } from './util/index.js'
2
2
  import Layout from './layout.js'
3
3
  import CardWidget from './card-widget.js'
4
4
  import Treeview from './treeview.js'
@@ -6,10 +6,11 @@ import DirectChat from './direct-chat.js'
6
6
  import FullScreen from './fullscreen.js'
7
7
  import PushMenu from './push-menu.js'
8
8
  import ColorMode from './color-mode.js'
9
+ import SidebarSearch from './sidebar-search.js'
9
10
  import { initAccessibility } from './accessibility.js'
10
11
 
11
12
  /**
12
- * AdminLTE v4.1.0
13
+ * AdminLTE v4.3.1
13
14
  * Author: Colorlib
14
15
  * Website: AdminLTE.io <https://adminlte.io>
15
16
  * License: Open source - MIT <https://opensource.org/licenses/MIT>
@@ -40,5 +41,8 @@ export {
40
41
  FullScreen,
41
42
  PushMenu,
42
43
  ColorMode,
43
- initAccessibility
44
+ SidebarSearch,
45
+ initAccessibility,
46
+ initialize,
47
+ teardown
44
48
  }
@@ -9,17 +9,25 @@
9
9
  */
10
10
 
11
11
  /**
12
- * element -> (data key -> component instance). WeakMap keys don't prevent
13
- * garbage collection, so instances die with their elements — important under
14
- * Hotwired Turbo, which swaps the whole <body> on navigation.
12
+ * Component registry: element -> (data key -> component instance). A single
13
+ * element can host several components at once, each stored under its own
14
+ * DATA_KEY. WeakMap keys don't prevent garbage collection, so instances die
15
+ * with their elements — important under Hotwired Turbo, which swaps the whole
16
+ * <body> on navigation.
15
17
  */
16
18
  const componentRegistry = new WeakMap<Element, Map<string, BaseComponent>>()
17
19
 
18
20
  class BaseComponent {
21
+ /**
22
+ * Subclasses must override this getter to declare their own name.
23
+ */
19
24
  static get NAME(): string {
20
25
  throw new Error('Component subclasses must override the static NAME getter.')
21
26
  }
22
27
 
28
+ /**
29
+ * Key this component is registered under: `lte.<name>`.
30
+ */
23
31
  static get DATA_KEY(): string {
24
32
  return `lte.${this.NAME}`
25
33
  }
@@ -27,6 +35,9 @@ class BaseComponent {
27
35
  /**
28
36
  * Untyped registry lookup. Every component exposes a typed wrapper
29
37
  * (e.g. CardWidget.getInstance()) built on top of this.
38
+ *
39
+ * @param element The element to look up.
40
+ * @returns The instance for this component, or null if there is none.
30
41
  */
31
42
  protected static _getInstance(element: Element | null | undefined): BaseComponent | null {
32
43
  if (!element) {
@@ -36,8 +47,17 @@ class BaseComponent {
36
47
  return componentRegistry.get(element)?.get(this.DATA_KEY) ?? null
37
48
  }
38
49
 
50
+ /**
51
+ * The element this instance is attached to.
52
+ */
39
53
  _element: HTMLElement
40
54
 
55
+ /**
56
+ * Attach a new instance to the given element and register it under the
57
+ * subclass's DATA_KEY.
58
+ *
59
+ * @param element The element to attach this instance to.
60
+ */
41
61
  constructor(element: HTMLElement) {
42
62
  this._element = element
43
63
 
@@ -55,6 +75,7 @@ class BaseComponent {
55
75
  const instances = componentRegistry.get(this._element)
56
76
  instances?.delete((this.constructor as typeof BaseComponent).DATA_KEY)
57
77
 
78
+ // Drop the element's entry once it holds no components at all.
58
79
  if (instances?.size === 0) {
59
80
  componentRegistry.delete(this._element)
60
81
  }
@@ -65,6 +86,12 @@ class BaseComponent {
65
86
  * Dispatch a namespaced custom event that bubbles — so applications can
66
87
  * listen once on `document` — and can optionally carry a payload or be
67
88
  * canceled. Returns the event so callers can check `defaultPrevented`.
89
+ *
90
+ * @param element The element to dispatch the event on.
91
+ * @param name The namespaced event name, e.g. `collapse.lte.push-menu`.
92
+ * @param options `cancelable` opts the event into preventDefault(); `detail`
93
+ * is the payload handed to listeners.
94
+ * @returns The dispatched event, after listeners have run.
68
95
  */
69
96
  const dispatchCustomEvent = <T = undefined>(
70
97
  element: Element,