@keenmate/web-multiselect 1.11.0 → 1.12.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.
@@ -0,0 +1,108 @@
1
+ /* ==============================================================================
2
+ COUNT-DISPLAY MODE
3
+ ==============================================================================
4
+ Alternative selection-summary UI: a single counter pill ("3 selected") with
5
+ an inline clear button, instead of one badge per item. Activated via the
6
+ `badges-display-mode="count"` attribute. The clickable badge that opens the
7
+ selected-items popover lives in badges.css.
8
+ */
9
+
10
+ /* ==============================================================================
11
+ COUNT-DISPLAY CONTAINER
12
+ ============================================================================== */
13
+
14
+ .ms__count-display {
15
+ display: flex;
16
+ align-items: center;
17
+ }
18
+
19
+ .ms__count-display:empty {
20
+ display: none;
21
+ }
22
+
23
+ /* Position variants */
24
+ .ms__count-display--bottom {
25
+ margin-top: var(--ms-count-display-margin-bottom);
26
+ }
27
+
28
+ .ms__count-display--top {
29
+ margin-bottom: var(--ms-count-display-margin-top);
30
+ order: var(--ms-order-first); /* Place before multiselect in flex container */
31
+ }
32
+
33
+ .ms__count-display--left {
34
+ order: var(--ms-order-first); /* Place before multiselect */
35
+ margin-right: var(--ms-count-display-margin-left);
36
+ justify-content: flex-start;
37
+ }
38
+
39
+ .ms__count-display--right {
40
+ margin-left: var(--ms-count-display-margin-right);
41
+ justify-content: flex-end;
42
+ }
43
+
44
+ /* ==============================================================================
45
+ COUNTER PILL (text + clear button)
46
+ ============================================================================== */
47
+
48
+ /* Wrapper containing count text and clear button */
49
+ .ms__counter-wrapper {
50
+ display: inline-flex;
51
+ align-items: center;
52
+ gap: var(--ms-counter-wrapper-gap);
53
+ background: var(--ms-counter-wrapper-bg);
54
+ border: var(--ms-counter-wrapper-border);
55
+ border-radius: var(--ms-counter-wrapper-border-radius);
56
+ padding: var(--ms-counter-wrapper-padding);
57
+ transition: all var(--ms-transition-fast) var(--ms-easing-snappy);
58
+ }
59
+
60
+ .ms__counter-wrapper:hover {
61
+ background: var(--ms-counter-wrapper-bg-hover);
62
+ border-color: var(--ms-counter-wrapper-border-color-hover);
63
+ }
64
+
65
+ .ms__count-text {
66
+ display: inline-flex;
67
+ align-items: center;
68
+ background: var(--ms-count-text-bg);
69
+ border: var(--ms-count-text-border);
70
+ padding: 0;
71
+ font-size: var(--ms-count-text-font-size);
72
+ color: var(--ms-count-text-color);
73
+ cursor: pointer;
74
+ transition: color var(--ms-transition-fast) var(--ms-easing-snappy);
75
+ }
76
+
77
+ .ms__count-clear {
78
+ flex-shrink: 0;
79
+ display: flex;
80
+ align-items: center;
81
+ justify-content: center;
82
+ width: var(--ms-count-clear-size);
83
+ height: var(--ms-count-clear-size);
84
+ padding: 0;
85
+ border: none;
86
+ background: var(--ms-count-clear-bg);
87
+ color: var(--ms-count-clear-color);
88
+ font-size: var(--ms-count-clear-font-size);
89
+ line-height: var(--ms-line-height-none);
90
+ cursor: pointer;
91
+ border-radius: var(--ms-count-clear-border-radius);
92
+ transition: all var(--ms-transition-fast) var(--ms-easing-snappy);
93
+ }
94
+
95
+ .ms__count-clear:hover {
96
+ background: var(--ms-count-clear-bg-hover);
97
+ color: var(--ms-count-clear-color-hover);
98
+ }
99
+
100
+ .ms__count-clear::before {
101
+ content: "";
102
+ display: block;
103
+ width: var(--ms-count-clear-icon-size);
104
+ height: var(--ms-count-clear-icon-size);
105
+ background-color: currentColor;
106
+ -webkit-mask: var(--ms-icon-clear) center / contain no-repeat;
107
+ mask: var(--ms-icon-clear) center / contain no-repeat;
108
+ }
@@ -0,0 +1,58 @@
1
+ /* ==============================================================================
2
+ DARK MODE — framework class + per-instance signal handling
3
+ ==============================================================================
4
+ Sets `color-scheme` on the host when the consumer signals dark/light via a
5
+ framework class (signal #4) or a per-instance attribute (signal #5). Every
6
+ `--ms-*` color in variables.css resolves through `light-dark(<light>, <dark>)`,
7
+ so flipping `color-scheme` on the host picks the correct branch without us
8
+ touching any `--base-*` value.
9
+
10
+ Why we don't override `--base-*` here:
11
+ Setting e.g. `--base-input-bg: #1a1a1a` on `:host` shadows the consumer's
12
+ `:root { --base-input-bg: ... }` for resolution inside the shadow root, so
13
+ their themed value (e.g. pure-admin's #163768) would be silently replaced
14
+ by our hardcoded default. Setting `color-scheme` instead leaves the
15
+ consumer's `--base-*` chain intact — they remain the source of truth, and
16
+ we only pick the dark branch of our own fallbacks.
17
+
18
+ Why `color-scheme` on `:host` is fine *here* (but not in variables.css):
19
+ variables.css avoids it because an unconditional declaration would override
20
+ whatever the consumer's <html>/<body>/ancestor set. Here we declare it only
21
+ when the consumer's own signal matches, so we're amplifying their intent
22
+ rather than fighting it. Frameworks that already set `color-scheme`
23
+ alongside their class (Bootstrap 5.3+) get a redundant no-op; frameworks
24
+ that don't (Tailwind `.dark`, hand-rolled toggles) get filled in.
25
+
26
+ Signals handled:
27
+ #4 Framework theme class on an ancestor — `:host-context([data-theme="dark"])`,
28
+ `:host-context([data-bs-theme="dark"])`, `:host-context(.dark)`.
29
+ #5 Per-instance attribute on the host — `:host([data-theme="dark"])`,
30
+ `:host([data-theme="light"])`. Highest specificity, wins over any
31
+ framework class on an ancestor.
32
+
33
+ See [color-scheme.md](BlissFramework guidelines) for the full pattern. */
34
+
35
+ /* DARK — framework class on ancestor (signal #4) */
36
+ :host-context([data-theme="dark"]),
37
+ :host-context([data-bs-theme="dark"]),
38
+ :host-context(.dark) {
39
+ color-scheme: dark;
40
+ }
41
+
42
+ /* LIGHT — framework class on ancestor (signal #4, safety net for
43
+ "force one section back to light on a dark page"). */
44
+ :host-context([data-theme="light"]),
45
+ :host-context([data-bs-theme="light"]),
46
+ :host-context(.light) {
47
+ color-scheme: light;
48
+ }
49
+
50
+ /* DARK — per-instance attribute on the host (signal #5). */
51
+ :host([data-theme="dark"]) {
52
+ color-scheme: dark;
53
+ }
54
+
55
+ /* LIGHT — per-instance attribute on the host (signal #5). */
56
+ :host([data-theme="light"]) {
57
+ color-scheme: light;
58
+ }
@@ -4,45 +4,45 @@
4
4
  Debug information display for development and troubleshooting
