@keenmate/web-multiselect 2.0.0-rc09 → 2.0.0-rc11
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 +188 -176
- package/custom-elements.json +377 -73
- package/dist/index.d.ts +154 -3
- package/dist/multiselect.js +1590 -1235
- package/dist/multiselect.umd.js +13 -12
- package/dist/style.css +1 -1
- package/docs/accessibility.md +1 -1
- package/docs/examples.md +5 -4
- package/docs/usage.md +5 -0
- package/package.json +2 -2
- package/src/css/badges.css +14 -0
- package/src/css/controls.css +89 -25
- package/src/css/floating.css +16 -2
- package/src/css/states.css +16 -5
- package/src/css/variables.css +24 -10
- package/vscode.html-custom-data.json +16 -1
- package/web-types.json +43 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import { BlissElement } from '@keenmate/web-components-core';
|
|
2
|
+
import { BreakpointMap } from '@keenmate/web-components-core';
|
|
3
|
+
import { classifyDevice } from '@keenmate/web-components-core';
|
|
4
|
+
import { configureBreakpoints } from '@keenmate/web-components-core';
|
|
5
|
+
import { DeviceClass } from '@keenmate/web-components-core';
|
|
6
|
+
import { ElementSize } from '@keenmate/web-components-core';
|
|
2
7
|
import { EnvironmentSnapshot } from '@keenmate/web-components-core';
|
|
8
|
+
import { getEnvironment } from '@keenmate/web-components-core';
|
|
3
9
|
import { InputDef } from '@keenmate/web-components-core';
|
|
4
10
|
import { Logger } from '@keenmate/web-components-core';
|
|
5
11
|
import { LogLevelDesc } from '@keenmate/web-components-core';
|
|
12
|
+
import { observeEnvironment } from '@keenmate/web-components-core';
|
|
13
|
+
import { observeViewport } from '@keenmate/web-components-core';
|
|
14
|
+
import { Orientation } from '@keenmate/web-components-core';
|
|
15
|
+
import { OS } from '@keenmate/web-components-core';
|
|
6
16
|
import { Placement } from '@keenmate/web-components-core/positioning';
|
|
17
|
+
import { PointerType } from '@keenmate/web-components-core';
|
|
7
18
|
import { PresentationContext } from '@keenmate/web-components-core';
|
|
19
|
+
import { TABLET_MIN_SHORT_SIDE } from '@keenmate/web-components-core';
|
|
8
20
|
|
|
9
21
|
/**
|
|
10
22
|
* Action button configuration for dropdown actions (Select All, Clear All, custom actions)
|
|
@@ -82,14 +94,26 @@ export declare type BadgesPosition = 'top' | 'bottom' | 'left' | 'right';
|
|
|
82
94
|
*/
|
|
83
95
|
export declare type BadgesThresholdMode = 'count' | 'partial';
|
|
84
96
|
|
|
97
|
+
export { BreakpointMap }
|
|
98
|
+
|
|
99
|
+
export { classifyDevice }
|
|
100
|
+
|
|
101
|
+
export { configureBreakpoints }
|
|
102
|
+
|
|
85
103
|
export declare const dataLogger: Logger;
|
|
86
104
|
|
|
105
|
+
export { DeviceClass }
|
|
106
|
+
|
|
87
107
|
/** Disable all logging (silent). */
|
|
88
108
|
export declare function disableLogging(): void;
|
|
89
109
|
|
|
90
110
|
/** Enable all logging (debug level). */
|
|
91
111
|
export declare function enableLogging(): void;
|
|
92
112
|
|
|
113
|
+
export { EnvironmentSnapshot }
|
|
114
|
+
|
|
115
|
+
export { getEnvironment }
|
|
116
|
+
|
|
93
117
|
export declare const initLogger: Logger;
|
|
94
118
|
|
|
95
119
|
export declare const interactionLogger: Logger;
|
|
@@ -256,6 +280,17 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
256
280
|
renderOptionContentCallback?: (item: T, context: OptionContentRenderContext) => string | HTMLElement;
|
|
257
281
|
/** Custom renderer for badge content (main badges area) - return HTML string or HTMLElement */
|
|
258
282
|
renderBadgeContentCallback?: (item: T, context: BadgeContentRenderContext) => string | HTMLElement;
|
|
283
|
+
/**
|
|
284
|
+
* Custom renderer for the WHOLE badge (main badges area) — return HTML string or HTMLElement
|
|
285
|
+
* for the entire pill/card, not just its content. Unlike renderBadgeContentCallback (which fills
|
|
286
|
+
* the built-in pill), this replaces the badge markup entirely. The component wraps your output in
|
|
287
|
+
* a `.ms__badge.ms__badge--custom` element carrying `data-value`, and delegates removal to any
|
|
288
|
+
* element inside it with `data-action="remove"` (or the built-in `.ms__badge-remove` class) — so
|
|
289
|
+
* put a remove control in your markup and the component handles the deselect. Falls back to the
|
|
290
|
+
* default pill for a given item if the callback returns null/empty. Main badges area only (the
|
|
291
|
+
* selected-items popover keeps using renderSelectedItemContentCallback).
|
|
292
|
+
*/
|
|
293
|
+
renderBadgeCallback?: (item: T, context: BadgeContentRenderContext) => string | HTMLElement | null | undefined;
|
|
259
294
|
/** Custom renderer for selected item content in popover - return HTML string or HTMLElement */
|
|
260
295
|
renderSelectedItemContentCallback?: (item: T) => string | HTMLElement;
|
|
261
296
|
/** Callback to add custom CSS classes to selected items in popover - return string or array of class names */
|
|
@@ -301,6 +336,21 @@ declare interface MultiSelectConfig<T = any> {
|
|
|
301
336
|
isAddNewAllowed?: boolean;
|
|
302
337
|
/** Show count badge next to toggle icon (internal: isCounterShown) */
|
|
303
338
|
isCounterShown?: boolean;
|
|
339
|
+
/**
|
|
340
|
+
* Show an inline clear (✕) button inside the input that wipes the whole selection.
|
|
341
|
+
* Appears only while something is selected (and the control is enabled). Clicking it
|
|
342
|
+
* clears the selection and any search text, fires `change`, and refocuses the input.
|
|
343
|
+
* Default `false`. (internal: isClearShown)
|
|
344
|
+
*/
|
|
345
|
+
isClearShown?: boolean;
|
|
346
|
+
/**
|
|
347
|
+
* Allow the selected-items popover to open. Defaults to `true`. The popover is triggered by
|
|
348
|
+
* the count / compact / "+X more" badge and by the in-input counter (`isCounterShown`). Set
|
|
349
|
+
* to `false` when you render your own selection UI (e.g. an external container fed by the
|
|
350
|
+
* `change` event) — the badge and counter still show the count, but clicking them does nothing
|
|
351
|
+
* and they lose the pointer cursor. (internal: isSelectedPopoverEnabled)
|
|
352
|
+
*/
|
|
353
|
+
isSelectedPopoverEnabled?: boolean;
|
|
304
354
|
/**
|
|
305
355
|
* Make badges display each option's `fullTitleMember` / `getFullTitleCallback` value
|
|
306
356
|
* instead of its display value. Falls back to the display value for options without a
|
|
@@ -581,6 +631,15 @@ export declare class MultiSelectElement<T = any> extends BlissElement<MultiSelec
|
|
|
581
631
|
* set before the dropdown can open.
|
|
582
632
|
*/
|
|
583
633
|
protected environmentChanged(env: EnvironmentSnapshot): void;
|
|
634
|
+
/**
|
|
635
|
+
* This element's own border box changed (core §12.9 `resized`). Overriding the
|
|
636
|
+
* hook opts us into a shared page-wide ResizeObserver, subscribed on connect and
|
|
637
|
+
* dropped on disconnect. Unlike `environmentChanged`/`viewportChanged` (the
|
|
638
|
+
* WINDOW), this is our OWN box — a picker in a 400px sidebar on a 2560px monitor
|
|
639
|
+
* reflows on its width, not the viewport's. We only act when `collapse-badges-
|
|
640
|
+
* below` is set; otherwise it's a cheap no-op.
|
|
641
|
+
*/
|
|
642
|
+
protected resized({ width }: ElementSize): void;
|
|
584
643
|
/** Form field name (mirrors the `name` attribute → `formFieldId`). */
|
|
585
644
|
get name(): string | null;
|
|
586
645
|
set name(value: string | null);
|
|
@@ -601,6 +660,15 @@ export declare class MultiSelectElement<T = any> extends BlissElement<MultiSelec
|
|
|
601
660
|
showMessage(content: string | HTMLElement, opts?: MessageOptions): void;
|
|
602
661
|
/** Dismiss the transient message shown by {@link showMessage}, if any. */
|
|
603
662
|
hideMessage(): void;
|
|
663
|
+
/** Open the dropdown. */
|
|
664
|
+
open(): void;
|
|
665
|
+
/** Close the dropdown. */
|
|
666
|
+
close(): void;
|
|
667
|
+
/** Toggle the dropdown open/closed. */
|
|
668
|
+
toggle(): void;
|
|
669
|
+
/** Whether the dropdown is currently open. Assigning opens/closes it. */
|
|
670
|
+
get isOpen(): boolean;
|
|
671
|
+
set isOpen(value: boolean);
|
|
604
672
|
destroy(): void;
|
|
605
673
|
}
|
|
606
674
|
|
|
@@ -732,6 +800,10 @@ export declare interface MultiSelectOptions extends MultiSelectConfig<MultiSelec
|
|
|
732
800
|
*/
|
|
733
801
|
declare type NodeId = string | number;
|
|
734
802
|
|
|
803
|
+
export { observeEnvironment }
|
|
804
|
+
|
|
805
|
+
export { observeViewport }
|
|
806
|
+
|
|
735
807
|
/**
|
|
736
808
|
* Context provided to renderOptionContentCallback.
|
|
737
809
|
*
|
|
@@ -783,6 +855,10 @@ export declare const OPTIONS_FORMATS: readonly ["json", "csv", "plain"];
|
|
|
783
855
|
|
|
784
856
|
export declare type OptionsFormat = (typeof OPTIONS_FORMATS)[number];
|
|
785
857
|
|
|
858
|
+
export { Orientation }
|
|
859
|
+
|
|
860
|
+
export { OS }
|
|
861
|
+
|
|
786
862
|
export declare interface ParsedOptions {
|
|
787
863
|
/** Parsed options: objects for `json`/`csv`, `[value, label]` tuples for `plain`. */
|
|
788
864
|
options: unknown[];
|
|
@@ -809,6 +885,8 @@ declare interface ParseOptionsOptions {
|
|
|
809
885
|
rowSplitter?: string;
|
|
810
886
|
}
|
|
811
887
|
|
|
888
|
+
export { PointerType }
|
|
889
|
+
|
|
812
890
|
/**
|
|
813
891
|
* Search input display mode
|
|
814
892
|
*/
|
|
@@ -831,6 +909,8 @@ export declare function setCategoryLevel(category: string, level: LogLevelDesc):
|
|
|
831
909
|
/** Set the same level on every category. */
|
|
832
910
|
export declare function setLogLevel(level: LogLevelDesc): void;
|
|
833
911
|
|
|
912
|
+
export { TABLET_MIN_SHORT_SIDE }
|
|
913
|
+
|
|
834
914
|
export declare const uiLogger: Logger;
|
|
835
915
|
|
|
836
916
|
/**
|
|
@@ -839,10 +919,10 @@ export declare const uiLogger: Logger;
|
|
|
839
919
|
export declare type ValueFormat = 'json' | 'csv' | 'array';
|
|
840
920
|
|
|
841
921
|
export declare class WebMultiSelect<T = any> {
|
|
922
|
+
#private;
|
|
842
923
|
private element;
|
|
843
924
|
private instanceId;
|
|
844
925
|
private options;
|
|
845
|
-
private isOpen;
|
|
846
926
|
private selectedValues;
|
|
847
927
|
private selectedOptions;
|
|
848
928
|
private allOptions;
|
|
@@ -867,6 +947,7 @@ export declare class WebMultiSelect<T = any> {
|
|
|
867
947
|
private justClosedViaClick;
|
|
868
948
|
private justOpenedViaClick;
|
|
869
949
|
private positioningDriftWarned;
|
|
950
|
+
private fullscreenContainingBlockWarned;
|
|
870
951
|
private presentationMode;
|
|
871
952
|
private fullscreenHeader;
|
|
872
953
|
private fullscreenSearchInput;
|
|
@@ -897,10 +978,12 @@ export declare class WebMultiSelect<T = any> {
|
|
|
897
978
|
private selectedPopoverVirtualScroll;
|
|
898
979
|
private selectedPopoverContainer;
|
|
899
980
|
private input;
|
|
981
|
+
private inputWrapper;
|
|
900
982
|
private dropdown;
|
|
901
983
|
private dropdownInner;
|
|
902
984
|
private badgesContainer;
|
|
903
985
|
private counter;
|
|
986
|
+
private clearButton;
|
|
904
987
|
private hint?;
|
|
905
988
|
private selectedPopover;
|
|
906
989
|
private documentKeydownHandler;
|
|
@@ -1048,6 +1131,24 @@ export declare class WebMultiSelect<T = any> {
|
|
|
1048
1131
|
*/
|
|
1049
1132
|
private hasGroups;
|
|
1050
1133
|
private renderDropdown;
|
|
1134
|
+
/**
|
|
1135
|
+
* Round the OUTER corners of the row at the very top and the row at the very
|
|
1136
|
+
* bottom of the list so a focused/selected row's background — and crucially its
|
|
1137
|
+
* focus `outline`, which traces the row's OWN box and follows its border-radius
|
|
1138
|
+
* but NOT an ancestor's overflow clip — curves with the panel instead of poking a
|
|
1139
|
+
* square corner past it.
|
|
1140
|
+
*
|
|
1141
|
+
* Keyed off DOM order, not option index, so grouping works: when grouped the top
|
|
1142
|
+
* row is a `.ms__group-label` (not the first option, which sits below it), so we
|
|
1143
|
+
* round whichever element is physically first/last. VirtualScroll renders rows in
|
|
1144
|
+
* index order into one innerHTML, so DOM order == visual order there too.
|
|
1145
|
+
*
|
|
1146
|
+
* Logical corners (`border-start-*` / `border-end-*`) so it mirrors in RTL. A
|
|
1147
|
+
* space-taking vertical scrollbar occupies the inline-END gutter, so the END-side
|
|
1148
|
+
* corners stay square then (the panel's rounded end corner is the scrollbar
|
|
1149
|
+
* track's). The radius is 0 in the fullscreen sheet (that scope zeroes the var).
|
|
1150
|
+
*/
|
|
1151
|
+
private applyEdgeOptionRadii;
|
|
1051
1152
|
/**
|
|
1052
1153
|
* Render dropdown with virtual scrolling
|
|
1053
1154
|
*/
|
|
@@ -1174,14 +1275,33 @@ export declare class WebMultiSelect<T = any> {
|
|
|
1174
1275
|
private deselectOption;
|
|
1175
1276
|
private selectAll;
|
|
1176
1277
|
clearAll(): void;
|
|
1278
|
+
/**
|
|
1279
|
+
* Inline clear (✕) handler: wipe the whole selection and any search text, then
|
|
1280
|
+
* restore focus to the input. clearAll() → commit() → renderBadges() already
|
|
1281
|
+
* refreshes this button's visibility (it hides once nothing is selected).
|
|
1282
|
+
*/
|
|
1283
|
+
private clearClick;
|
|
1284
|
+
/**
|
|
1285
|
+
* Show the inline clear (✕) only when it is opted in (isClearShown), something is
|
|
1286
|
+
* selected, and the control is enabled. Called from renderBadges() so it tracks
|
|
1287
|
+
* every selection change. Uses inline display like the counter / fullscreen clear.
|
|
1288
|
+
*/
|
|
1289
|
+
private updateClearButton;
|
|
1177
1290
|
/**
|
|
1178
1291
|
* Re-render and fire callbacks after a selection state change.
|
|
1179
1292
|
* `added` / `removed` drive per-item select/deselect callbacks.
|
|
1180
1293
|
* `onChange` fires once if anything actually changed.
|
|
1181
1294
|
*/
|
|
1182
1295
|
private commit;
|
|
1183
|
-
|
|
1184
|
-
|
|
1296
|
+
/** Open the dropdown (no-op if already open, or if there is nothing to show). */
|
|
1297
|
+
open(): void;
|
|
1298
|
+
/** Close the dropdown (no-op if already closed). */
|
|
1299
|
+
close(): void;
|
|
1300
|
+
/** Toggle the dropdown open/closed. */
|
|
1301
|
+
toggle(): void;
|
|
1302
|
+
/** Whether the dropdown is currently open. Assigning opens/closes it. */
|
|
1303
|
+
get isOpen(): boolean;
|
|
1304
|
+
set isOpen(value: boolean);
|
|
1185
1305
|
/**
|
|
1186
1306
|
* Anchor a floating panel (dropdown or selected-items popover) below/above the input with
|
|
1187
1307
|
* placement-locking and width-syncing. Returns the `autoUpdate` cleanup.
|
|
@@ -1199,6 +1319,23 @@ export declare class WebMultiSelect<T = any> {
|
|
|
1199
1319
|
* owns the measurement + culprit-finding + CB-CSS diagnostic (`detectFixedDrift`).
|
|
1200
1320
|
*/
|
|
1201
1321
|
private warnDrift;
|
|
1322
|
+
/**
|
|
1323
|
+
* Fullscreen counterpart of {@link warnDrift}. The overlay is a `position: fixed`,
|
|
1324
|
+
* full-viewport sheet — but if an ancestor of the host establishes a fixed-positioning
|
|
1325
|
+
* containing block (`transform` / `perspective` / `filter` / `backdrop-filter` / a
|
|
1326
|
+
* qualifying `will-change`), the browser anchors the sheet to THAT ancestor's box instead
|
|
1327
|
+
* of the viewport, so it no longer covers the screen (offset, clipped, or mis-sized).
|
|
1328
|
+
*
|
|
1329
|
+
* Unlike the floating path — where core measures real drift after positioning — nothing
|
|
1330
|
+
* anchors the sheet, so there's no drift to observe. Instead we ask core's shared
|
|
1331
|
+
* heuristic (`getFixedPositionOffsetParent`, the same one that feeds the floating platform)
|
|
1332
|
+
* whether the sheet's true offset parent is the viewport (`window`) or an element. An
|
|
1333
|
+
* element means it WILL be mis-anchored; warn once, pointing at the culprit. We only check
|
|
1334
|
+
* the reliably-honoured properties core lists (transform family) — `contain` /
|
|
1335
|
+
* `container-type` are omitted because browsers don't honour them for fixed positioning,
|
|
1336
|
+
* so they don't actually break the sheet.
|
|
1337
|
+
*/
|
|
1338
|
+
private warnFullscreenContainingBlock;
|
|
1202
1339
|
private positionDropdown;
|
|
1203
1340
|
/**
|
|
1204
1341
|
* Switch how the open panels are presented. 'floating' anchors them to the input
|
|
@@ -1364,6 +1501,20 @@ export declare class WebMultiSelect<T = any> {
|
|
|
1364
1501
|
private hideSelectedPopover;
|
|
1365
1502
|
private renderSelectedPopover;
|
|
1366
1503
|
private renderSelectedPopoverVirtual;
|
|
1504
|
+
/**
|
|
1505
|
+
* Coerce a render-callback result to an HTML string. Callbacks may return a string
|
|
1506
|
+
* (HTML) or an HTMLElement (serialized via `outerHTML`); null/undefined → ''. Used by
|
|
1507
|
+
* every "return string | HTMLElement" content callback that builds into an innerHTML
|
|
1508
|
+
* string. (DOM sinks that hold a live node instead — the reveal/message panels — use
|
|
1509
|
+
* textContent/appendChild directly and intentionally don't go through here.)
|
|
1510
|
+
*/
|
|
1511
|
+
private toHtml;
|
|
1512
|
+
/**
|
|
1513
|
+
* Normalize a class callback result (`string | string[] | null`) to a single
|
|
1514
|
+
* space-joined string with falsy entries dropped — e.g. `['a', '', 'b'] → "a b"`,
|
|
1515
|
+
* `null → ""`. Callers add their own leading space / base class as needed.
|
|
1516
|
+
*/
|
|
1517
|
+
private classSuffix;
|
|
1367
1518
|
/**
|
|
1368
1519
|
* Render a removable badge for a selected option (used by the badges/partial display modes
|
|
1369
1520
|
* and by the selected-items popover).
|