@keenmate/web-multiselect 2.2.0-rc01 → 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 -13
- package/custom-elements.json +107 -1
- package/dist/index.d.ts +175 -36
- package/dist/multiselect.js +775 -684
- package/dist/multiselect.umd.js +12 -12
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/css/options.css +6 -4
- package/vscode.html-custom-data.json +5 -0
- package/web-types.json +11 -1
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,10 +290,22 @@ 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;
|
|
302
|
+
/**
|
|
303
|
+
* Static CSS string injected into the Shadow DOM (attribute alternative to
|
|
304
|
+
* `customStylesCallback`, via the `custom-styles` attribute). The value is a
|
|
305
|
+
* raw stylesheet — selectors and all — dropped verbatim into the same
|
|
306
|
+
* replaceable style slot. `customStylesCallback` wins when both are set.
|
|
307
|
+
*/
|
|
308
|
+
customStyles?: string;
|
|
255
309
|
/** Member property name for search value extraction */
|
|
256
310
|
searchValueMember?: string;
|
|
257
311
|
/** Callback to extract search value from item */
|
|
@@ -362,8 +416,13 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
362
416
|
* presentation fields. The second argument is additive; one-argument callbacks keep working.
|
|
363
417
|
*/
|
|
364
418
|
renderSelectedItemContentCallback?: (item: T, context: BadgeContentRenderContext) => string | HTMLElement;
|
|
365
|
-
/**
|
|
366
|
-
|
|
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[];
|
|
367
426
|
/**
|
|
368
427
|
* Custom renderer for the selected item display in single-select mode — return plain text (it
|
|
369
428
|
* becomes the input value). Receives a {@link SelectedContentRenderContext} (2nd arg) carrying
|
|
@@ -687,10 +746,17 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
687
746
|
getCountLabelCallback?: ((selected: number, total: number) => string) | null;
|
|
688
747
|
/** Enable tooltips on selected item badges (internal: isBadgeTooltipsEnabled) */
|
|
689
748
|
isBadgeTooltipsEnabled?: boolean;
|
|
690
|
-
/**
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
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;
|
|
694
760
|
/** Format string for remove button tooltip text. Use {0} as placeholder for item name. Default: "Remove {0}" */
|
|
695
761
|
removeButtonTooltipText?: string;
|
|
696
762
|
/**
|
|
@@ -706,8 +772,14 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
706
772
|
badgeTooltipOffset?: number;
|
|
707
773
|
/** Enable tooltips on dropdown options (internal: isOptionTooltipsEnabled) */
|
|
708
774
|
isOptionTooltipsEnabled?: boolean;
|
|
709
|
-
/**
|
|
710
|
-
|
|
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;
|
|
711
783
|
/**
|
|
712
784
|
* Option tooltip placement (Floating UI `Placement`). Default `top-start`
|
|
713
785
|
* (anchored to the row's start edge, so it doesn't center on a full-width row).
|
|
@@ -729,6 +801,46 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
729
801
|
hostElement?: HTMLElement;
|
|
730
802
|
}
|
|
731
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
|
+
|
|
732
844
|
export declare class MultiSelectElement<T = any> extends BlissElement<MultiSelectEvents> {
|
|
733
845
|
#private;
|
|
734
846
|
static formAssociated: boolean;
|
|
@@ -895,10 +1007,11 @@ declare type MultiSelectEvents = {
|
|
|
895
1007
|
};
|
|
896
1008
|
|
|
897
1009
|
/**
|
|
898
|
-
* Imperative facade handed to `keydownCallback
|
|
899
|
-
*
|
|
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.
|
|
900
1013
|
*/
|
|
901
|
-
declare interface MultiSelectKeyboardController<T = any> {
|
|
1014
|
+
export declare interface MultiSelectKeyboardController<T = any> extends MultiSelectController<T> {
|
|
902
1015
|
/** Move focus to the next / previous option. */
|
|
903
1016
|
focusNext(): void;
|
|
904
1017
|
focusPrevious(): void;
|
|
@@ -915,19 +1028,12 @@ declare interface MultiSelectKeyboardController<T = any> {
|
|
|
915
1028
|
focusIndex(index: number): void;
|
|
916
1029
|
/** Toggle the currently focused option (no-op if nothing is focused). */
|
|
917
1030
|
toggleFocused(): void;
|
|
918
|
-
/** Toggle a specific option by its value (select ⇄ deselect). */
|
|
919
|
-
toggleValue(value: string | number): void;
|
|
920
1031
|
/** Select a specific option by its value (no-op if already selected). */
|
|
921
1032
|
selectValue(value: string | number): void;
|
|
922
1033
|
/** Deselect a specific option by its value (no-op if not selected). */
|
|
923
1034
|
deselectValue(value: string | number): void;
|
|
924
|
-
/**
|
|
925
|
-
open(): void;
|
|
926
|
-
close(): void;
|
|
927
|
-
/** Set the search box text (runs the search). */
|
|
1035
|
+
/** @deprecated Alias of {@link MultiSelectController.search}. */
|
|
928
1036
|
setSearch(term: string): void;
|
|
929
|
-
/** Clear the search box and reset the visible list. */
|
|
930
|
-
clearSearch(): void;
|
|
931
1037
|
}
|
|
932
1038
|
|
|
933
1039
|
/**
|
|
@@ -1534,6 +1640,17 @@ export declare class WebMultiSelect<T = any> {
|
|
|
1534
1640
|
/** Lazily build (and cache) the imperative facade passed to `keydownCallback`. Bound to the
|
|
1535
1641
|
* same private actions the built-in key handling uses, so consumer shortcuts behave identically. */
|
|
1536
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;
|
|
1537
1654
|
/** Clear the search box (both the main input and the fullscreen search) and reset the visible
|
|
1538
1655
|
* list. Shared by Escape and the keyboard controller. */
|
|
1539
1656
|
/**
|
|
@@ -1707,6 +1824,22 @@ export declare class WebMultiSelect<T = any> {
|
|
|
1707
1824
|
* so they don't actually break the sheet.
|
|
1708
1825
|
*/
|
|
1709
1826
|
private warnFullscreenContainingBlock;
|
|
1827
|
+
/**
|
|
1828
|
+
* Re-anchor an already-open floating dropdown from scratch so a frozen placement
|
|
1829
|
+
* is re-evaluated against the panel's CURRENT height.
|
|
1830
|
+
*
|
|
1831
|
+
* Why it's needed: an async `searchCallback` opens the panel while it's still
|
|
1832
|
+
* empty / showing the loader — short, so it fits below the input and (with the
|
|
1833
|
+
* default `lock-placement`) freezes to `bottom`. When results arrive the panel
|
|
1834
|
+
* grows to full height, but the frozen placement pins it below the input, so it
|
|
1835
|
+
* overflows the viewport bottom instead of flipping above into the free space.
|
|
1836
|
+
* `renderDropdown()` only rewrites the inner HTML; it never re-anchors. Tearing
|
|
1837
|
+
* down and recreating the anchor re-runs core's flip-on-first-compute against the
|
|
1838
|
+
* new height (picking the side that fits), then re-freezes — so `lock-placement`
|
|
1839
|
+
* still holds for the common case (panels that open already-populated, e.g. local
|
|
1840
|
+
* filtering, never hit this path). No-op unless a floating dropdown is open.
|
|
1841
|
+
*/
|
|
1842
|
+
private repositionDropdown;
|
|
1710
1843
|
private positionDropdown;
|
|
1711
1844
|
/**
|
|
1712
1845
|
* Switch how the open panels are presented. 'floating' anchors them to the input
|
|
@@ -1886,6 +2019,12 @@ export declare class WebMultiSelect<T = any> {
|
|
|
1886
2019
|
* `null → ""`. Callers add their own leading space / base class as needed.
|
|
1887
2020
|
*/
|
|
1888
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;
|
|
1889
2028
|
/**
|
|
1890
2029
|
* Render a removable badge for a selected option (used by the badges/partial display modes
|
|
1891
2030
|
* and by the selected-items popover).
|