5
5
  */
6
6
 
7
- .ms-debug-info {
7
+ .ms__debug-info {
8
8
  margin-top: calc(0.4 * var(--ms-rem));
9
9
  padding: calc(0.4 * var(--ms-rem));
10
- background-color: #f9fafb;
11
- border: 1px solid #e5e7eb;
12
- border-radius: calc(var(--base-border-radius-md, 0.6) * var(--ms-rem));
10
+ background-color: var(--ms-debug-bg);
11
+ border: 1px solid var(--ms-debug-border-color);
12
+ border-radius: var(--ms-debug-border-radius);
13
13
  font-size: calc(1.2 * var(--ms-rem));
14
- color: #111827;
14
+ color: var(--ms-debug-text-color);
15
15
  }
16
16
 
17
- .ms-debug-info details summary {
17
+ .ms__debug-info details summary {
18
18
  cursor: pointer;
19
19
  font-weight: 600;
20
- color: #2563eb;
20
+ color: var(--ms-debug-summary-color);
21
21
  user-select: none;
22
22
  padding: calc(0.4 * var(--ms-rem));
23
- border-radius: calc(var(--base-border-radius-sm, 0.4) * var(--ms-rem));
23
+ border-radius: var(--ms-debug-summary-border-radius);
24
24
  }
25
25
 
26
- .ms-debug-info details summary:hover {
27
- background-color: #f3f4f6;
26
+ .ms__debug-info details summary:hover {
27
+ background-color: var(--ms-debug-summary-bg-hover);
28
28
  }
29
29
 
30
- .ms-debug-info details summary:focus {
31
- outline: 2px solid #3b82f6;
30
+ .ms__debug-info details summary:focus {
31
+ outline: 2px solid var(--ms-debug-summary-outline-color);
32
32
  outline-offset: 2px;
33
33
  }
34
34
 
35
- .ms-debug-info .ms-debug-stats {
35
+ .ms__debug-info .ms__debug-stats {
36
36
  display: flex;
37
37
  flex-direction: column;
38
38
  gap: calc(0.4 * var(--ms-rem));
39
39
  margin-top: calc(0.4 * var(--ms-rem));
40
40
  padding: calc(0.4 * var(--ms-rem));
41
- background-color: #ffffff;
42
- border-radius: calc(var(--base-border-radius-sm, 0.4) * var(--ms-rem));
41
+ background-color: var(--ms-debug-stats-bg);
42
+ border-radius: var(--ms-debug-stats-border-radius);
43
43
  }
44
44
 
45
- .ms-debug-info .ms-debug-stats span {
45
+ .ms__debug-info .ms__debug-stats span {
46
46
  display: flex;
47
47
  justify-content: space-between;
48
48
  padding: 2px 4px;
@@ -50,8 +50,8 @@
50
50
  font-size: calc(1 * var(--ms-rem));
51
51
  }
52
52
 
53
- .ms-debug-info .ms-debug-stats span::before {
53
+ .ms__debug-info .ms__debug-stats span::before {
54
54
  content: '•';
55
55
  margin-right: calc(0.4 * var(--ms-rem));
56
- color: #3b82f6;
56
+ color: var(--ms-debug-bullet-color);
57
57
  }
@@ -1,13 +1,100 @@
1
1
  /* ==============================================================================
2
- TOOLTIPS & POPOVER
2
+ FLOATING Floating-UI-anchored panels
3
3
  ==============================================================================
4
- Badge tooltips and selected items popover
4
+ Search hint, dropdown panel, badge tooltips, and the selected-items popover.
5
+ All use `position: fixed` so they escape `overflow: hidden|auto|scroll`
6
+ containers, and all are positioned by Floating UI from JS. The CSS here
7
+ defines visual chrome only — positioning is dynamic.
5
8
  */
6
9
 
10
+ /* ==============================================================================
11
+ FLOATING SEARCH HINT
12
+ ============================================================================== */
13
+
14
+ .ms__hint {
15
+ display: none;
16
+ position: fixed;
17
+ z-index: var(--ms-z-index-popover);
18
+ padding: var(--ms-hint-padding);
19
+ background: var(--ms-hint-bg);
20
+ border: var(--ms-hint-border);
21
+ border-radius: var(--ms-hint-border-radius);
22
+ box-shadow: var(--ms-hint-box-shadow);
23
+ font-size: var(--ms-hint-font-size);
24
+ color: var(--ms-hint-color);
25
+ line-height: var(--ms-line-height-relaxed);
26
+ max-width: 100%;
27
+ }
28
+
29
+ .ms__hint--visible {
30
+ display: block;
31
+ }
32
+
33
+ /* ==============================================================================
34
+ DROPDOWN PANEL
35
+ ============================================================================== */
36
+
37
+ .ms__dropdown {
38
+ display: none;
39
+ position: fixed;
40
+ font-family: inherit; /* Ensure font inherits from container */
41
+ z-index: var(--ms-z-index-dropdown);
42
+ background: var(--ms-dropdown-bg);
43
+ border: var(--ms-dropdown-border);
44
+ border-radius: var(--ms-dropdown-border-radius);
45
+ box-shadow: var(--ms-dropdown-box-shadow);
46
+ max-height: var(--ms-options-max-height);
47
+ overflow: hidden; /* Clips content to border-radius, inner container handles scrolling */
48
+ color: var(--ms-dropdown-text-color);
49
+ }
50
+
51
+ .ms__dropdown--visible {
52
+ display: flex;
53
+ flex-direction: column;
54
+ }
55
+
56
+ /* Inner scrolling container — clips scrollbar to rounded corners */
57
+ .ms__dropdown-inner {
58
+ flex: 1;
59
+ overflow-y: auto;
60
+ overscroll-behavior: contain;
61
+ touch-action: pan-y;
62
+ -webkit-overflow-scrolling: touch;
63
+
64
+ /* Scrollbar styling */
65
+ scrollbar-width: thin; /* Firefox */
66
+ scrollbar-color: var(--ms-scrollbar-thumb-bg) var(--ms-scrollbar-track-bg);
67
+ }
68
+
69
+ .ms__dropdown-inner::-webkit-scrollbar {
70
+ width: var(--ms-scrollbar-width);
71
+ }
72
+
73
+ .ms__dropdown-inner::-webkit-scrollbar-track {
74
+ background: var(--ms-scrollbar-track-bg);
75
+ }
76
+
77
+ .ms__dropdown-inner::-webkit-scrollbar-thumb {
78
+ background: var(--ms-scrollbar-thumb-bg);
79
+ border-radius: var(--ms-scrollbar-thumb-border-radius);
80
+ }
81
+
82
+ .ms__dropdown-inner::-webkit-scrollbar-thumb:hover {
83
+ background: var(--ms-scrollbar-thumb-bg-hover);
84
+ }
85
+
86
+ .ms__dropdown--virtual {
87
+ /* In virtual scroll mode, let the options container handle scrolling */
88
+ max-height: none;
89
+ }
90
+
91
+ .ms__dropdown--virtual .ms__dropdown-inner {
92
+ overflow-y: visible;
93
+ }
94
+
7
95
  /* ==============================================================================
8
96
  BADGE TOOLTIPS
9
- ==============================================================================
10
- */
97
+ ============================================================================== */
11
98
 
12
99
  .ms__badge-tooltip {
13
100
  position: fixed;
@@ -35,11 +122,12 @@
35
122
  }
36
123
 
37
124
  /* ==============================================================================
38
- SELECTED ITEMS POPOVER
125
+ SELECTED-ITEMS POPOVER
39
126
  ==============================================================================
127
+ Opens from the count-display / compact / "+X more" interactions to show
128
+ every selected item. Contains its own scrollable body.
40
129
  */
41
130
 
42
- /* Selected items popover (for count display mode) */
43
131
  .ms__selected-popover {
44
132
  display: none;
45
133
  position: fixed;
@@ -151,10 +239,6 @@
151
239
  min-width: 0; /* Allow proper flex sizing */
152
240
  white-space: normal; /* Explicitly allow wrapping */
153
241
  word-wrap: break-word; /* Break long words */
154
- /* Remove overflow constraints to allow multi-line content */
155
- /* overflow: hidden; */
156
- /* text-overflow: ellipsis; */
157
- /* white-space: nowrap; */
158
242
  }
159
243
 
160
244
  /* Virtual scroll mode */
package/src/css/main.css CHANGED
@@ -1,27 +1,32 @@
1
1
  /* ==============================================================================
2
- MULTISELECT COMPONENT - MAIN ENTRY POINT
2
+ MULTISELECT COMPONENT MAIN ENTRY POINT
3
3
  ==============================================================================
4
- Typeahead multiselect with rich content support and floating hints
4
+ Cascade layer order (later = higher priority):
5
+ variables — :host { --ms-* } declarations
6
+ component — base + feature rules
7
+ overrides — dark mode, framework themes, per-instance overrides
5
8
 
6
- File structure:
7
- - _variables.css : All CSS custom properties at :host level (for theming)
8
- - _base.css : FOUC prevention + layout containers
9
- - _input-dropdown.css : Input, toggle, counter, hint, dropdown, actions
10
- - _options.css : Options list, groups, checkbox, content, states
11
- - _badges-display.css : Badges, count display, individual badges
12
- - _tooltips-popover.css : Badge tooltips + selected items popover
13
- - _rtl.css : RTL (Right-to-Left) language support
14
- - _modifiers.css : State modifiers
15
- - _debug.css : Debug information panel
9
+ Consumer override contract:
10
+ - Any unlayered consumer rule beats every rule in these layers.
11
+ - Any :root --base-* declaration beats the variables layer trivially.
16
12
  */
17
13
 
18
- /* Import all partials in dependency order */
19
- @import '_variables.css';
20
- @import '_base.css';
21
- @import '_input-dropdown.css';
22
- @import '_options.css';
23
- @import '_badges-display.css';
24
- @import '_tooltips-popover.css';
25
- @import '_rtl.css';
26
- @import '_modifiers.css';
27
- @import '_debug.css';
14
+ @layer variables, component, overrides;
15
+
16
+ /* === SKELETON + CANONICAL CONCERNS (Tier 1 + Tier 2) === */
17
+ @import url('./variables.css') layer(variables);
18
+ @import url('./base.css') layer(component);
19
+ @import url('./controls.css') layer(component);
20
+ @import url('./floating.css') layer(component);
21
+ @import url('./states.css') layer(component);
22
+ @import url('./animations.css') layer(component);
23
+
24
+ /* === COMPONENT-SPECIFIC FEATURES (Tier 3 — alphabetized) === */
25
+ @import url('./badges.css') layer(component);
26
+ @import url('./count-display.css') layer(component);
27
+ @import url('./debug.css') layer(component);
28
+ @import url('./options.css') layer(component);
29
+ @import url('./rtl.css') layer(component);
30
+
31
+ /* === OVERRIDES === */
32
+ @import url('./dark-mode.css') layer(overrides);
@@ -153,7 +153,7 @@
153
153
  outline: none;
154
154
  }
155
155
 
156
- /* Checkbox alignment variants (center is default, defined in _variables.css) */
156
+ /* Checkbox alignment variants (center is default, defined in variables.css) */
157
157
  .ms__option[data-checkbox-align="top"] {
158
158
  --ms-checkbox-align: flex-start;
159
159
  }
@@ -1,13 +1,10 @@
1
1
  /* ==============================================================================
2
- MODIFIERS & VARIANTS
3
- ==============================================================================
4
- State modifiers (disabled, no-checkboxes)
5
- Note: Size variants removed - use --ms-rem for global scaling instead
6
- */
7
-
8
- /* ==============================================================================
9
- STATE MODIFIERS
2
+ STATES cross-feature state modifiers
10
3
  ==============================================================================
4
+ Block-level state classes that affect multiple feature areas. Per-element
5
+ states (`.ms__input:focus`, `.ms__option--focused`, `.ms__badges:empty`,
6
+ etc.) stay in their feature files; this file is for state classes set on
7
+ the `.ms` block that flow through to multiple internal elements.
11
8
  */
12
9
 
13
10
  /* Disabled state */
@@ -627,4 +627,19 @@
627
627
  --ms-scrollbar-thumb-bg: var(--ms-border-color);
628
628
  --ms-scrollbar-thumb-bg-hover: var(--ms-text-color-3);
629
629
  --ms-scrollbar-thumb-border-radius: 4px;
630
+
631
+ /* ==========================================================================
632
+ DEBUG PANEL (dev-only)
633
+ ========================================================================== */
634
+ --ms-debug-bg: var(--base-elevated-bg, light-dark(#f9fafb, #2b2b2b));
635
+ --ms-debug-border-color: var(--ms-border-color);
636
+ --ms-debug-text-color: var(--ms-text-color-1);
637
+ --ms-debug-border-radius: var(--ms-border-radius-md);
638
+ --ms-debug-summary-color: var(--ms-accent-color);
639
+ --ms-debug-summary-bg-hover: var(--ms-primary-bg);
640
+ --ms-debug-summary-outline-color: var(--ms-accent-color);
641
+ --ms-debug-summary-border-radius: var(--ms-border-radius-sm);
642
+ --ms-debug-stats-bg: var(--base-main-bg, light-dark(#ffffff, #1a1a1a));
643
+ --ms-debug-stats-border-radius: var(--ms-border-radius-sm);
644
+ --ms-debug-bullet-color: var(--ms-accent-color);
630
645
  }
File without changes