@keenmate/web-multiselect 1.0.0-rc02 → 1.0.0-rc04

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.
@@ -0,0 +1,142 @@
1
+ // ==============================================================================
2
+ // RTL (Right-to-Left) SUPPORT
3
+ // ==============================================================================
4
+ // Styles for RTL languages (Arabic, Hebrew, etc.)
5
+ // Applied when .ml--rtl class is present
6
+
7
+ @use 'variables' as *;
8
+
9
+ // ==============================================================================
10
+ // INPUT & TOGGLE ICON
11
+ // ==============================================================================
12
+
13
+ .ml--rtl {
14
+ .ml__input-wrapper {
15
+ direction: rtl;
16
+ }
17
+
18
+ .ml__input {
19
+ text-align: right;
20
+ padding-left: var(--ml-input-padding-right, $ml-input-padding-right);
21
+ padding-right: var(--ml-input-padding-h, $ml-input-padding-h);
22
+ }
23
+
24
+ // Move toggle icon to left side
25
+ .ml__toggle {
26
+ left: var(--ml-toggle-right, $ml-toggle-right) !important;
27
+ right: auto !important;
28
+ }
29
+
30
+ // Move count badge to left side
31
+ .ml__count-badge {
32
+ left: var(--ml-count-badge-offset, $ml-count-badge-offset) !important;
33
+ right: auto !important;
34
+ }
35
+
36
+ // ==============================================================================
37
+ // DROPDOWN OPTIONS
38
+ // ==============================================================================
39
+
40
+ .ml__dropdown {
41
+ direction: rtl;
42
+ text-align: right;
43
+ }
44
+
45
+ // Checkbox on right side
46
+ .ml__option {
47
+ flex-direction: row-reverse;
48
+ }
49
+
50
+ .ml__checkbox {
51
+ margin-left: var(--ml-spacing-sm, $ml-spacing-sm);
52
+ margin-right: 0;
53
+ }
54
+
55
+ .ml__option-content {
56
+ text-align: right;
57
+ }
58
+
59
+ .ml__option-icon {
60
+ margin-left: var(--ml-spacing-xs, $ml-spacing-xs);
61
+ margin-right: 0;
62
+ }
63
+
64
+ // ==============================================================================
65
+ // PILLS LAYOUT
66
+ // ==============================================================================
67
+
68
+ .ml__pills {
69
+ direction: rtl;
70
+ }
71
+
72
+ // Pills flow right-to-left
73
+ .ml__pill {
74
+ flex-direction: row-reverse;
75
+ }
76
+
77
+ // Remove button on left side of pill
78
+ .ml__pill-remove {
79
+ border-radius: var(--ml-pill-remove-border-radius-rtl, $ml-pill-border-radius) 0 0 var(--ml-pill-remove-border-radius-rtl, $ml-pill-border-radius);
80
+ border-left: var(--ml-pill-remove-border, $ml-pill-remove-border);
81
+ border-right: none;
82
+ }
83
+
84
+ // Pill text rounded on right
85
+ .ml__pill-text {
86
+ border-radius: 0 var(--ml-pill-text-border-radius-rtl, $ml-pill-border-radius) var(--ml-pill-text-border-radius-rtl, $ml-pill-border-radius) 0;
87
+ }
88
+
89
+ // ==============================================================================
90
+ // COUNT DISPLAY
91
+ // ==============================================================================
92
+
93
+ .ml__count-display {
94
+ direction: rtl;
95
+ }
96
+
97
+ .ml__count-badge-wrapper {
98
+ flex-direction: row-reverse;
99
+ }
100
+
101
+ // ==============================================================================
102
+ // SELECTED POPOVER
103
+ // ==============================================================================
104
+
105
+ .ml__selected-popover {
106
+ direction: rtl;
107
+ text-align: right;
108
+ }
109
+
110
+ // ==============================================================================
111
+ // ACTIONS
112
+ // ==============================================================================
113
+
114
+ .ml__actions {
115
+ direction: rtl;
116
+ }
117
+
118
+ // ==============================================================================
119
+ // GROUPS
120
+ // ==============================================================================
121
+
122
+ .ml__group-label {
123
+ text-align: right;
124
+ }
125
+
126
+ // ==============================================================================
127
+ // EMPTY STATE
128
+ // ==============================================================================
129
+
130
+ .ml__empty {
131
+ text-align: right;
132
+ }
133
+
134
+ // ==============================================================================
135
+ // HINT
136
+ // ==============================================================================
137
+
138
+ .ml__hint {
139
+ direction: rtl;
140
+ text-align: right;
141
+ }
142
+ }
@@ -330,8 +330,8 @@ $ml-pill-gap: $ml-spacing-sm !default;
330
330
  $ml-pills-gap: $ml-pill-gap !default;
