@keenmate/web-multiselect 2.2.0-rc02 → 2.2.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 +9 -16
- package/custom-elements.json +77 -0
- package/dist/index.d.ts +152 -36
- package/dist/multiselect.js +468 -397
- package/dist/multiselect.umd.js +11 -11
- package/package.json +1 -1
- package/web-types.json +1 -1
package/README.md
CHANGED
|
@@ -21,22 +21,15 @@ Reads `--base-*` variables from the page if [`@keenmate/theme-designer`](https:/
|
|
|
21
21
|
- Custom rendering callbacks for options, badges, and group headers.
|
|
22
22
|
- Form integration via standard hidden inputs (FormData-compatible).
|
|
23
23
|
|
|
24
|
-
## What's New in v2.2.0
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
- **
|
|
29
|
-
|
|
30
|
-
- **
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
- **Tree cascade is now the default — check a branch, check its subtree** — In a multi-select tree, `checkbox-mode` now defaults to `cascade` (previously `independent`), so ticking a branch selects its whole subtree and branches render a tristate (checked / indeterminate / unchecked) box — what most tree-select UIs do. The emitted selection follows `cascade-select-policy` (default `rolled-up`: a fully-checked subtree collapses to its root value). This is a behavior change for existing tree consumers — set `checkbox-mode="independent"` to keep the old per-node toggling. Flat and single-select lists are unaffected, since there's no subtree to cascade into.
|
|
35
|
-
- **Per-group select-all in flat grouped lists — `group-select-mode="cascade"`** — A new attribute puts a tristate checkbox on each group header in a flat, multi-select, grouped list; clicking it checks or unchecks all of that group's currently-visible members. The group name itself is never a selected value — `getValue()`, badges, and form output carry member values only — a partially-selected group reads indeterminate, and a header toggle fires a single `change`. Disabled members are excluded from the select-all. Default `none` leaves headers inert, as before.
|
|
36
|
-
- **Per-group selected counts + one shared count formatter** — Every group header now shows a count of that group's selected members, rendered as the same small chip as the in-input `[N]` counter (not a new badge style). A new `getCountLabelCallback((selected, total) => string)` formats both the in-input counter and the group chip together so they always read the same way — default `[3]`, or return `` `${s}/${t}` `` for an "x / y of total" style, where `total` is the whole option list for the counter and the group's member count for a header.
|
|
37
|
-
- **Order the selected items — `selected-order`** — Control the sequence chosen items appear in across badges, partial "+N more", and the selected-items popover: `as-selected` (default), `label-asc` / `label-desc`, `member` (by a `selected-order-member` property or `getSelectedOrderCallback`), or `custom` (a comparator). It's display-only — `getValue()`, form output, and `getSelected()` keep insertion order — and because the ordering runs in one shared place, the partial "+N more" split and its remove button always act on the items sorted *after* the visible slice.
|
|
38
|
-
- **Every render callback now receives a context** — `renderGroupLabelContentCallback` gains a second `GroupLabelRenderContext` argument (the group's members and selection, e.g. `selectedCount`), and `renderSelectedItemContentCallback` / `renderSelectedContentCallback` now also receive a context carrying the presentation (`isFullscreen` / `isModal`) — matching the option and badge callbacks. Everything is additive, so existing one-argument callbacks keep working; branch on `isFullscreen` to render leaner content in the phone overlay.
|
|
39
|
-
- **Fixes — selection preservation, hidden search field, "+N more" ✕** — Changing a cosmetic attribute (`badges-display-mode` / `badges-position`) no longer wipes the current selection (it's applied in place, and genuine rebuilds now preserve the runtime selection); `search-input-mode="hidden"` no longer collapses the input row, so the toggle stays at the trailing edge; and the "+N more" badge's ✕ now removes exactly the hidden items instead of silently opening the popover.
|
|
24
|
+
## What's New in v2.2.0
|
|
25
|
+
|
|
26
|
+
- **Standardized callback context — one typed contract for action-button and display callbacks** — The action-button callbacks used to receive the untyped picker instance, and the display `get*` callbacks (badge display/class/tooltip, remove-button tooltip, selected-item class, option tooltip) got only the item. They now receive a typed second argument: a new `ActionContext<T>` (extends `PresentationContext`, carrying component state, the host element, and a `MultiSelectController<T>` imperative facade) for `getIsVisible`/`getIsDisabled`/`getText`/`getClass`/`getTooltip`/`onClick`, and the same `BadgeContentRenderContext` / `OptionContentRenderContext` their `render*` twin already gets for the display siblings. Everything is additive — existing one-argument callbacks keep working — and `ActionContext`, `MultiSelectController`, `MultiSelectKeyboardController`, and `ActionButton` are now exported from the package entry.
|
|
27
|
+
- **`custom-styles` attribute — style shadow-DOM internals with zero JavaScript** — The only way to inject custom CSS into the shadow root used to be `customStylesCallback`, which locked out static HTML, server-rendered markup, and no-build sites. The new `custom-styles` attribute takes raw CSS as a string and injects it verbatim into the same replaceable style slot the callback uses, so you can restyle badges, options, and your own custom-rendered content declaratively. It's reactive, mirrored by a `customStyles` property, and flows through the same dev-mode `--ms-*` lint; when both are set, `customStylesCallback` still wins.
|
|
28
|
+
- **Tree cascade by default, plus per-group select-all** — In a multi-select tree, `checkbox-mode` now defaults to `cascade`: ticking a branch selects its whole subtree, branches render tristate, and the emitted value follows `cascade-select-policy` (default `rolled-up`). This is a behavior change for existing tree consumers — set `checkbox-mode="independent"` to keep per-node toggling. Flat grouped lists get the parallel `group-select-mode="cascade"`, a tristate select-all checkbox on each group header (member values only — the group name is never a value).
|
|
29
|
+
- **Per-group selected counts + one shared count formatter** — Every group header now shows a count of that group's selected members, rendered as the same small chip as the in-input `[N]` counter. A new `getCountLabelCallback((selected, total) => string)` formats both places together so they always read the same way — default `[3]`, or return `` `${s}/${t}` `` for an x-of-total style.
|
|
30
|
+
- **Order the selected items — `selected-order`** — Control the sequence chosen items appear in across badges, the partial "+N more" split, and the popover: `as-selected` (default), `label-asc`/`label-desc`, `member` (via `selected-order-member` or `getSelectedOrderCallback`), or `custom` (a comparator). Display-only — `getValue()`, form output, and `getSelected()` keep insertion order.
|
|
31
|
+
- **Every render callback now carries the presentation context** — `renderSelectedItemContentCallback`, `renderSelectedContentCallback`, and `renderGroupLabelContentCallback` now receive a second context argument (matching the option and badge callbacks), so any custom renderer can branch on `isFullscreen`/`isModal` to render leaner content in the phone overlay. The context render-type interfaces are exported from the package entry, and it's additive — one-argument callbacks are unaffected.
|
|
32
|
+
- **Fixes — selection & layout robustness** — Single-select no longer keeps a stale multi-selection when seeded with several values; an async `searchCallback` dropdown no longer overflows the viewport when results grow after it opens near the bottom; changing a cosmetic attribute (`badges-display-mode`/`badges-position`) no longer wipes the selection; `search-input-mode="hidden"` no longer collapses the input row; and the "+N more" badge's ✕ now removes the hidden items instead of silently opening the popover.
|
|
40
33
|
|
|
41
34
|
## Demos & docs
|
|
42
35
|
|
package/custom-elements.json
CHANGED
|
@@ -925,6 +925,13 @@
|
|
|
925
925
|
"type": {
|
|
926
926
|
"text": "T"
|
|
927
927
|
}
|
|
928
|
+
},
|
|
929
|
+
{
|
|
930
|
+
"name": "context",
|
|
931
|
+
"optional": true,
|
|
932
|
+
"type": {
|
|
933
|
+
"text": "BadgeContentRenderContext"
|
|
934
|
+
}
|
|
928
935
|
}
|
|
929
936
|
],
|
|
930
937
|
"description": "Badge display falls back to the regular display value rather than '[N/A]', so consumers can override badge\ntext independently. Doesn't fit the extractField shape (no tuple/member layer of its own)."
|
|
@@ -2091,6 +2098,36 @@
|
|
|
2091
2098
|
},
|
|
2092
2099
|
"description": "Lazily build (and cache) the imperative facade passed to `keydownCallback`. Bound to the\nsame private actions the built-in key handling uses, so consumer shortcuts behave identically."
|
|
2093
2100
|
},
|
|
2101
|
+
{
|
|
2102
|
+
"kind": "method",
|
|
2103
|
+
"name": "hostEl",
|
|
2104
|
+
"privacy": "private",
|
|
2105
|
+
"return": {
|
|
2106
|
+
"type": {
|
|
2107
|
+
"text": "HTMLElement"
|
|
2108
|
+
}
|
|
2109
|
+
},
|
|
2110
|
+
"description": "The host custom element — `this.element` is the internal `.ms` mount (inside the shadow\nroot), so the host is its root node's `host` when shadowed, else the mount itself. Used as\nthe ActionContext escape hatch (and where a wrapper hangs a server bridge)."
|
|
2111
|
+
},
|
|
2112
|
+
{
|
|
2113
|
+
"kind": "method",
|
|
2114
|
+
"name": "buildActionContext",
|
|
2115
|
+
"privacy": "private",
|
|
2116
|
+
"return": {
|
|
2117
|
+
"type": {
|
|
2118
|
+
"text": "ActionContext<T>"
|
|
2119
|
+
}
|
|
2120
|
+
},
|
|
2121
|
+
"parameters": [
|
|
2122
|
+
{
|
|
2123
|
+
"name": "button",
|
|
2124
|
+
"type": {
|
|
2125
|
+
"text": "ActionButton<T>"
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
],
|
|
2129
|
+
"description": "Build the ActionContext passed (as the additive 2nd arg) to every action-button\ncallback and the `onClick` event: a snapshot of live state plus the shared controller."
|
|
2130
|
+
},
|
|
2094
2131
|
{
|
|
2095
2132
|
"kind": "method",
|
|
2096
2133
|
"name": "clearSearch",
|
|
@@ -3032,6 +3069,25 @@
|
|
|
3032
3069
|
],
|
|
3033
3070
|
"description": "Normalize a class callback result (`string | string[] | null`) to a single\nspace-joined string with falsy entries dropped — e.g. `['a', '', 'b'] → \"a b\"`,\n`null → \"\"`. Callers add their own leading space / base class as needed."
|
|
3034
3071
|
},
|
|
3072
|
+
{
|
|
3073
|
+
"kind": "method",
|
|
3074
|
+
"name": "badgeRenderContext",
|
|
3075
|
+
"privacy": "private",
|
|
3076
|
+
"return": {
|
|
3077
|
+
"type": {
|
|
3078
|
+
"text": "BadgeContentRenderContext"
|
|
3079
|
+
}
|
|
3080
|
+
},
|
|
3081
|
+
"parameters": [
|
|
3082
|
+
{
|
|
3083
|
+
"name": "isInPopover",
|
|
3084
|
+
"type": {
|
|
3085
|
+
"text": "boolean"
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
],
|
|
3089
|
+
"description": "Build the BadgeContentRenderContext handed to the sibling `get*` callbacks\n(badge display / class / tooltip), so they see the same context the `render*` badge\ncallbacks get: `displayMode`, `isInPopover`, plus the shared presentation fields."
|
|
3090
|
+
},
|
|
3035
3091
|
{
|
|
3036
3092
|
"kind": "method",
|
|
3037
3093
|
"name": "renderBadgeHTML",
|
|
@@ -3242,6 +3298,13 @@
|
|
|
3242
3298
|
"type": {
|
|
3243
3299
|
"text": "T"
|
|
3244
3300
|
}
|
|
3301
|
+
},
|
|
3302
|
+
{
|
|
3303
|
+
"name": "context",
|
|
3304
|
+
"optional": true,
|
|
3305
|
+
"type": {
|
|
3306
|
+
"text": "BadgeContentRenderContext"
|
|
3307
|
+
}
|
|
3245
3308
|
}
|
|
3246
3309
|
],
|
|
3247
3310
|
"description": "Build the badge-text tooltip content (callback overrides; default = displayValue + optional subtitle on next line)."
|
|
@@ -3268,6 +3331,13 @@
|
|
|
3268
3331
|
"type": {
|
|
3269
3332
|
"text": "T"
|
|
3270
3333
|
}
|
|
3334
|
+
},
|
|
3335
|
+
{
|
|
3336
|
+
"name": "context",
|
|
3337
|
+
"optional": true,
|
|
3338
|
+
"type": {
|
|
3339
|
+
"text": "BadgeContentRenderContext"
|
|
3340
|
+
}
|
|
3271
3341
|
}
|
|
3272
3342
|
],
|
|
3273
3343
|
"description": "Build the remove-button tooltip text (callback > format string with {0} > \"Remove {name}\")."
|
|
@@ -3306,6 +3376,13 @@
|
|
|
3306
3376
|
"type": {
|
|
3307
3377
|
"text": "T"
|
|
3308
3378
|
}
|
|
3379
|
+
},
|
|
3380
|
+
{
|
|
3381
|
+
"name": "context",
|
|
3382
|
+
"optional": true,
|
|
3383
|
+
"type": {
|
|
3384
|
+
"text": "OptionContentRenderContext"
|
|
3385
|
+
}
|
|
3309
3386
|
}
|
|
3310
3387
|
],
|
|
3311
3388
|
"description": "Build the option tooltip content (callback overrides; default = displayValue + optional subtitle on next line)."
|
package/dist/index.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ import { TABLET_MIN_SHORT_SIDE } from '@keenmate/web-components-core';
|
|
|
22
22
|
* Action button configuration for dropdown actions (Select All, Clear All, custom actions)
|
|
23
23
|
* @template T The type of data items
|
|
24
24
|
*/
|
|
25
|
-
declare interface ActionButton<T = any> {
|
|
25
|
+
export declare interface ActionButton<T = any> {
|
|
26
26
|
/** Action identifier ('select-all', 'clear-all', or 'custom' for custom actions) */
|
|
27
27
|
action: 'select-all' | 'clear-all' | 'custom';
|
|
28
28
|
/** Button text label */
|
|
@@ -42,18 +42,53 @@ declare interface ActionButton<T = any> {
|
|
|
42
42
|
isVisible?: boolean;
|
|
43
43
|
/** Static disabled state - set to true to disable button */
|
|
44
44
|
isDisabled?: boolean;
|
|
45
|
-
/**
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
/** Dynamic
|
|
52
|
-
|
|
53
|
-
/** Dynamic
|
|
54
|
-
|
|
55
|
-
/** Dynamic
|
|
56
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Custom click handler (required for 'custom' action). The 1st arg is the live picker
|
|
47
|
+
* instance (as before); the additive 2nd arg is a typed {@link ActionContext} (state +
|
|
48
|
+
* controller). One-argument handlers keep working.
|
|
49
|
+
*/
|
|
50
|
+
onClick?: (multiselect: any, context?: ActionContext<T>) => void | Promise<void>;
|
|
51
|
+
/** Dynamic visibility callback - return false to hide button (takes priority over isVisible). Additive 2nd arg: {@link ActionContext}. */
|
|
52
|
+
getIsVisibleCallback?: (multiselect: any, context?: ActionContext<T>) => boolean;
|
|
53
|
+
/** Dynamic disabled state callback - return true to disable button (takes priority over isDisabled). Additive 2nd arg: {@link ActionContext}. */
|
|
54
|
+
getIsDisabledCallback?: (multiselect: any, context?: ActionContext<T>) => boolean;
|
|
55
|
+
/** Dynamic text callback - return button text (takes priority over text). Additive 2nd arg: {@link ActionContext}. */
|
|
56
|
+
getTextCallback?: (multiselect: any, context?: ActionContext<T>) => string;
|
|
57
|
+
/** Dynamic CSS class callback - return class name(s) (takes priority over cssClass). Additive 2nd arg: {@link ActionContext}. */
|
|
58
|
+
getClassCallback?: (multiselect: any, context?: ActionContext<T>) => string | string[];
|
|
59
|
+
/** Dynamic tooltip callback - return tooltip text (takes priority over tooltip). Additive 2nd arg: {@link ActionContext}. */
|
|
60
|
+
getTooltipCallback?: (multiselect: any, context?: ActionContext<T>) => string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Context handed (as the additive 2nd argument) to the action-button callbacks —
|
|
65
|
+
* {@link ActionButton.getTextCallback} / `getIsVisibleCallback` / `getIsDisabledCallback` /
|
|
66
|
+
* `getClassCallback` / `getTooltipCallback` — and to the `onClick` event. A typed snapshot of
|
|
67
|
+
* live state plus a {@link MultiSelectController} facade, replacing reliance on the untyped picker
|
|
68
|
+
* instance passed as the first argument. Extends {@link PresentationContext}, so a callback can
|
|
69
|
+
* branch on how the panel is presented (floating vs fullscreen), consistent with the render callbacks.
|
|
70
|
+
*/
|
|
71
|
+
export declare interface ActionContext<T = any> extends PresentationContext {
|
|
72
|
+
/** The action button config entry this callback belongs to. */
|
|
73
|
+
button: ActionButton<T>;
|
|
74
|
+
/** Currently selected scalar values. */
|
|
75
|
+
selectedValues: (string | number)[];
|
|
76
|
+
/** Currently selected option objects, in selection order. */
|
|
77
|
+
selectedOptions: T[];
|
|
78
|
+
/** All available options (post assignment). */
|
|
79
|
+
options: ReadonlyArray<T>;
|
|
80
|
+
/** `selectedOptions.length` — convenience. */
|
|
81
|
+
selectedCount: number;
|
|
82
|
+
/** `options.length` — convenience (the Select-All denominator). */
|
|
83
|
+
optionCount: number;
|
|
84
|
+
/** Whether the dropdown is currently open. */
|
|
85
|
+
isOpen: boolean;
|
|
86
|
+
/** The current search term. */
|
|
87
|
+
searchTerm: string;
|
|
88
|
+
/** Imperative facade — drive the picker (selection / dropdown / search / messages). */
|
|
89
|
+
controller: MultiSelectController<T>;
|
|
90
|
+
/** Escape hatch: the host custom element, for anything not on the controller. */
|
|
91
|
+
element: HTMLElement & Record<string, any>;
|
|
57
92
|
}
|
|
58
93
|
|
|
59
94
|
/** Horizontal arrangement of buttons within an action row. `stretch` = full-width (default). */
|
|
@@ -218,8 +253,15 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
218
253
|
displayValueMember?: string;
|
|
219
254
|
/** Callback to extract display value from item */
|
|
220
255
|
getDisplayValueCallback?: (item: T) => string;
|
|
221
|
-
/**
|
|
222
|
-
|
|
256
|
+
/**
|
|
257
|
+
* Callback to customize badge display text (defaults to display value if not provided).
|
|
258
|
+
* The second argument is additive: when the value is computed while rendering a specific
|
|
259
|
+
* badge/popover item it receives that item's {@link BadgeContentRenderContext} (`displayMode`,
|
|
260
|
+
* `isInPopover`, and the shared presentation fields); it is **absent** when the value is needed
|
|
261
|
+
* outside a render (e.g. selected-order sorting, the counter chip's title), so one-argument
|
|
262
|
+
* callbacks keep working. Treat `context` as optional.
|
|
263
|
+
*/
|
|
264
|
+
getBadgeDisplayCallback?: (item: T, context?: BadgeContentRenderContext) => string;
|
|
223
265
|
/**
|
|
224
266
|
* Order of the CURRENTLY-SELECTED items *where they are displayed* — badges, partial mode
|
|
225
267
|
* (i.e. which items sit behind the "+N more" badge), and the selected-items popover. This is a
|
|
@@ -248,8 +290,13 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
248
290
|
fullTitleMember?: string;
|
|
249
291
|
/** Callback to extract the full title from an item (takes precedence over `fullTitleMember`). */
|
|
250
292
|
getFullTitleCallback?: (item: T) => string;
|
|
251
|
-
/**
|
|
252
|
-
|
|
293
|
+
/**
|
|
294
|
+
* Callback to add custom CSS classes to badges - return string or array of class names.
|
|
295
|
+
* Additive 2nd arg: receives the badge's {@link BadgeContentRenderContext} when invoked during
|
|
296
|
+
* a badge render (the same context {@link renderBadgeContentCallback} gets), so classes can react
|
|
297
|
+
* to `displayMode` / `isInPopover` / presentation. Optional — one-argument callbacks keep working.
|
|
298
|
+
*/
|
|
299
|
+
getBadgeClassCallback?: (item: T, context?: BadgeContentRenderContext) => string | string[];
|
|
253
300
|
/** Callback to inject custom CSS into Shadow DOM - return CSS string for styling custom classes */
|
|
254
301
|
customStylesCallback?: () => string;
|
|
255
302
|
/**
|
|
@@ -369,8 +416,13 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
369
416
|
* presentation fields. The second argument is additive; one-argument callbacks keep working.
|
|
370
417
|
*/
|
|
371
418
|
renderSelectedItemContentCallback?: (item: T, context: BadgeContentRenderContext) => string | HTMLElement;
|
|
372
|
-
/**
|
|
373
|
-
|
|
419
|
+
/**
|
|
420
|
+
* Callback to add custom CSS classes to selected items in popover - return string or array of
|
|
421
|
+
* class names. Additive 2nd arg: receives the {@link BadgeContentRenderContext} for the popover
|
|
422
|
+
* item (`isInPopover` is `true`) — the same context {@link renderSelectedItemContentCallback}
|
|
423
|
+
* gets. Optional — one-argument callbacks keep working.
|
|
424
|
+
*/
|
|
425
|
+
getSelectedItemClassCallback?: (item: T, context?: BadgeContentRenderContext) => string | string[];
|
|
374
426
|
/**
|
|
375
427
|
* Custom renderer for the selected item display in single-select mode — return plain text (it
|
|
376
428
|
* becomes the input value). Receives a {@link SelectedContentRenderContext} (2nd arg) carrying
|
|
@@ -694,10 +746,17 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
694
746
|
getCountLabelCallback?: ((selected: number, total: number) => string) | null;
|
|
695
747
|
/** Enable tooltips on selected item badges (internal: isBadgeTooltipsEnabled) */
|
|
696
748
|
isBadgeTooltipsEnabled?: boolean;
|
|
697
|
-
/**
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
749
|
+
/**
|
|
750
|
+
* Callback to generate custom tooltip content for a badge. Additive 2nd arg: receives the
|
|
751
|
+
* badge's {@link BadgeContentRenderContext} (`displayMode` / `isInPopover` / presentation), the
|
|
752
|
+
* same context {@link renderBadgeContentCallback} gets. Optional — one-argument callbacks keep working.
|
|
753
|
+
*/
|
|
754
|
+
getBadgeTooltipCallback?: ((item: T, context?: BadgeContentRenderContext) => string | HTMLElement) | null;
|
|
755
|
+
/**
|
|
756
|
+
* Callback to generate custom tooltip text for a remove button. Additive 2nd arg: the badge's
|
|
757
|
+
* {@link BadgeContentRenderContext}. Optional — one-argument callbacks keep working.
|
|
758
|
+
*/
|
|
759
|
+
getRemoveButtonTooltipCallback?: ((item: T, context?: BadgeContentRenderContext) => string) | null;
|
|
701
760
|
/** Format string for remove button tooltip text. Use {0} as placeholder for item name. Default: "Remove {0}" */
|
|
702
761
|
removeButtonTooltipText?: string;
|
|
703
762
|
/**
|
|
@@ -713,8 +772,14 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
713
772
|
badgeTooltipOffset?: number;
|
|
714
773
|
/** Enable tooltips on dropdown options (internal: isOptionTooltipsEnabled) */
|
|
715
774
|
isOptionTooltipsEnabled?: boolean;
|
|
716
|
-
/**
|
|
717
|
-
|
|
775
|
+
/**
|
|
776
|
+
* Callback to generate custom tooltip content for a dropdown option. Default: display value, plus
|
|
777
|
+
* subtitle on the next line when present. Additive 2nd arg: receives the row's
|
|
778
|
+
* {@link OptionContentRenderContext} (`index`, `isSelected`, `isFocused`, `isMatched`,
|
|
779
|
+
* `isDisabled`, presentation), the same context {@link renderOptionContentCallback} gets, so an
|
|
780
|
+
* option tooltip can match how the row itself was rendered. Optional — one-argument callbacks keep working.
|
|
781
|
+
*/
|
|
782
|
+
getOptionTooltipCallback?: ((item: T, context?: OptionContentRenderContext) => string | HTMLElement) | null;
|
|
718
783
|
/**
|
|
719
784
|
* Option tooltip placement (Floating UI `Placement`). Default `top-start`
|
|
720
785
|
* (anchored to the row's start edge, so it doesn't center on a full-width row).
|
|
@@ -736,6 +801,46 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
736
801
|
hostElement?: HTMLElement;
|
|
737
802
|
}
|
|
738
803
|
|
|
804
|
+
/**
|
|
805
|
+
* Imperative facade for driving a live picker from a callback without reaching into internals.
|
|
806
|
+
* Shared base of the callback controllers: {@link MultiSelectKeyboardController} (handed to
|
|
807
|
+
* `keydownCallback`) extends it with focus-navigation, and {@link ActionContext} exposes it to
|
|
808
|
+
* the action-button callbacks. Every method mirrors a public element method.
|
|
809
|
+
*/
|
|
810
|
+
export declare interface MultiSelectController<T = any> {
|
|
811
|
+
/** The selected option objects, in selection order (mirrors `el.getSelected()`). */
|
|
812
|
+
getSelected(): T[];
|
|
813
|
+
/** The selection as returned to forms/consumers — scalar or array per `multiple` (mirrors `el.getValue()`). */
|
|
814
|
+
getValue(): string | number | (string | number)[] | null;
|
|
815
|
+
/** All available options (post assignment, pre-filter). */
|
|
816
|
+
getOptions(): ReadonlyArray<T>;
|
|
817
|
+
/** Replace the selection. Silent by default; pass `{ notify: true }` to emit ONE aggregate `change`. */
|
|
818
|
+
setSelected(values: (string | number)[], opts?: {
|
|
819
|
+
notify?: boolean;
|
|
820
|
+
}): void;
|
|
821
|
+
/** Select every selectable option. */
|
|
822
|
+
selectAll(): void;
|
|
823
|
+
/** Clear the whole selection. */
|
|
824
|
+
clearAll(): void;
|
|
825
|
+
/** Toggle a single option by its value (select ⇄ deselect). */
|
|
826
|
+
toggleValue(value: string | number): void;
|
|
827
|
+
open(): void;
|
|
828
|
+
close(): void;
|
|
829
|
+
toggle(): void;
|
|
830
|
+
/** Set the search box text (runs the search, exactly as if typed). */
|
|
831
|
+
search(term: string): void;
|
|
832
|
+
/** Clear the search box and restore the full list (does not touch the selection). */
|
|
833
|
+
clearSearch(): void;
|
|
834
|
+
/** Scroll a specific option / group / index into view. */
|
|
835
|
+
scrollToValue(value: string | number): void;
|
|
836
|
+
scrollToGroup(group: string): void;
|
|
837
|
+
scrollToIndex(index: number): void;
|
|
838
|
+
/** Surface a transient message ("toast"), visible even in the fullscreen overlay. */
|
|
839
|
+
showMessage(content: string | HTMLElement, opts?: MessageOptions): void;
|
|
840
|
+
/** Dismiss the transient message, if any. */
|
|
841
|
+
hideMessage(): void;
|
|
842
|
+
}
|
|
843
|
+
|
|
739
844
|
export declare class MultiSelectElement<T = any> extends BlissElement<MultiSelectEvents> {
|
|
740
845
|
#private;
|
|
741
846
|
static formAssociated: boolean;
|
|
@@ -902,10 +1007,11 @@ declare type MultiSelectEvents = {
|
|
|
902
1007
|
};
|
|
903
1008
|
|
|
904
1009
|
/**
|
|
905
|
-
* Imperative facade handed to `keydownCallback
|
|
906
|
-
*
|
|
1010
|
+
* Imperative facade handed to `keydownCallback`: the shared {@link MultiSelectController} plus the
|
|
1011
|
+
* focus-navigation methods that only make sense mid-keystroke. Every method mirrors a built-in
|
|
1012
|
+
* keyboard action.
|
|
907
1013
|
*/
|
|
908
|
-
declare interface MultiSelectKeyboardController<T = any> {
|
|
1014
|
+
export declare interface MultiSelectKeyboardController<T = any> extends MultiSelectController<T> {
|
|
909
1015
|
/** Move focus to the next / previous option. */
|
|
910
1016
|
focusNext(): void;
|
|
911
1017
|
focusPrevious(): void;
|
|
@@ -922,19 +1028,12 @@ declare interface MultiSelectKeyboardController<T = any> {
|
|
|
922
1028
|
focusIndex(index: number): void;
|
|
923
1029
|
/** Toggle the currently focused option (no-op if nothing is focused). */
|
|
924
1030
|
toggleFocused(): void;
|
|
925
|
-
/** Toggle a specific option by its value (select ⇄ deselect). */
|
|
926
|
-
toggleValue(value: string | number): void;
|
|
927
1031
|
/** Select a specific option by its value (no-op if already selected). */
|
|
928
1032
|
selectValue(value: string | number): void;
|
|
929
1033
|
/** Deselect a specific option by its value (no-op if not selected). */
|
|
930
1034
|
deselectValue(value: string | number): void;
|
|
931
|
-
/**
|
|
932
|
-
open(): void;
|
|
933
|
-
close(): void;
|
|
934
|
-
/** Set the search box text (runs the search). */
|
|
1035
|
+
/** @deprecated Alias of {@link MultiSelectController.search}. */
|
|
935
1036
|
setSearch(term: string): void;
|
|
936
|
-
/** Clear the search box and reset the visible list. */
|
|
937
|
-
clearSearch(): void;
|
|
938
1037
|
}
|
|
939
1038
|
|
|
940
1039
|
/**
|
|
@@ -1541,6 +1640,17 @@ export declare class WebMultiSelect<T = any> {
|
|
|
1541
1640
|
/** Lazily build (and cache) the imperative facade passed to `keydownCallback`. Bound to the
|
|
1542
1641
|
* same private actions the built-in key handling uses, so consumer shortcuts behave identically. */
|
|
1543
1642
|
private getKeyboardController;
|
|
1643
|
+
/**
|
|
1644
|
+
* The host custom element — `this.element` is the internal `.ms` mount (inside the shadow
|
|
1645
|
+
* root), so the host is its root node's `host` when shadowed, else the mount itself. Used as
|
|
1646
|
+
* the {@link ActionContext} escape hatch (and where a wrapper hangs a server bridge).
|
|
1647
|
+
*/
|
|
1648
|
+
private hostEl;
|
|
1649
|
+
/**
|
|
1650
|
+
* Build the {@link ActionContext} passed (as the additive 2nd arg) to every action-button
|
|
1651
|
+
* callback and the `onClick` event: a snapshot of live state plus the shared controller.
|
|
1652
|
+
*/
|
|
1653
|
+
private buildActionContext;
|
|
1544
1654
|
/** Clear the search box (both the main input and the fullscreen search) and reset the visible
|
|
1545
1655
|
* list. Shared by Escape and the keyboard controller. */
|
|
1546
1656
|
/**
|
|
@@ -1909,6 +2019,12 @@ export declare class WebMultiSelect<T = any> {
|
|
|
1909
2019
|
* `null → ""`. Callers add their own leading space / base class as needed.
|
|
1910
2020
|
*/
|
|
1911
2021
|
private classSuffix;
|
|
2022
|
+
/**
|
|
2023
|
+
* Build the {@link BadgeContentRenderContext} handed to the sibling `get*` callbacks
|
|
2024
|
+
* (badge display / class / tooltip), so they see the same context the `render*` badge
|
|
2025
|
+
* callbacks get: `displayMode`, `isInPopover`, plus the shared presentation fields.
|
|
2026
|
+
*/
|
|
2027
|
+
private badgeRenderContext;
|
|
1912
2028
|
/**
|
|
1913
2029
|
* Render a removable badge for a selected option (used by the badges/partial display modes
|
|
1914
2030
|
* and by the selected-items popover).
|