admin-lte 4.2.0 → 4.4.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 (63) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +18 -1
  3. package/dist/css/adminlte-colors.css +1261 -0
  4. package/dist/css/adminlte-colors.css.map +1 -0
  5. package/dist/css/adminlte-colors.min.css +15 -0
  6. package/dist/css/adminlte-colors.min.css.map +1 -0
  7. package/dist/css/adminlte-colors.rtl.css +1260 -0
  8. package/dist/css/adminlte-colors.rtl.css.map +1 -0
  9. package/dist/css/adminlte-colors.rtl.min.css +15 -0
  10. package/dist/css/adminlte-colors.rtl.min.css.map +1 -0
  11. package/dist/css/adminlte-docs.css +1 -1
  12. package/dist/css/adminlte-docs.css.map +1 -1
  13. package/dist/css/adminlte-docs.min.css +1 -1
  14. package/dist/css/adminlte-docs.min.css.map +1 -1
  15. package/dist/css/adminlte-docs.rtl.css +1 -1
  16. package/dist/css/adminlte-docs.rtl.css.map +1 -1
  17. package/dist/css/adminlte-docs.rtl.min.css +1 -1
  18. package/dist/css/adminlte-docs.rtl.min.css.map +1 -1
  19. package/dist/css/adminlte-select2.css +329 -0
  20. package/dist/css/adminlte-select2.css.map +1 -0
  21. package/dist/css/adminlte-select2.min.css +12 -0
  22. package/dist/css/adminlte-select2.min.css.map +1 -0
  23. package/dist/css/adminlte-select2.rtl.css +328 -0
  24. package/dist/css/adminlte-select2.rtl.css.map +1 -0
  25. package/dist/css/adminlte-select2.rtl.min.css +12 -0
  26. package/dist/css/adminlte-select2.rtl.min.css.map +1 -0
  27. package/dist/css/adminlte.css +323 -19
  28. package/dist/css/adminlte.css.map +1 -1
  29. package/dist/css/adminlte.min.css +2 -2
  30. package/dist/css/adminlte.min.css.map +1 -1
  31. package/dist/css/adminlte.rtl.css +323 -19
  32. package/dist/css/adminlte.rtl.css.map +1 -1
  33. package/dist/css/adminlte.rtl.min.css +2 -2
  34. package/dist/css/adminlte.rtl.min.css.map +1 -1
  35. package/dist/js/adminlte.esm.js +231 -81
  36. package/dist/js/adminlte.esm.js.map +1 -1
  37. package/dist/js/adminlte.esm.min.js +2 -2
  38. package/dist/js/adminlte.esm.min.js.map +1 -1
  39. package/dist/js/adminlte.js +231 -80
  40. package/dist/js/adminlte.js.map +1 -1
  41. package/dist/js/adminlte.min.js +2 -2
  42. package/dist/js/adminlte.min.js.map +1 -1
  43. package/dist/js/types/adminlte.d.ts +2 -1
  44. package/dist/js/types/sidebar-search.d.ts +46 -0
  45. package/package.json +2 -1
  46. package/src/scss/_app-header.scss +49 -1
  47. package/src/scss/_app-sidebar.scss +22 -2
  48. package/src/scss/_mixins.scss +1 -0
  49. package/src/scss/_ribbon.scss +75 -0
  50. package/src/scss/_variables.scss +36 -0
  51. package/src/scss/_widgets.scss +192 -0
  52. package/src/scss/adminlte-colors.scss +35 -0
  53. package/src/scss/adminlte-docs.scss +1 -1
  54. package/src/scss/adminlte-select2.scss +31 -0
  55. package/src/scss/adminlte.scss +1 -1
  56. package/src/scss/colors/_colors.scss +159 -0
  57. package/src/scss/colors/_variables.scss +85 -0
  58. package/src/scss/compat/_select2.scss +476 -0
  59. package/src/scss/mixins/_search-field.scss +46 -0
  60. package/src/scss/parts/_extra-components.scss +2 -0
  61. package/src/ts/accessibility.ts +25 -13
  62. package/src/ts/adminlte.ts +3 -1
  63. package/src/ts/sidebar-search.ts +252 -0
@@ -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
+ }
@@ -0,0 +1,46 @@
1
+ //
2
+ // Mixin: search field in the chrome
3
+ //
4
+ // One treatment for the navbar search and the sidebar filter. Colours are all
5
+ // theme-relative (`--bs-emphasis-color-rgb`, `--bs-body-color`), so the field
6
+ // is a soft translucent glass on any coloured or dark header / sidebar and a
7
+ // soft grey on a white one — it never fights the `text-bg-*` behind it.
8
+ //
9
+
10
+ @mixin lte-search-field() {
11
+ --#{$lte-prefix}search-field-bg: rgba(var(--#{$prefix}emphasis-color-rgb), .06);
12
+ --#{$lte-prefix}search-field-hover-bg: rgba(var(--#{$prefix}emphasis-color-rgb), .09);
13
+ --#{$lte-prefix}search-field-focus-bg: rgba(var(--#{$prefix}emphasis-color-rgb), .1);
14
+ --#{$lte-prefix}search-field-border-color: rgba(var(--#{$prefix}emphasis-color-rgb), .1);
15
+ --#{$lte-prefix}search-field-focus-border-color: rgba(var(--#{$prefix}emphasis-color-rgb), .35);
16
+ --#{$lte-prefix}search-field-focus-ring: 0 0 0 .2rem rgba(var(--#{$prefix}emphasis-color-rgb), .12);
17
+ --#{$lte-prefix}search-field-color: var(--#{$prefix}body-color);
18
+ --#{$lte-prefix}search-field-placeholder-color: var(--#{$prefix}secondary-color);
19
+ --#{$lte-prefix}search-field-icon-color: var(--#{$prefix}secondary-color);
20
+
21
+ .form-control {
22
+ padding: $lte-search-field-padding-y $lte-search-field-padding-x;
23
+ font-size: $lte-search-field-font-size;
24
+ color: var(--#{$lte-prefix}search-field-color);
25
+ background-color: var(--#{$lte-prefix}search-field-bg);
26
+ border-color: var(--#{$lte-prefix}search-field-border-color);
27
+ box-shadow: none;
28
+ @include border-radius($border-radius-pill);
29
+ @include transition(background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out);
30
+
31
+ &::placeholder {
32
+ color: var(--#{$lte-prefix}search-field-placeholder-color);
33
+ opacity: 1;
34
+ }
35
+
36
+ &:hover {
37
+ background-color: var(--#{$lte-prefix}search-field-hover-bg);
38
+ }
39
+
40
+ &:focus {
41
+ background-color: var(--#{$lte-prefix}search-field-focus-bg);
42
+ border-color: var(--#{$lte-prefix}search-field-focus-border-color);
43
+ box-shadow: var(--#{$lte-prefix}search-field-focus-ring);
44
+ }
45
+ }
46
+ }
@@ -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
 
@@ -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.2.0
13
+ * AdminLTE v4.4.0
13
14
  * Author: Colorlib
14
15
  * Website: AdminLTE.io <https://adminlte.io>
15
16
  * License: Open source - MIT <https://opensource.org/licenses/MIT>
@@ -40,6 +41,7 @@ export {
40
41
  FullScreen,
41
42
  PushMenu,
42
43
  ColorMode,
44
+ SidebarSearch,
43
45
  initAccessibility,
44
46
  initialize,
45
47
  teardown