@keenmate/pure-admin-core 2.3.6 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -29
- package/dist/css/main.css +68 -148
- package/package.json +1 -5
- package/snippets/AUDIT.md +94 -0
- package/snippets/alerts.html +264 -89
- package/snippets/badges.html +193 -61
- package/snippets/buttons.html +178 -0
- package/snippets/callouts.html +210 -129
- package/snippets/cards.html +383 -200
- package/snippets/checkbox-lists.html +199 -65
- package/snippets/code.html +55 -11
- package/snippets/command-palette.html +401 -111
- package/snippets/comparison.html +144 -93
- package/snippets/customization.html +311 -104
- package/snippets/data-display.html +584 -0
- package/snippets/detail-panel.html +470 -138
- package/snippets/filter-card.html +246 -0
- package/snippets/forms.html +408 -308
- package/snippets/grid.html +253 -141
- package/snippets/layout.html +379 -480
- package/snippets/lists.html +144 -47
- package/snippets/loaders.html +64 -39
- package/snippets/manifest.json +330 -280
- package/snippets/modal-dialogs.html +137 -64
- package/snippets/modals.html +221 -151
- package/snippets/notifications.html +285 -0
- package/snippets/popconfirm.html +213 -19
- package/snippets/profile.html +290 -330
- package/snippets/statistics.html +247 -0
- package/snippets/tables.html +359 -150
- package/snippets/tabs.html +129 -45
- package/snippets/timeline.html +123 -56
- package/snippets/toasts.html +179 -31
- package/snippets/tooltips.html +199 -81
- package/snippets/typography.html +183 -58
- package/snippets/utilities.html +511 -415
- package/snippets/virtual-scroll.html +201 -75
- package/snippets/web-daterangepicker.html +369 -189
- package/snippets/web-multiselect.html +360 -124
- package/src/scss/core-components/_alerts.scss +51 -12
- package/src/scss/core-components/_pagers.scss +1 -1
- package/src/scss/core-components/_popconfirm.scss +35 -13
- package/src/scss/core-components/_profile.scss +18 -8
- package/src/scss/core-components/_statistics.scss +12 -12
- package/src/scss/core-components/_tables.scss +2 -134
- package/src/scss/variables/_components.scss +17 -2
- package/scripts/download-themes.js +0 -351
|
@@ -1,9 +1,33 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
<!-- ================================
|
|
2
|
+
WEB MULTISELECT
|
|
3
|
+
A framework-agnostic web component from @keenmate/web-multiselect
|
|
4
|
+
(separate package; not part of pure-admin-core's CSS).
|
|
5
|
+
|
|
6
|
+
Pure Admin's role: themes export ~45 --base-* CSS variables (see
|
|
7
|
+
_base-css-variables.scss + _web-components-theme.scss bridge).
|
|
8
|
+
The component reads them via fallback chains:
|
|
9
|
+
|
|
10
|
+
1. Page override : web-multiselect { --ms-accent-color: … }
|
|
11
|
+
2. Theme base value: var(--base-accent-color)
|
|
12
|
+
3. Hardcoded default: built into the component
|
|
13
|
+
|
|
14
|
+
So in a Pure Admin app you usually do NOT override --ms-* — the
|
|
15
|
+
theme already cascades. Override --ms-* only for one-off
|
|
16
|
+
instance-specific tweaks. Pure Admin also sets two group-label
|
|
17
|
+
overrides directly in _web-components-theme.scss:
|
|
18
|
+
web-multiselect {
|
|
19
|
+
--ms-group-label-color: var(--base-text-color-1);
|
|
20
|
+
--ms-group-label-font-weight: 600;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
Note on the rem base: the component exposes --ms-rem (default 10px)
|
|
24
|
+
which matches Pure Admin's html { font-size: 10px } perfectly —
|
|
25
|
+
all internal sizing scales together with the surrounding UI.
|
|
26
|
+
|
|
5
27
|
Package: npm install @keenmate/web-multiselect
|
|
6
|
-
|
|
28
|
+
Repo: https://github.com/keenmate/web-multiselect
|
|
29
|
+
Auto-registers as <web-multiselect> on import.
|
|
30
|
+
================================ -->
|
|
7
31
|
|
|
8
32
|
<!-- ========================================
|
|
9
33
|
BASIC USAGE
|
|
@@ -28,33 +52,35 @@
|
|
|
28
52
|
DISPLAY MODES
|
|
29
53
|
======================================== -->
|
|
30
54
|
|
|
31
|
-
<!--
|
|
32
|
-
<web-multiselect badges-display-mode="
|
|
55
|
+
<!-- badges (default) - one badge per selected item -->
|
|
56
|
+
<web-multiselect badges-display-mode="badges" placeholder="Select...">
|
|
33
57
|
<option value="1" selected>Option 1</option>
|
|
34
58
|
<option value="2" selected>Option 2</option>
|
|
35
59
|
</web-multiselect>
|
|
36
60
|
|
|
37
|
-
<!--
|
|
61
|
+
<!-- count - "X selected" counter only -->
|
|
38
62
|
<web-multiselect badges-display-mode="count" placeholder="Select...">
|
|
39
63
|
<option value="1" selected>Option 1</option>
|
|
40
64
|
<option value="2" selected>Option 2</option>
|
|
41
65
|
</web-multiselect>
|
|
42
66
|
|
|
43
|
-
<!--
|
|
67
|
+
<!-- compact - first item + "+X more" -->
|
|
44
68
|
<web-multiselect badges-display-mode="compact" placeholder="Select...">
|
|
45
69
|
<option value="1" selected>First</option>
|
|
46
70
|
<option value="2" selected>Second</option>
|
|
47
71
|
<option value="3" selected>Third</option>
|
|
48
72
|
</web-multiselect>
|
|
49
73
|
|
|
50
|
-
<!--
|
|
51
|
-
|
|
74
|
+
<!-- partial - limited visible badges + "+X more"
|
|
75
|
+
Pair with badges-max-visible to control the cap; switch
|
|
76
|
+
thresholding logic with badges-threshold-mode="count" | "partial". -->
|
|
77
|
+
<web-multiselect badges-display-mode="partial" badges-max-visible="2" placeholder="Select...">
|
|
52
78
|
<option value="1" selected>Alpha</option>
|
|
53
79
|
<option value="2" selected>Beta</option>
|
|
54
80
|
<option value="3" selected>Gamma</option>
|
|
55
81
|
</web-multiselect>
|
|
56
82
|
|
|
57
|
-
<!--
|
|
83
|
+
<!-- none - placeholder/input only, no badges UI -->
|
|
58
84
|
<web-multiselect badges-display-mode="none" placeholder="Select...">
|
|
59
85
|
<option value="1" selected>Option A</option>
|
|
60
86
|
<option value="2" selected>Option B</option>
|
|
@@ -64,20 +90,34 @@
|
|
|
64
90
|
SEARCH & FILTER
|
|
65
91
|
======================================== -->
|
|
66
92
|
|
|
67
|
-
<!-- Search
|
|
68
|
-
|
|
93
|
+
<!-- Search filter mode (hides non-matching).
|
|
94
|
+
Note: the attribute is `enable-search`, not `search-enabled`. -->
|
|
95
|
+
<web-multiselect enable-search="true" search-mode="filter" placeholder="Search...">
|
|
69
96
|
<option value="apple">Apple</option>
|
|
70
97
|
<option value="banana">Banana</option>
|
|
71
98
|
<option value="cherry">Cherry</option>
|
|
72
99
|
</web-multiselect>
|
|
73
100
|
|
|
74
|
-
<!--
|
|
75
|
-
<web-multiselect search
|
|
101
|
+
<!-- Navigate mode (jumps focus to first match, keeps all options visible) -->
|
|
102
|
+
<web-multiselect enable-search="true" search-mode="navigate" placeholder="Search...">
|
|
76
103
|
<option value="argentina">Argentina</option>
|
|
77
104
|
<option value="brazil">Brazil</option>
|
|
78
105
|
<option value="canada">Canada</option>
|
|
79
106
|
</web-multiselect>
|
|
80
107
|
|
|
108
|
+
<!-- Tweak the search input itself with `search-input-mode` and
|
|
109
|
+
gate it behind a minimum search length: -->
|
|
110
|
+
<web-multiselect enable-search="true"
|
|
111
|
+
search-mode="filter"
|
|
112
|
+
search-input-mode="normal"
|
|
113
|
+
min-search-length="2"
|
|
114
|
+
search-placeholder="Type 2+ chars…"
|
|
115
|
+
placeholder="Search countries…">
|
|
116
|
+
<option value="ar">Argentina</option>
|
|
117
|
+
<option value="br">Brazil</option>
|
|
118
|
+
<option value="ca">Canada</option>
|
|
119
|
+
</web-multiselect>
|
|
120
|
+
|
|
81
121
|
<!-- ========================================
|
|
82
122
|
GROUPED OPTIONS
|
|
83
123
|
======================================== -->
|
|
@@ -109,7 +149,16 @@
|
|
|
109
149
|
VIRTUAL SCROLLING (Large Datasets)
|
|
110
150
|
======================================== -->
|
|
111
151
|
|
|
112
|
-
|
|
152
|
+
<!-- Virtual scrolling auto-enables once the option count crosses
|
|
153
|
+
`virtual-scroll-threshold` (default ≈ a few hundred). To force
|
|
154
|
+
it on/off, set `enable-virtual-scroll="true" | "false"`.
|
|
155
|
+
`option-height` should match your actual rendered row height. -->
|
|
156
|
+
<web-multiselect id="large-dataset"
|
|
157
|
+
enable-search="true"
|
|
158
|
+
enable-virtual-scroll="true"
|
|
159
|
+
option-height="50"
|
|
160
|
+
virtual-scroll-buffer="10"
|
|
161
|
+
placeholder="Search 10,000 items...">
|
|
113
162
|
<!-- Options added via JavaScript for large datasets -->
|
|
114
163
|
</web-multiselect>
|
|
115
164
|
|
|
@@ -228,135 +277,322 @@ document.getElementById('myForm').addEventListener('submit', (e) => {
|
|
|
228
277
|
======================================== -->
|
|
229
278
|
|
|
230
279
|
<!--
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
-
|
|
236
|
-
-
|
|
237
|
-
-
|
|
280
|
+
Source of truth: web-component.ts observedAttributes list. The full
|
|
281
|
+
set of attributes the web component accepts:
|
|
282
|
+
|
|
283
|
+
Core:
|
|
284
|
+
- placeholder Input placeholder
|
|
285
|
+
- multiple "true" (default) | "false" for single-select
|
|
286
|
+
- dir "ltr" (default) | "rtl"
|
|
287
|
+
- disabled Disable the entire component
|
|
288
|
+
- allow-groups "true" | "false" — render <optgroup> headers
|
|
289
|
+
- close-on-select Close dropdown on each pick
|
|
290
|
+
- lock-placement Pin dropdown placement (skip flip)
|
|
291
|
+
- dropdown-min-width CSS width
|
|
292
|
+
- dropdown-max-width CSS width
|
|
293
|
+
- max-height Dropdown max height
|
|
294
|
+
- empty-message Text when no options match
|
|
295
|
+
- loading-message Text shown during async load
|
|
296
|
+
- sticky-actions Pin the action bar at the bottom
|
|
297
|
+
- actions-layout Layout token for the action bar
|
|
298
|
+
- allow-add-new Let the user create options inline
|
|
299
|
+
- initial-values CSV / JSON initial selection
|
|
300
|
+
- show-debug-info Boolean — opt-in console logging
|
|
301
|
+
|
|
302
|
+
Badges (selection display):
|
|
303
|
+
- badges-display-mode "badges" (default) | "count" | "compact"
|
|
304
|
+
| "partial" | "none"
|
|
305
|
+
- badges-position "bottom" (default) | "top" | "left" | "right"
|
|
306
|
+
- badges-threshold Numeric trigger for threshold-mode collapse
|
|
307
|
+
- badges-threshold-mode "count" | "partial"
|
|
308
|
+
- badges-max-visible Cap on visible badges in partial mode
|
|
309
|
+
- show-counter Show "(N)" counter alongside badges
|
|
310
|
+
- enable-badge-tooltips Tooltip on each badge
|
|
311
|
+
- badge-tooltip-placement Floating UI placement for badge tooltip
|
|
312
|
+
- remove-button-tooltip-text Tooltip text on the × button
|
|
238
313
|
|
|
239
314
|
Search:
|
|
240
|
-
- search
|
|
241
|
-
|
|
242
|
-
- search-
|
|
243
|
-
-
|
|
315
|
+
- enable-search "true" | "false" (default false)
|
|
316
|
+
(NOT `search-enabled` — common mistake)
|
|
317
|
+
- search-mode "filter" (default) | "navigate"
|
|
318
|
+
- search-input-mode "normal" | "readonly" | "hidden"
|
|
319
|
+
- search-placeholder Placeholder for the search input
|
|
320
|
+
- search-hint Helper text under the search input
|
|
321
|
+
- min-search-length Don't trigger filter until N characters typed
|
|
322
|
+
- keep-options-on-search Keep already-selected items at the top
|
|
323
|
+
- should-keep-search-on-close Preserve search query across opens
|
|
244
324
|
|
|
245
325
|
Display:
|
|
246
|
-
- show-checkboxes
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
- virtual-scroll-
|
|
252
|
-
- option-height
|
|
326
|
+
- show-checkboxes Show checkboxes inside option rows
|
|
327
|
+
|
|
328
|
+
Virtual Scrolling (auto-enabled past virtual-scroll-threshold):
|
|
329
|
+
- enable-virtual-scroll "true" | "false"
|
|
330
|
+
(NOT `virtual-scroll-enabled` — common mistake)
|
|
331
|
+
- virtual-scroll-threshold Item count that flips virtual scrolling on
|
|
332
|
+
- option-height Height of each option row in px (must match
|
|
333
|
+
your render — defaults to 50)
|
|
334
|
+
- badge-height Height of each badge row when virtual
|
|
335
|
+
- virtual-scroll-buffer Items rendered above/below viewport
|
|
336
|
+
|
|
337
|
+
Member Property Names (for plugging in foreign data shapes):
|
|
338
|
+
- value-member Default: 'value'
|
|
339
|
+
- display-value-member Default: 'label'
|
|
340
|
+
- search-value-member Default: same as display-value-member
|
|
341
|
+
- icon-member Default: 'icon'
|
|
342
|
+
- subtitle-member Default: 'subtitle'
|
|
343
|
+
- group-member Default: 'group'
|
|
344
|
+
- disabled-member Default: 'disabled'
|
|
345
|
+
|
|
346
|
+
Form Integration:
|
|
347
|
+
- name Field name; participates in <form> submission
|
|
348
|
+
- value-format "json" (default) | "csv" | "array"
|
|
253
349
|
-->
|
|
254
350
|
|
|
255
351
|
<!-- ========================================
|
|
256
|
-
CSS
|
|
352
|
+
CSS CUSTOM PROPERTIES (--ms-*)
|
|
353
|
+
The component defines its variables on :host inside its shadow DOM,
|
|
354
|
+
so override them by targeting the element (NOT :root — :root inside
|
|
355
|
+
shadow DOM doesn't reach the component).
|
|
356
|
+
|
|
357
|
+
The actual prefix is --ms- (multiselect), not --ml-.
|
|
257
358
|
======================================== -->
|
|
258
359
|
|
|
259
360
|
<style>
|
|
260
|
-
/* Override
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
--
|
|
266
|
-
--
|
|
267
|
-
--
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
--
|
|
271
|
-
--ml-input-border: #ced4da;
|
|
272
|
-
--ml-input-padding-v: 0.5rem;
|
|
273
|
-
--ml-input-padding-h: 0.75rem;
|
|
274
|
-
--ml-input-font-size: 0.875rem;
|
|
275
|
-
--ml-input-border-radius: 4px;
|
|
276
|
-
--ml-input-focus-border: #007bff;
|
|
277
|
-
|
|
278
|
-
/* Dropdown */
|
|
279
|
-
--ml-dropdown-bg: #ffffff;
|
|
280
|
-
--ml-dropdown-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
281
|
-
--ml-dropdown-max-height: 300px;
|
|
282
|
-
|
|
283
|
-
/* Options */
|
|
284
|
-
--ml-option-padding-v: 0.5rem;
|
|
285
|
-
--ml-option-padding-h: 0.75rem;
|
|
286
|
-
--ml-option-hover-bg: #f8f9fa;
|
|
287
|
-
--ml-option-selected-bg: rgba(0, 123, 255, 0.05);
|
|
288
|
-
--ml-option-selected-color: #007bff;
|
|
289
|
-
|
|
290
|
-
/* Badges */
|
|
291
|
-
--ml-badge-bg: #007bff;
|
|
292
|
-
--ml-badge-text: #ffffff;
|
|
293
|
-
--ml-badge-padding-v: 0.125rem;
|
|
294
|
-
--ml-badge-padding-h: 0.5rem;
|
|
295
|
-
--ml-badge-font-size: 0.75rem;
|
|
296
|
-
--ml-badge-border-radius: 2px;
|
|
297
|
-
--ml-badge-gap: 0.5rem;
|
|
298
|
-
|
|
299
|
-
/* Animations */
|
|
300
|
-
--ml-transition-duration: 0.15s;
|
|
301
|
-
--ml-timing-function: ease;
|
|
361
|
+
/* Override on the element so the variables cascade into the shadow root.
|
|
362
|
+
In a Pure Admin app this is rarely needed — the theme already cascades
|
|
363
|
+
via --base-* and the component falls back from --ms-* → var(--base-*,
|
|
364
|
+
hardcoded). Override only for one-off instance tweaks. */
|
|
365
|
+
web-multiselect {
|
|
366
|
+
--ms-accent-color: var(--pa-accent);
|
|
367
|
+
--ms-input-bg: var(--pa-input-bg);
|
|
368
|
+
--ms-text-color-1: var(--pa-text-color-1);
|
|
369
|
+
--ms-text-color-3: var(--pa-text-color-2);
|
|
370
|
+
--ms-border-color: var(--pa-border-color);
|
|
371
|
+
--ms-input-border-radius: var(--pa-border-radius);
|
|
302
372
|
}
|
|
303
|
-
</style>
|
|
304
373
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
374
|
+
/* Scoped instance override (e.g. a "compact" variant) */
|
|
375
|
+
web-multiselect.compact {
|
|
376
|
+
--ms-rem: 9px; /* shrinks every internal sizing unit */
|
|
377
|
+
--ms-accent-color: #10b981;
|
|
378
|
+
}
|
|
379
|
+
</style>
|
|
308
380
|
|
|
309
381
|
<!--
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
382
|
+
Variable groups (full list in src/css/_variables.css — 349 declarations):
|
|
383
|
+
|
|
384
|
+
Base sizing
|
|
385
|
+
--ms-rem Base sizing unit. Defaults 10px to match
|
|
386
|
+
Pure Admin's html { font-size: 10px }. All
|
|
387
|
+
internal sizes scale from this value.
|
|
388
|
+
|
|
389
|
+
Colors / theme
|
|
390
|
+
--ms-accent-color, --ms-accent-color-hover, --ms-accent-color-active
|
|
391
|
+
--ms-accent-color-light, --ms-accent-color-light-hover
|
|
392
|
+
--ms-text-color-1..-4, --ms-text-color-on-accent
|
|
393
|
+
--ms-text-primary, --ms-text-secondary (legacy aliases)
|
|
394
|
+
--ms-primary-bg, --ms-primary-bg-hover
|
|
395
|
+
--ms-border-color, --ms-border
|
|
396
|
+
|
|
397
|
+
Input
|
|
398
|
+
--ms-input-bg, --ms-input-color, --ms-input-border,
|
|
399
|
+
--ms-input-border-hover, --ms-input-border-focus,
|
|
400
|
+
--ms-input-placeholder-color, --ms-input-bg-disabled
|
|
401
|
+
|
|
402
|
+
Toggle / chevron
|
|
403
|
+
--ms-toggle-icon-color, --ms-toggle-icon-color-open
|
|
404
|
+
|
|
405
|
+
Dropdown
|
|
406
|
+
--ms-dropdown-bg, --ms-dropdown-shadow, --ms-dropdown-border,
|
|
407
|
+
--ms-dropdown-border-radius, --ms-dropdown-max-height
|
|
408
|
+
|
|
409
|
+
Options
|
|
410
|
+
--ms-option-bg, --ms-option-bg-hover, --ms-option-bg-selected,
|
|
411
|
+
--ms-option-text-color, --ms-option-text-color-hover, …
|
|
412
|
+
|
|
413
|
+
Badges
|
|
414
|
+
--ms-badge-bg, --ms-badge-text, --ms-badge-padding-v / -h,
|
|
415
|
+
--ms-badge-font-size, --ms-badge-border-radius, --ms-badge-gap
|
|
416
|
+
|
|
417
|
+
Group labels (set by Pure Admin's _web-components-theme.scss)
|
|
418
|
+
--ms-group-label-color, --ms-group-label-font-weight
|
|
419
|
+
|
|
420
|
+
Animations
|
|
421
|
+
--ms-transition-duration, --ms-timing-function
|
|
422
|
+
|
|
423
|
+
PURE ADMIN INTEGRATION:
|
|
424
|
+
packages/core/src/scss/core-components/_web-components-theme.scss
|
|
425
|
+
bridges --base-* → --ms-* automatically. So themes "just work" — no
|
|
426
|
+
manual --ms-* overrides needed in normal Pure Admin usage. The
|
|
427
|
+
bridge file also sets two group-label-specific overrides directly.
|
|
331
428
|
-->
|
|
332
429
|
|
|
333
430
|
<!-- ========================================
|
|
334
|
-
|
|
431
|
+
TYPESCRIPT TYPES
|
|
335
432
|
======================================== -->
|
|
336
433
|
|
|
337
434
|
<!--
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
435
|
+
import '@keenmate/web-multiselect';
|
|
436
|
+
import type {
|
|
437
|
+
MultiSelectOption, // single option shape
|
|
438
|
+
MultiSelectOptions, // array of options
|
|
439
|
+
MultiSelectEventDetail, // shape of `change` event detail
|
|
440
|
+
BadgesDisplayMode, // 'badges' | 'count' | 'compact' | 'partial' | 'none'
|
|
441
|
+
BadgesPosition, // 'top' | 'bottom' | 'left' | 'right'
|
|
442
|
+
BadgesThresholdMode, // 'count' | 'partial'
|
|
443
|
+
SearchInputMode, // 'normal' | 'readonly' | 'hidden'
|
|
444
|
+
SearchMode, // 'filter' | 'navigate'
|
|
445
|
+
ValueFormat // 'json' | 'csv' | 'array'
|
|
446
|
+
} from '@keenmate/web-multiselect';
|
|
447
|
+
|
|
448
|
+
const select = document.querySelector('web-multiselect');
|
|
449
|
+
|
|
450
|
+
select.options = [
|
|
451
|
+
{ value: 'js', label: 'JavaScript' },
|
|
452
|
+
{ value: 'ts', label: 'TypeScript' }
|
|
453
|
+
];
|
|
454
|
+
|
|
455
|
+
select.addEventListener('change', (e) => {
|
|
456
|
+
// e.detail: MultiSelectEventDetail
|
|
457
|
+
console.log(e.detail.selectedValues);
|
|
458
|
+
});
|
|
351
459
|
-->
|
|
352
460
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
461
|
+
|
|
462
|
+
<!-- ================================
|
|
463
|
+
COMPONENT REFERENCE
|
|
464
|
+
================================ -->
|
|
356
465
|
|
|
357
466
|
<!--
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
467
|
+
DECLARATIVE vs PROGRAMMATIC OPTIONS:
|
|
468
|
+
|
|
469
|
+
Declarative — drop <option> / <optgroup> children, no JS needed:
|
|
470
|
+
<web-multiselect placeholder="Pick…">
|
|
471
|
+
<optgroup label="Frontend">
|
|
472
|
+
<option value="react" selected>React</option>
|
|
473
|
+
<option value="vue">Vue</option>
|
|
474
|
+
</optgroup>
|
|
475
|
+
</web-multiselect>
|
|
476
|
+
|
|
477
|
+
Programmatic — set the .options array (re-initializes the picker):
|
|
478
|
+
el.options = [
|
|
479
|
+
{ value: 'react', label: 'React', icon: '⚛️' },
|
|
480
|
+
{ value: 'vue', label: 'Vue', icon: '💚' }
|
|
481
|
+
];
|
|
482
|
+
|
|
483
|
+
Foreign data shapes — re-map property names instead of transforming
|
|
484
|
+
the data:
|
|
485
|
+
el.valueMember = 'id';
|
|
486
|
+
el.displayValueMember = 'name';
|
|
487
|
+
el.iconMember = 'emoji';
|
|
488
|
+
el.options = [{ id: '1', name: 'React', emoji: '⚛️' }];
|
|
489
|
+
|
|
490
|
+
DISPLAY MODES (badges-display-mode):
|
|
491
|
+
badges (default) one badge per selected item
|
|
492
|
+
count "X selected" counter only
|
|
493
|
+
compact first item + "+X more"
|
|
494
|
+
partial visible badges capped by `badges-max-visible`,
|
|
495
|
+
threshold flip via `badges-threshold-mode`
|
|
496
|
+
none no badges UI; placeholder only
|
|
497
|
+
|
|
498
|
+
SEARCH (enable-search="true"):
|
|
499
|
+
search-mode="filter" hides non-matching options
|
|
500
|
+
search-mode="navigate" keeps all visible, jumps focus to match
|
|
501
|
+
search-input-mode normal | readonly | hidden
|
|
502
|
+
min-search-length delay filter until N characters typed
|
|
503
|
+
|
|
504
|
+
VIRTUAL SCROLL:
|
|
505
|
+
Auto-enabled past `virtual-scroll-threshold`. Force with
|
|
506
|
+
`enable-virtual-scroll="true" | "false"`. Tune with
|
|
507
|
+
`option-height` (must match real row height, default 50) and
|
|
508
|
+
`virtual-scroll-buffer`. Handles 10–15k options comfortably.
|
|
509
|
+
|
|
510
|
+
EVENTS:
|
|
511
|
+
change detail: { selectedValues, selectedOptions }
|
|
512
|
+
Bubbles + composed; works through shadow DOM boundaries.
|
|
513
|
+
|
|
514
|
+
PUBLIC METHODS:
|
|
515
|
+
el.setSelected(values: (string|number)[])
|
|
516
|
+
el.getValue() → values array
|
|
517
|
+
el.getSelected() → MultiSelectOption[]
|
|
518
|
+
el.options read/write the options array
|
|
519
|
+
el.{value,displayValue,…}Member re-map foreign-data property names
|
|
520
|
+
el.picker underlying engine for advanced calls
|
|
521
|
+
|
|
522
|
+
FORM INTEGRATION:
|
|
523
|
+
Add `name` to participate in <form> submission. `value-format`
|
|
524
|
+
controls the encoding the form receives:
|
|
525
|
+
json (default) — JSON.stringify(values)
|
|
526
|
+
csv — comma-separated string
|
|
527
|
+
array — multiple form fields with the same name
|
|
528
|
+
(FormData.getAll(name))
|
|
529
|
+
|
|
530
|
+
KEYBOARD:
|
|
531
|
+
↓ / ↑ navigate options
|
|
532
|
+
Enter / Space toggle selection
|
|
533
|
+
Esc close dropdown / clear search
|
|
534
|
+
Backspace with empty search, removes last badge
|
|
535
|
+
Tab focus the action bar / next field
|
|
536
|
+
Type incremental search (when enable-search)
|
|
537
|
+
|
|
538
|
+
CSS VARIABLE NAMESPACES:
|
|
539
|
+
--ms-* Component runtime tokens. Set on the element (NOT
|
|
540
|
+
:root — :root inside shadow DOM doesn't reach the
|
|
541
|
+
component). Prefix is "ms" (multiselect), not "ml".
|
|
542
|
+
--base-* Pure Admin theme bridge. Themes export these via
|
|
543
|
+
output-base-css-variables; the component falls back
|
|
544
|
+
from --ms-* → var(--base-*, hardcoded).
|
|
545
|
+
|
|
546
|
+
LOAD ORDER:
|
|
547
|
+
Import the component once (auto-registers the custom element):
|
|
548
|
+
import '@keenmate/web-multiselect';
|
|
549
|
+
import '@keenmate/web-multiselect/style.css';
|
|
550
|
+
Pure Admin's CSS provides the --base-* values; the component picks
|
|
551
|
+
them up automatically.
|
|
552
|
+
|
|
553
|
+
STRUCTURE PATTERNS:
|
|
554
|
+
|
|
555
|
+
Tag-style multi-select with checkboxes:
|
|
556
|
+
<web-multiselect multiple="true"
|
|
557
|
+
enable-search="true"
|
|
558
|
+
show-checkboxes="true"
|
|
559
|
+
badges-display-mode="badges">
|
|
560
|
+
…
|
|
561
|
+
</web-multiselect>
|
|
562
|
+
|
|
563
|
+
Big dataset with virtual scrolling + filter search:
|
|
564
|
+
<web-multiselect enable-search="true"
|
|
565
|
+
enable-virtual-scroll="true"
|
|
566
|
+
option-height="44"
|
|
567
|
+
virtual-scroll-buffer="10"
|
|
568
|
+
max-height="40rem">
|
|
569
|
+
…
|
|
570
|
+
</web-multiselect>
|
|
571
|
+
|
|
572
|
+
Compact selection counter (saves vertical space in toolbars):
|
|
573
|
+
<web-multiselect badges-display-mode="count"
|
|
574
|
+
show-counter="true">
|
|
575
|
+
…
|
|
576
|
+
</web-multiselect>
|
|
577
|
+
|
|
578
|
+
RTL with logical badge position. NOTE: BadgesPosition is physical
|
|
579
|
+
('top' | 'bottom' | 'left' | 'right') — pair `dir="rtl"` with the
|
|
580
|
+
appropriate physical side:
|
|
581
|
+
<web-multiselect dir="rtl" badges-position="right">…</web-multiselect>
|
|
582
|
+
|
|
583
|
+
Form-integrated CSV submission:
|
|
584
|
+
<form>
|
|
585
|
+
<web-multiselect name="tags" value-format="csv">
|
|
586
|
+
…
|
|
587
|
+
</web-multiselect>
|
|
588
|
+
</form>
|
|
589
|
+
|
|
590
|
+
RESOURCES:
|
|
591
|
+
npm @keenmate/web-multiselect
|
|
592
|
+
Repository https://github.com/keenmate/web-multiselect
|
|
593
|
+
AI guides ../../web-multiselect/ai/ (per-topic .txt files)
|
|
594
|
+
API docs ../../web-multiselect/docs/api-reference.html
|
|
595
|
+
Theming ../../web-multiselect/THEMING.md
|
|
596
|
+
Pure Admin src/scss/core-components/_web-components-theme.scss
|
|
597
|
+
bridges --base-* into the component's fallback chain.
|
|
362
598
|
-->
|