@keenmate/web-multiselect 2.1.0 → 2.2.0-rc01
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 +11 -8
- package/custom-elements.json +306 -26
- package/dist/index.d.ts +169 -14
- package/dist/multiselect.js +1392 -1207
- package/dist/multiselect.umd.js +12 -12
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/css/controls.css +6 -3
- package/src/css/options.css +47 -0
- package/src/css/variables.css +2 -0
- package/vscode.html-custom-data.json +22 -1
- package/web-types.json +58 -10
package/dist/index.d.ts
CHANGED
|
@@ -72,7 +72,7 @@ declare type ActionsPosition = 'top' | 'bottom';
|
|
|
72
72
|
/**
|
|
73
73
|
* Context provided to renderBadgeContentCallback
|
|
74
74
|
*/
|
|
75
|
-
declare interface BadgeContentRenderContext extends PresentationContext {
|
|
75
|
+
export declare interface BadgeContentRenderContext extends PresentationContext {
|
|
76
76
|
/** Current badges display mode */
|
|
77
77
|
displayMode: BadgesDisplayMode;
|
|
78
78
|
/** Whether the badge is being rendered in the selected items popover */
|
|
@@ -114,6 +114,35 @@ export { EnvironmentSnapshot }
|
|
|
114
114
|
|
|
115
115
|
export { getEnvironment }
|
|
116
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Context handed to `renderGroupLabelContentCallback` as its second argument, so a custom group
|
|
119
|
+
* header can reflect the selection — e.g. render a "3 / 8" count next to the title. The fields are
|
|
120
|
+
* populated for every group header; the selection fields are meaningful mainly under
|
|
121
|
+
* `groupSelectMode: 'cascade'` (a flat multi-select grouped list). Under the default rendering
|
|
122
|
+
* (no callback) the component draws the count itself; with a callback, YOU own the content and can
|
|
123
|
+
* render the count however you like from these fields.
|
|
124
|
+
*
|
|
125
|
+
* Like {@link OptionContentRenderContext} / {@link BadgeContentRenderContext}, it extends the
|
|
126
|
+
* shared {@link PresentationContext} (`presentation` / `isFullscreen` / `isModal`), so a group
|
|
127
|
+
* header can also render leaner in the phone fullscreen overlay.
|
|
128
|
+
*/
|
|
129
|
+
export declare interface GroupLabelRenderContext<T = any> extends PresentationContext {
|
|
130
|
+
/** The group name (identical to the callback's first argument). */
|
|
131
|
+
groupName: string;
|
|
132
|
+
/** The group's currently-visible (filtered) members, in render order. */
|
|
133
|
+
members: T[];
|
|
134
|
+
/** The subset of `members` that are currently selected (includes disabled-but-selected). */
|
|
135
|
+
selectedMembers: T[];
|
|
136
|
+
/** `selectedMembers.length` — the number to show "behind the group title". */
|
|
137
|
+
selectedCount: number;
|
|
138
|
+
/** `members.length` — total visible members in the group. */
|
|
139
|
+
memberCount: number;
|
|
140
|
+
/** Visible, non-disabled members — the cascade "select-all" denominator. */
|
|
141
|
+
selectableCount: number;
|
|
142
|
+
/** Tristate roll-up of the group under cascade selection. */
|
|
143
|
+
checkState: 'checked' | 'indeterminate' | 'unchecked';
|
|
144
|
+
}
|
|
145
|
+
|
|
117
146
|
export declare const initLogger: Logger;
|
|
118
147
|
|
|
119
148
|
export declare const interactionLogger: Logger;
|
|
@@ -191,6 +220,25 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
191
220
|
getDisplayValueCallback?: (item: T) => string;
|
|
192
221
|
/** Callback to customize badge display text (defaults to display value if not provided) */
|
|
193
222
|
getBadgeDisplayCallback?: (item: T) => string;
|
|
223
|
+
/**
|
|
224
|
+
* Order of the CURRENTLY-SELECTED items *where they are displayed* — badges, partial mode
|
|
225
|
+
* (i.e. which items sit behind the "+N more" badge), and the selected-items popover. This is a
|
|
226
|
+
* display concern only: `getValue()`, the form output, and `getSelected()` always keep
|
|
227
|
+
* as-selected (insertion) order regardless of this setting, and the options dropdown is never
|
|
228
|
+
* reordered.
|
|
229
|
+
* - `as-selected` (default) — the order items were picked.
|
|
230
|
+
* - `label-asc` / `label-desc` — by the badge label, A→Z / Z→A (locale-aware).
|
|
231
|
+
* - `member` — by the `selectedOrderMember` property (or `getSelectedOrderCallback`); numeric
|
|
232
|
+
* keys sort numerically, everything else with a locale string compare.
|
|
233
|
+
* - `custom` — delegate to `selectedOrderCompareCallback`.
|
|
234
|
+
*/
|
|
235
|
+
selectedOrder?: 'as-selected' | 'label-asc' | 'label-desc' | 'member' | 'custom';
|
|
236
|
+
/** Property name used as the sort key when `selectedOrder === 'member'` (selected-items display only). */
|
|
237
|
+
selectedOrderMember?: string;
|
|
238
|
+
/** Extract the sort key when `selectedOrder === 'member'` (overrides `selectedOrderMember`). */
|
|
239
|
+
getSelectedOrderCallback?: (item: T) => string | number;
|
|
240
|
+
/** Comparator used when `selectedOrder === 'custom'`; standard `(a,b) => number` contract. */
|
|
241
|
+
selectedOrderCompareCallback?: (a: T, b: T) => number;
|
|
194
242
|
/**
|
|
195
243
|
* Member property name for a "full title" — a fully-qualified label that ships with the
|
|
196
244
|
* data (e.g. a breadcrumb like "Fruit / Pome fruit / Apple"). It is never computed by the
|
|
@@ -250,9 +298,10 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
250
298
|
*/
|
|
251
299
|
getIsSelectableCallback?: (node: LTreeNode<T>) => boolean;
|
|
252
300
|
/**
|
|
253
|
-
* Tree checkbox interaction. `
|
|
254
|
-
*
|
|
255
|
-
*
|
|
301
|
+
* Tree checkbox interaction. `cascade` (default) checks a node's whole subtree
|
|
302
|
+
* and shows a tristate (checked / indeterminate / unchecked) box on branches —
|
|
303
|
+
* what most tree-select UIs do. `independent` toggles only the clicked node.
|
|
304
|
+
* Tree + multiple only (no subtree to cascade otherwise). Unset → cascade.
|
|
256
305
|
*/
|
|
257
306
|
checkboxMode?: 'independent' | 'cascade';
|
|
258
307
|
/**
|
|
@@ -270,8 +319,23 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
270
319
|
groupMember?: string;
|
|
271
320
|
/** Callback to extract group from item */
|
|
272
321
|
getGroupCallback?: (item: T) => string;
|
|
273
|
-
/**
|
|
274
|
-
|
|
322
|
+
/**
|
|
323
|
+
* Callback to customize group label content (can return HTML). Receives the group name and a
|
|
324
|
+
* {@link GroupLabelRenderContext} with the group's members and selection (e.g. `selectedCount`),
|
|
325
|
+
* so a custom header can show a per-group count. The second argument is additive — existing
|
|
326
|
+
* one-argument callbacks keep working.
|
|
327
|
+
*/
|
|
328
|
+
renderGroupLabelContentCallback?: (groupName: string, context: GroupLabelRenderContext<T>) => string | HTMLElement;
|
|
329
|
+
/**
|
|
330
|
+
* Group-header selection in a flat (non-tree) grouped, multi-select list.
|
|
331
|
+
* - `none` (default) — group headers are inert labels.
|
|
332
|
+
* - `cascade` — each header shows a **tristate** checkbox that checks/unchecks
|
|
333
|
+
* all of that group's currently-visible members. The group itself is never a
|
|
334
|
+
* selected value (`getValue()`/badges/form carry member values only); a
|
|
335
|
+
* partially-selected group reads indeterminate. Flat + multiple only — no
|
|
336
|
+
* effect in tree mode (use `checkboxMode`) or single-select.
|
|
337
|
+
*/
|
|
338
|
+
groupSelectMode?: 'none' | 'cascade';
|
|
275
339
|
/** Member property name for disabled state extraction */
|
|
276
340
|
disabledMember?: string;
|
|
277
341
|
/** Callback to extract disabled state from item */
|
|
@@ -291,12 +355,22 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
291
355
|
* selected-items popover keeps using renderSelectedItemContentCallback).
|
|
292
356
|
*/
|
|
293
357
|
renderBadgeCallback?: (item: T, context: BadgeContentRenderContext) => string | HTMLElement | null | undefined;
|
|
294
|
-
/**
|
|
295
|
-
|
|
358
|
+
/**
|
|
359
|
+
* Custom renderer for selected item content in the selected-items popover — return HTML string
|
|
360
|
+
* or HTMLElement. Receives a {@link BadgeContentRenderContext} (2nd arg) since a popover item
|
|
361
|
+
* is rendered through the same badge path: `isInPopover` is `true`, plus the shared
|
|
362
|
+
* presentation fields. The second argument is additive; one-argument callbacks keep working.
|
|
363
|
+
*/
|
|
364
|
+
renderSelectedItemContentCallback?: (item: T, context: BadgeContentRenderContext) => string | HTMLElement;
|
|
296
365
|
/** Callback to add custom CSS classes to selected items in popover - return string or array of class names */
|
|
297
366
|
getSelectedItemClassCallback?: (item: T) => string | string[];
|
|
298
|
-
/**
|
|
299
|
-
|
|
367
|
+
/**
|
|
368
|
+
* Custom renderer for the selected item display in single-select mode — return plain text (it
|
|
369
|
+
* becomes the input value). Receives a {@link SelectedContentRenderContext} (2nd arg) carrying
|
|
370
|
+
* the shared presentation fields. The second argument is additive; one-argument callbacks keep
|
|
371
|
+
* working.
|
|
372
|
+
*/
|
|
373
|
+
renderSelectedContentCallback?: (item: T, context: SelectedContentRenderContext) => string;
|
|
300
374
|
/** HTML form field ID/name for hidden input */
|
|
301
375
|
formFieldId?: string;
|
|
302
376
|
/**
|
|
@@ -595,8 +669,22 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
595
669
|
onDeselect?: ((option: T) => void) | null;
|
|
596
670
|
/** Event handler: the selection set changed (fire-and-forget). Mirrors the bubbling `change` CustomEvent on the element. */
|
|
597
671
|
onChange?: ((selectedOptions: T[]) => void) | null;
|
|
598
|
-
/**
|
|
672
|
+
/**
|
|
673
|
+
* Formats the badges-area count/summary text: the `count` mode badge ("N selected") and the
|
|
674
|
+
* partial-mode "+X more" badge (when `moreCount` is provided). NOT the small `[N]` chip — that's
|
|
675
|
+
* {@link getCountLabelCallback}. For i18n/pluralization.
|
|
676
|
+
*/
|
|
599
677
|
getCounterCallback?: ((count: number, moreCount?: number) => string) | null;
|
|
678
|
+
/**
|
|
679
|
+
* Formats the small count CHIP shared by the in-input counter (`show-counter`) and each group
|
|
680
|
+
* header's per-group count. Distinct from {@link getCounterCallback}, which formats the
|
|
681
|
+
* badges-area "N selected" / "+X more" text. Receives `selected` and `total`: for the in-input
|
|
682
|
+
* counter `total` is the whole option list; for a group header it's that group's member count.
|
|
683
|
+
* Return the label as plain text. Default `[selected]` (e.g. `[3]`). Set it to
|
|
684
|
+
* `` (s, t) => `${s}/${t}` `` for an "x / y" style. One callback drives both so they always
|
|
685
|
+
* read the same way.
|
|
686
|
+
*/
|
|
687
|
+
getCountLabelCallback?: ((selected: number, total: number) => string) | null;
|
|
600
688
|
/** Enable tooltips on selected item badges (internal: isBadgeTooltipsEnabled) */
|
|
601
689
|
isBadgeTooltipsEnabled?: boolean;
|
|
602
690
|
/** Callback to generate custom tooltip content for a badge */
|
|
@@ -928,7 +1016,7 @@ export { observeViewport }
|
|
|
928
1016
|
* render leaner content in the phone overlay. Reactive: swapping presentation re-renders and
|
|
929
1017
|
* re-invokes the callback with the new value.
|
|
930
1018
|
*/
|
|
931
|
-
declare interface OptionContentRenderContext extends PresentationContext {
|
|
1019
|
+
export declare interface OptionContentRenderContext extends PresentationContext {
|
|
932
1020
|
/** Index of the option in the filtered list */
|
|
933
1021
|
index: number;
|
|
934
1022
|
/** Whether the option is currently selected */
|
|
@@ -1014,6 +1102,13 @@ export declare type SearchInputMode = 'normal' | 'readonly' | 'hidden';
|
|
|
1014
1102
|
*/
|
|
1015
1103
|
export declare type SearchMode = 'filter' | 'navigate';
|
|
1016
1104
|
|
|
1105
|
+
/**
|
|
1106
|
+
* Context handed to `renderSelectedContentCallback` (single-select selected-value display). Carries
|
|
1107
|
+
* only the shared {@link PresentationContext} fields (`presentation` / `isFullscreen` / `isModal`),
|
|
1108
|
+
* so the single-select label can render leaner in the phone fullscreen overlay.
|
|
1109
|
+
*/
|
|
1110
|
+
export declare type SelectedContentRenderContext = PresentationContext;
|
|
1111
|
+
|
|
1017
1112
|
/**
|
|
1018
1113
|
* Set the level of one category. Accepts the full prefixed name
|
|
1019
1114
|
* (`MULTISELECT:UI`) or the bare suffix (`UI`) — both normalize to the category
|
|
@@ -1136,6 +1231,14 @@ export declare class WebMultiSelect<T = any> {
|
|
|
1136
1231
|
*/
|
|
1137
1232
|
private getItemFullTitle;
|
|
1138
1233
|
private getItemSearchValue;
|
|
1234
|
+
/** Sort key for `selectedOrder === 'member'` (member/callback pattern). */
|
|
1235
|
+
private getItemSortKey;
|
|
1236
|
+
/**
|
|
1237
|
+
* Selected options in the order they should be DISPLAYED (badges / partial "+N more" / popover).
|
|
1238
|
+
* Never mutates state — always returns a fresh array. Display concern only: getValue()/form
|
|
1239
|
+
* output/getSelected() keep as-selected (insertion) order. See `selectedOrder`.
|
|
1240
|
+
*/
|
|
1241
|
+
private getOrderedSelectedOptions;
|
|
1139
1242
|
private getItemIcon;
|
|
1140
1243
|
private getItemSubtitle;
|
|
1141
1244
|
private getItemGroup;
|
|
@@ -1158,8 +1261,10 @@ export declare class WebMultiSelect<T = any> {
|
|
|
1158
1261
|
private buildTree;
|
|
1159
1262
|
/**
|
|
1160
1263
|
* Whether cascade checkbox mode is active: a multi-select tree with
|
|
1161
|
-
* `checkbox-mode
|
|
1162
|
-
* and branches show a tristate box.
|
|
1264
|
+
* `checkbox-mode` NOT set to `independent`. Checking a node then toggles its
|
|
1265
|
+
* whole subtree and branches show a tristate box. Cascade is the DEFAULT
|
|
1266
|
+
* (unset → cascade); opt out per-instance with `checkbox-mode="independent"`.
|
|
1267
|
+
* Only ever active in tree + multiple — no subtree to cascade otherwise.
|
|
1163
1268
|
*/
|
|
1164
1269
|
private isCascadeMode;
|
|
1165
1270
|
private cascadePolicy;
|
|
@@ -1250,6 +1355,46 @@ export declare class WebMultiSelect<T = any> {
|
|
|
1250
1355
|
* Check if any options have groups
|
|
1251
1356
|
*/
|
|
1252
1357
|
private hasGroups;
|
|
1358
|
+
/**
|
|
1359
|
+
* Whether the flat-group cascade checkbox is active: a multi-select, grouped,
|
|
1360
|
+
* non-tree list with `group-select-mode="cascade"`. When on, each group header
|
|
1361
|
+
* gets a tristate checkbox that toggles all of that group's visible members.
|
|
1362
|
+
* Tree mode has its own `checkbox-mode` cascade, so this stays flat-only.
|
|
1363
|
+
*/
|
|
1364
|
+
private isGroupCascadeActive;
|
|
1365
|
+
/**
|
|
1366
|
+
* Tristate check-state of a group from its members: `checked` if every
|
|
1367
|
+
* non-disabled member is selected, `unchecked` if none are, else
|
|
1368
|
+
* `indeterminate`. Disabled members are excluded from the denominator so a
|
|
1369
|
+
* group with a stuck-disabled member can still read fully checked. An empty
|
|
1370
|
+
* (or all-disabled) group reads `unchecked`.
|
|
1371
|
+
*/
|
|
1372
|
+
private groupCheckState;
|
|
1373
|
+
/**
|
|
1374
|
+
* Selection roll-up for a flat group's (visible) members: which are selected, how many, and
|
|
1375
|
+
* the tristate check-state. `selectedCount` counts every selected member (including a
|
|
1376
|
+
* disabled-but-selected one) — it's the "N behind the group title". `checkState` excludes
|
|
1377
|
+
* disabled members from its denominator (mirrors the select-all), so a group with a stuck
|
|
1378
|
+
* disabled member can still read fully `checked`. Shared by the header count, the tristate
|
|
1379
|
+
* checkbox, and the `renderGroupLabelContentCallback` context.
|
|
1380
|
+
*/
|
|
1381
|
+
private groupSelectionInfo;
|
|
1382
|
+
/**
|
|
1383
|
+
* Formats the small count chip shared by the in-input counter and the per-group header count.
|
|
1384
|
+
* Default `[selected]` (matches the historical in-input `[N]`); a `getCountLabelCallback` can
|
|
1385
|
+
* switch both to e.g. `selected/total`.
|
|
1386
|
+
*/
|
|
1387
|
+
private formatCountLabel;
|
|
1388
|
+
/** Trailing count chip for a group header — any grouped list (rendered only when >0 selected). */
|
|
1389
|
+
private groupCountHtml;
|
|
1390
|
+
/**
|
|
1391
|
+
* Shared markup for a `.ms__checkbox` input — the single source of truth for option rows, tree
|
|
1392
|
+
* nodes, and group headers. Indeterminate is a pure CSS state (the box is `appearance: none`, so
|
|
1393
|
+
* no native `input.indeterminate` is needed — virtual-scroll-safe) plus `aria-checked="mixed"`.
|
|
1394
|
+
*/
|
|
1395
|
+
private checkboxHtml;
|
|
1396
|
+
/** Group-header tristate checkbox (maps the group's roll-up state onto `checkboxHtml`). */
|
|
1397
|
+
private groupCheckboxHtml;
|
|
1253
1398
|
private renderDropdown;
|
|
1254
1399
|
/**
|
|
1255
1400
|
* Round the OUTER corners of the row at the very top and the row at the very
|
|
@@ -1479,6 +1624,16 @@ export declare class WebMultiSelect<T = any> {
|
|
|
1479
1624
|
private deselectOption;
|
|
1480
1625
|
private selectAll;
|
|
1481
1626
|
clearAll(): void;
|
|
1627
|
+
/**
|
|
1628
|
+
* Flat-group cascade toggle: check or uncheck every (visible) member of a group
|
|
1629
|
+
* in one shot. If the group is fully checked → deselect all its members; else →
|
|
1630
|
+
* select all its non-disabled members. Operates on the currently-filtered
|
|
1631
|
+
* members (same scope as Select-All) and, like Select-All / Clear-All,
|
|
1632
|
+
* batch-mutates then fires a single `commit` — so one render and one `change`
|
|
1633
|
+
* event, and it deliberately bypasses the per-item beforeSelect/beforeDeselect
|
|
1634
|
+
* veto. The group name itself is never added to the selection.
|
|
1635
|
+
*/
|
|
1636
|
+
private toggleGroup;
|
|
1482
1637
|
/**
|
|
1483
1638
|
* Inline clear (✕) handler: wipe the whole selection and any search text, then
|
|
1484
1639
|
* restore focus to the input. clearAll() → commit() → renderBadges() already
|