331
331
  $ml-pills-margin-bottom: $ml-spacing-sm !default;
332
332
  $ml-pills-margin-top: $ml-spacing-sm !default;
333
- $ml-pills-margin-left: $ml-spacing-sm !default;
334
- $ml-pills-margin-right: $ml-spacing-sm !default;
333
+ $ml-pills-margin-left: $ml-spacing-xs !default;
334
+ $ml-pills-margin-right: $ml-spacing-xs !default;
335
335
 
336
336
  // Count Display
337
337
  // ==============================================================================
@@ -10,6 +10,7 @@
10
10
  // - _options.scss : Options list, groups, checkbox, content, states
11
11
  // - _pills-display.scss : Pills, count display, individual pills
12
12
  // - _tooltips-popover.scss: Pill tooltips + selected items popover
13
+ // - _rtl.scss : RTL (Right-to-Left) language support
13
14
  // - _modifiers.scss : Size variants + state modifiers
14
15
  // - _debug.scss : Debug information panel
15
16
 
@@ -20,5 +21,6 @@
20
21
  @use 'options';
21
22
  @use 'pills-display';
22
23
  @use 'tooltips-popover';
24
+ @use 'rtl';
23
25
  @use 'modifiers';
24
26
  @use 'debug';
package/dist/index.d.ts DELETED
@@ -1,26 +0,0 @@
1
- import './scss/main.scss';
2
- import { MultiSelectElement } from './web-component';
3
- export { MultiSelectElement };
4
- export { PureMultiSelect } from './multiselect';
5
- export type { MultiSelectOption, MultiSelectOptions, MultiSelectEventDetail, PillsDisplayMode, PillsPosition, PillsThresholdMode, SearchInputMode, ValueFormat } from './types';
6
- import './web-component';
7
- export interface GlobalMultiSelectAPI {
8
- version: () => string;
9
- config: {
10
- name: string;
11
- version: string;
12
- author: string;
13
- license: string;
14
- repository: string;
15
- homepage: string;
16
- };
17
- register: () => void;
18
- getInstances: () => HTMLElement[];
19
- }
20
- declare global {
21
- interface Window {
22
- keenmate?: {
23
- multiselect?: GlobalMultiSelectAPI;
24
- };
25
- }
26
- }
@@ -1,117 +0,0 @@
1
- /**
2
- * Pure Admin - MultiSelect with Typeahead
3
- * Comprehensive multiselect component with rich content support and floating hints
4
- */
5
- import type { MultiSelectConfig } from './types';
6
- export declare class PureMultiSelect<T = any> {
7
- private element;
8
- private instanceId;
9
- private options;
10
- private isOpen;
11
- private selectedValues;
12
- private selectedOptions;
13
- private allOptions;
14
- private filteredOptions;
15
- private hiddenInputs;
16
- private focusedIndex;
17
- private searchTerm;
18
- private isLoading;
19
- private showSelectedPopover;
20
- private selectedPopoverPlacement;
21
- private dropdownPlacement;
22
- private dropdownCleanup;
23
- private hintCleanup;
24
- private selectedPopoverCleanup;
25
- private pillTooltips;
26
- private pillTooltipCleanups;
27
- private input;
28
- private dropdown;
29
- private pillsContainer;
30
- private countBadge;
31
- private hint?;
32
- private selectedPopover;
33
- /**
34
- * Extract value/ID from item
35
- * Precedence: tuple[0] -> valueMember -> getValueCallback -> '[N/A]'
36
- */
37
- private getItemValue;
38
- /**
39
- * Extract display value from item
40
- * Precedence: tuple[1] -> displayValueMember -> getDisplayValueCallback -> '[N/A]'
41
- */
42
- private getItemDisplayValue;
43
- /**
44
- * Extract search value from item
45
- * Precedence: searchValueMember -> getSearchValueCallback -> displayValue
46
- */
47
- private getItemSearchValue;
48
- /**
49
- * Extract icon from item
50
- */
51
- private getItemIcon;
52
- /**
53
- * Extract subtitle from item
54
- */
55
- private getItemSubtitle;
56
- /**
57
- * Extract group from item
58
- */
59
- private getItemGroup;
60
- /**
61
- * Extract disabled state from item
62
- */
63
- private getItemDisabled;
64
- constructor(element: HTMLElement, options?: Partial<MultiSelectConfig<T>>);
65
- private init;
66
- private parseOptions;
67
- private buildHTML;
68
- private renderDropdown;
69
- private renderOption;
70
- private highlightMatch;
71
- private groupOptions;
72
- private renderPills;
73
- private attachEvents;
74
- private handleSearch;
75
- private handleKeydown;
76
- private handleDropdownClick;
77
- private handlePillClick;
78
- private handleClickOutside;
79
- private focusNext;
80
- private focusPrevious;
81
- private focusFirst;
82
- private focusLast;
83
- private focusPageUp;
84
- private focusPageDown;
85
- private scrollToFocused;
86
- private toggleOption;
87
- private handleAddNew;
88
- private selectOption;
89
- private deselectOption;
90
- private selectAll;
91
- private clearAll;
92
- private open;
93
- private close;
94
- private positionDropdown;
95
- private positionHint;
96
- private parseInitialSelection;
97
- private toggleSelectedPopover;
98
- private showPopover;
99
- private hideSelectedPopover;
100
- private renderSelectedPopover;
101
- private handleSelectedPopoverClick;
102
- private positionSelectedPopover;
103
- private updateHiddenInput;
104
- private getFormValue;
105
- getSelected(): T[];
106
- setSelected(values: (string | number)[]): void;
107
- get selectedItem(): T | null;
108
- get selectedValue(): string | number | (string | number)[] | null;
109
- getValue(): string | number | (string | number)[] | null;
110
- private attachPillTooltips;
111
- private createTooltipForElement;
112
- private createRemoveButtonTooltip;
113
- private positionPillTooltip;
114
- private cleanupPillTooltip;
115
- private destroyAllPillTooltips;
116
- destroy(): void;
117
- }
package/dist/types.d.ts DELETED
@@ -1,187 +0,0 @@
1
- /**
2
- * Type definitions for the MultiSelect component
3
- */
4
- import type { Placement } from '@floating-ui/dom';
5
- /**
6
- * Position of the pills container relative to the input
7
- */
8
- export type PillsPosition = 'top' | 'bottom' | 'left' | 'right';
9
- /**
10
- * Search input display mode
11
- */
12
- export type SearchInputMode = 'normal' | 'readonly' | 'hidden';
13
- /**
14
- * Value format for serialization (forms and callbacks)
15
- */
16
- export type ValueFormat = 'json' | 'csv' | 'array';
17
- /**
18
- * Threshold behavior mode when pills exceed threshold
19
- */
20
- export type PillsThresholdMode = 'count' | 'partial';
21
- /**
22
- * Display mode for selected items (pills area)
23
- */
24
- export type PillsDisplayMode = 'pills' | 'count' | 'compact' | 'partial';
25
- /**
26
- * Support both object arrays and [key, value] tuples
27
- */
28
- export type MultiSelectDataItem<T> = T | [string | number, string];
29
- /**
30
- * Generic configuration options for the MultiSelect component
31
- * @template T The type of data items
32
- */
33
- export interface MultiSelectConfig<T = any> {
34
- /** Options array - can be objects or [key, value] tuples */
35
- options?: T[];
36
- /** Member property name for value/ID extraction */
37
- valueMember?: string;
38
- /** Callback to extract value/ID from item */
39
- getValueCallback?: (item: T) => string | number;
40
- /** Member property name for display value extraction */
41
- displayValueMember?: string;
42
- /** Callback to extract display value from item */
43
- getDisplayValueCallback?: (item: T) => string;
44
- /** Member property name for search value extraction */
45
- searchValueMember?: string;
46
- /** Callback to extract search value from item */
47
- getSearchValueCallback?: (item: T) => string;
48
- /** Member property name for icon extraction */
49
- iconMember?: string;
50
- /** Callback to extract icon from item */
51
- getIconCallback?: (item: T) => string;
52
- /** Member property name for subtitle extraction */
53
- subtitleMember?: string;
54
- /** Callback to extract subtitle from item */
55
- getSubtitleCallback?: (item: T) => string;
56
- /** Member property name for group extraction */
57
- groupMember?: string;
58
- /** Callback to extract group from item */
59
- getGroupCallback?: (item: T) => string;
60
- /** Member property name for disabled state extraction */
61
- disabledMember?: string;
62
- /** Callback to extract disabled state from item */
63
- getDisabledCallback?: (item: T) => boolean;
64
- /** HTML form field ID/name for hidden input */
65
- formFieldId?: string;
66
- /** Format for value serialization (forms and callbacks) */
67
- valueFormat?: ValueFormat;
68
- /** Custom callback to format value */
69
- getValueFormatCallback?: (selectedValues: (string | number)[]) => string;
70
- /** Allow multiple selections (internal: isMultipleEnabled) */
71
- isMultipleEnabled?: boolean;
72
- /** Enable search/filtering (internal: isSearchEnabled) */
73
- isSearchEnabled?: boolean;
74
- /** Allow grouping of options (internal: isGroupsAllowed) */
75
- isGroupsAllowed?: boolean;
76
- /** Show 'Select All' button (internal: isSelectAllAllowed) */
77
- isSelectAllAllowed?: boolean;
78
- /** Show 'Clear All' button (internal: isClearAllAllowed) */
79
- isClearAllAllowed?: boolean;
80
- /** Show checkboxes next to options (internal: isCheckboxesShown) */
81
- isCheckboxesShown?: boolean;
82
- /** Keep Select All/Clear All buttons fixed at top while scrolling (internal: isActionsSticky) */
83
- isActionsSticky?: boolean;
84
- /** Close dropdown after selecting an option (internal: isCloseOnSelect) */
85
- isCloseOnSelect?: boolean;
86
- /** Lock dropdown placement after first open (internal: isPlacementLocked) */
87
- isPlacementLocked?: boolean;
88
- /** Allow adding new options not in the list (internal: isAddNewAllowed) */
89
- isAddNewAllowed?: boolean;
90
- /** Show count badge next to toggle icon (internal: isCountBadgeShown) */
91
- isCountBadgeShown?: boolean;
92
- /** Hint text shown above the input when focused */
93
- searchHint?: string;
94
- /** Placeholder text for the search input */
95
- searchPlaceholder?: string;
96
- /** Minimum width for the dropdown (e.g., '20rem', '300px') */
97
- dropdownMinWidth?: string | null;
98
- /** Display mode for selected items in pills area */
99
- pillsDisplayMode?: PillsDisplayMode;
100
- /** Position of pills container */
101
- pillsPosition?: PillsPosition;
102
- /** Threshold behavior mode: 'count' shows count badge, 'partial' shows limited pills + more badge */
103
- pillsThresholdMode?: PillsThresholdMode;
104
- /** Maximum height for dropdown */
105
- maxHeight?: string;
106
- /** Message shown when no results found */
107
- emptyMessage?: string;
108
- /** Message shown while loading async data */
109
- loadingMessage?: string;
110
- /** Search input display mode */
111
- searchInputMode?: SearchInputMode;
112
- /** Auto-switch from pills to count when threshold is exceeded */
113
- pillsThreshold?: number | null;
114
- /** Maximum number of pills to show in partial mode (used with thresholdMode='partial') */
115
- pillsMaxVisible?: number | null;
116
- /** Minimum search length before loading data */
117
- minSearchLength?: number;
118
- /** Async function to load data: (searchTerm) => Promise<options[]> */
119
- searchCallback?: ((searchTerm: string) => Promise<T[]>) | null;
120
- /** Callback to add a new option when isAddNewAllowed is true */
121
- addNewCallback?: ((value: string) => T | Promise<T>) | null;
122
- /** Callback when an option is selected */
123
- selectCallback?: ((option: T) => void) | null;
124
- /** Callback when an option is deselected */
125
- deselectCallback?: ((option: T) => void) | null;
126
- /** Callback when selection changes */
127
- changeCallback?: ((selectedOptions: T[]) => void) | null;
128
- /** Callback to format count pill text (for i18n/pluralization). When moreCount is provided, it's for the "+X more" badge in partial mode. */
129
- getCountPillCallback?: ((count: number, moreCount?: number) => string) | null;
130
- /** Enable tooltips on selected item pills (internal: isPillTooltipsEnabled) */
131
- isPillTooltipsEnabled?: boolean;
132
- /** Callback to generate custom tooltip content for a pill */
133
- getPillTooltipCallback?: ((item: T) => string | HTMLElement) | null;
134
- /** Tooltip placement relative to pill */
135
- pillTooltipPlacement?: Placement;
136
- /** Delay before showing tooltip in milliseconds */
137
- pillTooltipDelay?: number;
138
- /** Offset distance for tooltip in pixels */
139
- pillTooltipOffset?: number;
140
- /** Container element for dropdown/hint/popover (for Shadow DOM support) */
141
- container?: HTMLElement | null;
142
- /** Host element for appending hidden inputs (for form integration with shadow DOM) */
143
- hostElement?: HTMLElement;
144
- }
145
- /**
146
- * Event detail structure for multiselect events
147
- * @template T The type of data items
148
- */
149
- export interface MultiSelectEventDetail<T = any> {
150
- /** Currently selected options */
151
- selectedOptions: T[];
152
- /** Selected values array */
153
- selectedValues: (string | number)[];
154
- /** The option that triggered the event (for select/deselect) */
155
- option?: T;
156
- }
157
- /**
158
- * Legacy interface for backward reference
159
- * Note: New code should use generic types with member/callback properties
160
- * @deprecated Use generic types with valueMember/displayValueMember instead
161
- */
162
- export interface MultiSelectOption {
163
- /** Unique identifier for the option */
164
- value: string;
165
- /** Display label */
166
- label: string;
167
- /** Optional icon or emoji */
168
- icon?: string;
169
- /** Optional subtitle/description */
170
- subtitle?: string;
171
- /** Optional group name */
172
- group?: string;
173
- /** Whether the option is disabled */
174
- disabled?: boolean;
175
- }
176
- /**
177
- * Legacy options interface
178
- * @deprecated Use MultiSelectConfig<T> instead
179
- */
180
- export interface MultiSelectOptions extends MultiSelectConfig<MultiSelectOption> {
181
- options?: MultiSelectOption[];
182
- searchCallback?: ((searchTerm: string) => Promise<MultiSelectOption[]>) | null;
183
- addNewCallback?: ((value: string) => MultiSelectOption | Promise<MultiSelectOption>) | null;
184
- selectCallback?: ((option: MultiSelectOption) => void) | null;
185
- deselectCallback?: ((option: MultiSelectOption) => void) | null;
186
- changeCallback?: ((selectedOptions: MultiSelectOption[]) => void) | null;
187
- }
@@ -1,103 +0,0 @@
1
- export declare function getAllInstances(): MultiSelectElement[];
2
- export declare class MultiSelectElement<T = any> extends HTMLElement {
3
- private picker?;
4
- private containerElement?;
5
- private shadow;
6
- private _options?;
7
- private _valueMember?;
8
- private _getValueCallback?;
9
- private _displayValueMember?;
10
- private _getDisplayValueCallback?;
11
- private _searchValueMember?;
12
- private _getSearchValueCallback?;
13
- private _iconMember?;
14
- private _getIconCallback?;
15
- private _subtitleMember?;
16
- private _getSubtitleCallback?;
17
- private _groupMember?;
18
- private _getGroupCallback?;
19
- private _disabledMember?;
20
- private _getDisabledCallback?;
21
- private _getValueFormatCallback?;
22
- private _getPillTooltipCallback?;
23
- private _getCountPillCallback?;
24
- private _searchCallback?;
25
- private _addNewCallback?;
26
- private _selectCallback?;
27
- private _deselectCallback?;
28
- private _changeCallback?;
29
- static get observedAttributes(): string[];
30
- constructor();
31
- connectedCallback(): void;
32
- disconnectedCallback(): void;
33
- attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
34
- private render;
35
- private renderDebugInfo;
36
- private updateDebugInfo;
37
- private initializePicker;
38
- private reinitialize;
39
- get options(): T[] | undefined;
40
- set options(value: T[] | undefined);
41
- set valueMember(value: string | null);
42
- get valueMember(): string | null;
43
- set displayValueMember(value: string | null);
44
- get displayValueMember(): string | null;
45
- set searchValueMember(value: string | null);
46
- get searchValueMember(): string | null;
47
- set iconMember(value: string | null);
48
- get iconMember(): string | null;
49
- set subtitleMember(value: string | null);
50
- get subtitleMember(): string | null;
51
- set groupMember(value: string | null);
52
- get groupMember(): string | null;
53
- set disabledMember(value: string | null);
54
- get disabledMember(): string | null;
55
- set getValueCallback(callback: ((item: T) => string | number) | undefined);
56
- get getValueCallback(): ((item: T) => string | number) | undefined;
57
- set getDisplayValueCallback(callback: ((item: T) => string) | undefined);
58
- get getDisplayValueCallback(): ((item: T) => string) | undefined;
59
- set getSearchValueCallback(callback: ((item: T) => string) | undefined);
60
- get getSearchValueCallback(): ((item: T) => string) | undefined;
61
- set getIconCallback(callback: ((item: T) => string) | undefined);
62
- get getIconCallback(): ((item: T) => string) | undefined;
63
- set getSubtitleCallback(callback: ((item: T) => string) | undefined);
64
- get getSubtitleCallback(): ((item: T) => string) | undefined;
65
- set getGroupCallback(callback: ((item: T) => string) | undefined);
66
- get getGroupCallback(): ((item: T) => string) | undefined;
67
- set getDisabledCallback(callback: ((item: T) => boolean) | undefined);
68
- get getDisabledCallback(): ((item: T) => boolean) | undefined;
69
- set name(value: string | null);
70
- get name(): string | null;
71
- set valueFormat(value: 'json' | 'csv' | 'array' | null);
72
- get valueFormat(): string | null;
73
- set getValueFormatCallback(callback: ((values: (string | number)[]) => string) | undefined);
74
- get getValueFormatCallback(): ((values: (string | number)[]) => string) | undefined;
75
- set thresholdMode(value: 'count' | 'partial' | null);
76
- get thresholdMode(): string | null;
77
- set pillsMaxVisible(value: number | null);
78
- get pillsMaxVisible(): number | null;
79
- set enablePillTooltips(value: boolean);
80
- get enablePillTooltips(): boolean;
81
- set pillTooltipPlacement(value: string | null);
82
- get pillTooltipPlacement(): string | null;
83
- set getPillTooltipCallback(callback: ((item: T) => string | HTMLElement) | undefined);
84
- get getPillTooltipCallback(): ((item: T) => string | HTMLElement) | undefined;
85
- set getCountPillCallback(callback: ((count: number, moreCount?: number) => string) | undefined);
86
- get getCountPillCallback(): ((count: number, moreCount?: number) => string) | undefined;
87
- get searchCallback(): ((searchTerm: string) => Promise<T[]>) | undefined;
88
- set searchCallback(callback: ((searchTerm: string) => Promise<T[]>) | undefined);
89
- get addNewCallback(): ((value: string) => T | Promise<T>) | undefined;
90
- set addNewCallback(callback: ((value: string) => T | Promise<T>) | undefined);
91
- get selectCallback(): ((option: T) => void) | undefined;
92
- set selectCallback(callback: ((option: T) => void) | undefined);
93
- get deselectCallback(): ((option: T) => void) | undefined;
94
- set deselectCallback(callback: ((option: T) => void) | undefined);
95
- get changeCallback(): ((selectedOptions: T[]) => void) | undefined;
96
- set changeCallback(callback: ((selectedOptions: T[]) => void) | undefined);
97
- get selectedValue(): string | number | (string | number)[] | null;
98
- get selectedItem(): T | null;
99
- getSelected(): T[];
100
- setSelected(values: (string | number)[]): void;
101
- getValue(): string | number | (string | number)[] | null;
102
- destroy(): void;
103
- }