@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.
- package/README.md +58 -16
- package/component-variables.manifest.json +12 -0
- package/dist/multiselect.js +199 -199
- package/dist/multiselect.umd.js +7 -7
- package/dist/style.css +1 -1
- package/package.json +2 -1
- package/src/css/animations.css +1 -0
- package/src/css/{_badges-display.css → badges.css} +11 -110
- package/src/css/{_base.css → base.css} +3 -3
- package/src/css/{_input-dropdown.css → controls.css} +16 -108
- package/src/css/count-display.css +108 -0
- package/src/css/dark-mode.css +58 -0
- package/src/css/{_debug.css → debug.css} +18 -18
- package/src/css/{_tooltips-popover.css → floating.css} +94 -10
- package/src/css/main.css +27 -22
- package/src/css/{_options.css → options.css} +1 -1
- package/src/css/{_modifiers.css → states.css} +5 -8
- package/src/css/{_variables.css → variables.css} +15 -0
- /package/src/css/{_rtl.css → rtl.css} +0 -0
package/README.md
CHANGED
|
@@ -7,6 +7,17 @@ A lightweight, accessible multiselect web component with typeahead search, RTL l
|
|
|
7
7
|
|
|
8
8
|
> **⚠️ Security Notice:** This component intentionally allows raw HTML in rendering callbacks to give developers full control over content display. If you display user-generated content, you must sanitize it yourself. See [HTML Injection (XSS) Notice](#html-injection-xss-notice) for the complete list of affected callbacks.
|
|
9
9
|
|
|
10
|
+
## What's New in v1.12.0-rc01
|
|
11
|
+
|
|
12
|
+
- **Dark mode now responds to framework theme classes** — `data-bs-theme="dark"` (Bootstrap 5.3+), `.dark` (Tailwind), and `data-theme="dark"` on any ancestor flip the component to dark, even on apps that flip classes without declaring `color-scheme`. Your own `--base-*` overrides on `:root` flow through unchanged — the component picks the dark branch of its built-in fallbacks without clobbering your theme. Symmetric `light` selectors let you force one widget back to light on a dark page. Per-instance `<web-multiselect data-theme="dark">` works as the highest-priority escape hatch.
|
|
13
|
+
- **CSS cascade layers (`@layer variables, component, overrides`)** — every internal rule lives in a named layer, so consumer CSS in the light DOM can override any component rule without `!important` or specificity arms races. Document any unlayered rule in your app's CSS and it wins automatically.
|
|
14
|
+
- **CSS file structure refactored into canonical Tier 1+2+3** — `controls.css` for input chrome, `floating.css` for dropdown/hint/tooltip/popover, `states.css` for block-level state modifiers, `badges.css` / `count-display.css` for the two display modes, etc. Each file now owns one logical concern; the old mixed-bag `input-dropdown.css`, `tooltips-popover.css`, `badges-display.css` are gone. Only affects deep CSS imports; bundle output unchanged.
|
|
15
|
+
- **CSS source files no longer have underscore prefix** — `_variables.css` → `variables.css`, etc. The underscore was a leftover SASS partial convention; these are plain CSS modules.
|
|
16
|
+
- **BEM-aligned class names** — `.ms-wrapper` → `.ms__wrapper`, `.ms-debug-info` → `.ms__debug-info`, `.ms-debug-stats` → `.ms__debug-stats`. The wrapper class is internal layout chrome; debug classes are dev-only. See CHANGELOG migration table if you'd styled any of these externally.
|
|
17
|
+
- **Debug panel now fully themeable** — 11 new `--ms-debug-*` variables (was hardcoded hex literals).
|
|
18
|
+
- **`"./manifest"` short-import** — `import manifest from '@keenmate/web-multiselect/manifest'` for tooling that reads the variable catalog.
|
|
19
|
+
- **`test/AUDIT.md`** — living compliance tracker against the BlissFramework web-component guidelines (CSS structure, base variables, color scheme).
|
|
20
|
+
|
|
10
21
|
## What's New in v1.11.0
|
|
11
22
|
|
|
12
23
|
- **OS-aware light/dark defaults via `light-dark()`** — set `color-scheme: dark` on your page (`:root`, `body`, etc.) and the multiselect picks readable dark text/background colors automatically. No more enumerating ~15 `--base-*` overrides just to get usable defaults on a dark theme.
|
|
@@ -18,19 +29,6 @@ A lightweight, accessible multiselect web component with typeahead search, RTL l
|
|
|
18
29
|
- **New `examples-positioning.html`** — walks through baseline / transformed-ancestor / container-type / drift-detection scenarios.
|
|
19
30
|
- **New dark-mode e2e suite** — 4 specs verifying WCAG-AA option contrast on a dark page across fully-themed, minimal-override, and pure OS-inheritance configurations.
|
|
20
31
|
|
|
21
|
-
## What's New in v1.10.0
|
|
22
|
-
|
|
23
|
-
- **`data-options` attribute on `<web-multiselect>`** — set options declaratively from HTML, no JS bootstrap required (works alongside `initial-values` for pure-HTML / server-rendered / SharePoint workbench scenarios).
|
|
24
|
-
- **`form.reset()` now clears the selection** — the element is now form-associated (`static formAssociated = true` + `ElementInternals` + `formResetCallback()`).
|
|
25
|
-
- **Dropdown / hint / selected popover no longer clipped inside scrollable ancestors** — Floating UI now uses `strategy: 'fixed'` for all three panels, so they escape `overflow: hidden|auto|scroll` containers (e.g. SharePoint Framework workbenches).
|
|
26
|
-
- **`initial-values` now works when options arrive after init** — values are reconciled on every `options` mutation, not just at construction.
|
|
27
|
-
- **Remove / close (×) buttons render as SVG masks** — pixel-centered regardless of font; color still flows through the existing `--ms-*-color` variables via `currentColor`; three new `--ms-*-icon-size` variables for theming.
|
|
28
|
-
- **Keyboard navigation now keeps working after a mouse click on an option** — previously, clicking an option moved focus from the search input to the option's checkbox (knocking the `keydown` listener offline) *and* left `focusedIndex` at its pre-click value, so subsequent ArrowDown / ArrowUp / Enter went nowhere visible. Click now anchors `focusedIndex` to the clicked option and refocuses the search input, so arrow keys continue from where you clicked and Enter toggles the option under the cursor.
|
|
29
|
-
- **Count-clear / popover-close hover backdrop now matches the rest of the component** — was a circle (`border-radius: 50%`), now a small rounded rectangle (`--ms-border-radius-sm`) consistent with every other interactive element. Themes that prefer the circle can set `--ms-count-clear-border-radius` and `--ms-selected-popover-close-border-radius` back to `50%`.
|
|
30
|
-
- **Keyboard `Enter` respects disabled options** — previously only the click handler did.
|
|
31
|
-
- **End-to-end test suite** — 114 Playwright specs across 19 fixture pages (`npm run test:e2e`).
|
|
32
|
-
- **`THEMING.md`** — new reference cataloguing every theme-able component state and the CSS variables that drive it.
|
|
33
|
-
|
|
34
32
|
## Features
|
|
35
33
|
|
|
36
34
|
- 📝 **Declarative HTML** - Use standard `<option>` and `<optgroup>` elements - no JavaScript required for simple cases!
|
|
@@ -1733,6 +1731,31 @@ You can customize the component using CSS variables even with just a `<script>`
|
|
|
1733
1731
|
</style>
|
|
1734
1732
|
```
|
|
1735
1733
|
|
|
1734
|
+
### Dark mode — supported signals
|
|
1735
|
+
|
|
1736
|
+
Since v1.12.0 the multiselect honors **five different signals** for switching to dark mode. Pick whichever fits your app; you don't need to wire them all up.
|
|
1737
|
+
|
|
1738
|
+
| # | Signal | Set by | Example |
|
|
1739
|
+
|---|--------|--------|---------|
|
|
1740
|
+
| 1 | OS preference + page `color-scheme` | App author | `html { color-scheme: light dark }` — multiselect picks the OS branch automatically. |
|
|
1741
|
+
| 2 | Page-level `color-scheme: dark` | App author | `body { color-scheme: dark }` — flips every multiselect on the page to dark. |
|
|
1742
|
+
| 3 | Framework data-attribute on ancestor | Bootstrap, Pure Admin, custom apps | `<html data-bs-theme="dark">` or `<div data-theme="dark">…</div>` |
|
|
1743
|
+
| 4 | Framework class on ancestor | Tailwind, hand-rolled toggles | `<html class="dark">` |
|
|
1744
|
+
| 5 | Per-instance attribute on host | App author, for one widget | `<web-multiselect data-theme="dark">` |
|
|
1745
|
+
|
|
1746
|
+
**Precedence** (highest wins): per-instance (#5) → framework ancestor (#3, #4) → page color-scheme (#1, #2).
|
|
1747
|
+
|
|
1748
|
+
#### Forcing a single widget back to light
|
|
1749
|
+
|
|
1750
|
+
If your page is dark but you want one multiselect to render light:
|
|
1751
|
+
|
|
1752
|
+
```html
|
|
1753
|
+
<!-- on a body { color-scheme: dark } page -->
|
|
1754
|
+
<web-multiselect data-theme="light"></web-multiselect>
|
|
1755
|
+
```
|
|
1756
|
+
|
|
1757
|
+
This works for any of signals #3–#5. The symmetric `data-theme="light"`, `data-bs-theme="light"`, `.light` selectors restore the light palette inside the affected scope.
|
|
1758
|
+
|
|
1736
1759
|
### Available CSS Variables
|
|
1737
1760
|
|
|
1738
1761
|
The component exposes **150+ CSS custom properties** defined at the `:host` level, making them inspectable and overridable. Below are the **50+ most commonly customized variables** organized by category.
|
|
@@ -1759,7 +1782,7 @@ All CSS custom properties are now defined at the `:host` level in the compiled C
|
|
|
1759
1782
|
```
|
|
1760
1783
|
|
|
1761
1784
|
For the complete list of all available CSS variables, see:
|
|
1762
|
-
- [
|
|
1785
|
+
- [variables.css](./src/css/variables.css) - All 150+ CSS custom properties at `:host` level
|
|
1763
1786
|
|
|
1764
1787
|
#### Colors
|
|
1765
1788
|
|
|
@@ -1893,6 +1916,25 @@ For the complete list of all available CSS variables, see:
|
|
|
1893
1916
|
| `--ms-shadow-xl` | (box shadow) | Extra large shadow |
|
|
1894
1917
|
| `--ms-disabled-opacity` | `0.5` | Opacity for disabled state |
|
|
1895
1918
|
|
|
1919
|
+
### Cascade layers / override contract
|
|
1920
|
+
|
|
1921
|
+
Since v1.12.0, the component's internal CSS is organized into named `@layer`s:
|
|
1922
|
+
|
|
1923
|
+
```css
|
|
1924
|
+
@layer variables, component, overrides;
|
|
1925
|
+
```
|
|
1926
|
+
|
|
1927
|
+
This gives consumers a predictable escape hatch when they need to override a rule from outside the shadow DOM (e.g. via `web-multiselect ::part(...)` or descendant selectors that reach into composed light DOM):
|
|
1928
|
+
|
|
1929
|
+
| Where your rule lives | Wins against |
|
|
1930
|
+
|---|---|
|
|
1931
|
+
| Unlayered consumer rule | Every internal layer (no `!important` needed) |
|
|
1932
|
+
| Consumer `@layer overrides` block | Component's `overrides` layer if loaded later in the stylesheet stack |
|
|
1933
|
+
| `:root { --base-* }` declaration | Component's `variables` layer trivially |
|
|
1934
|
+
| `web-multiselect { --ms-* }` element selector | Same as above, with higher specificity |
|
|
1935
|
+
|
|
1936
|
+
In practice you rarely need to think about layers — variables-first theming (`--ms-*` and `--base-*` overrides) covers ~95% of customization. Layers exist for the residual 5% where you need to flip a property the variable system doesn't expose.
|
|
1937
|
+
|
|
1896
1938
|
### Advanced: Direct CSS Import
|
|
1897
1939
|
|
|
1898
1940
|
For users who want to import the raw CSS source files:
|
|
@@ -1902,8 +1944,8 @@ For users who want to import the raw CSS source files:
|
|
|
1902
1944
|
@import '@keenmate/web-multiselect/css';
|
|
1903
1945
|
|
|
1904
1946
|
/* Or import individual partials */
|
|
1905
|
-
@import '@keenmate/web-multiselect/src/css/
|
|
1906
|
-
@import '@keenmate/web-multiselect/src/css/
|
|
1947
|
+
@import '@keenmate/web-multiselect/src/css/variables.css';
|
|
1948
|
+
@import '@keenmate/web-multiselect/src/css/base.css';
|
|
1907
1949
|
/* ... etc */
|
|
1908
1950
|
```
|
|
1909
1951
|
|
|
@@ -390,6 +390,18 @@
|
|
|
390
390
|
{ "name": "ms-scrollbar-thumb-bg-hover", "category": "scrollbar", "usage": "Scrollbar thumb hover background" },
|
|
391
391
|
{ "name": "ms-scrollbar-thumb-border-radius", "category": "scrollbar", "usage": "Scrollbar thumb border radius" },
|
|
392
392
|
|
|
393
|
+
{ "name": "ms-debug-bg", "category": "debug", "usage": "Debug panel background" },
|
|
394
|
+
{ "name": "ms-debug-border-color", "category": "debug", "usage": "Debug panel border" },
|
|
395
|
+
{ "name": "ms-debug-text-color", "category": "debug", "usage": "Debug panel text" },
|
|
396
|
+
{ "name": "ms-debug-border-radius", "category": "debug", "usage": "Debug panel corner radius" },
|
|
397
|
+
{ "name": "ms-debug-summary-color", "category": "debug", "usage": "Debug section heading color" },
|
|
398
|
+
{ "name": "ms-debug-summary-bg-hover", "category": "debug", "usage": "Debug section heading hover background" },
|
|
399
|
+
{ "name": "ms-debug-summary-outline-color", "category": "debug", "usage": "Debug section heading focus outline" },
|
|
400
|
+
{ "name": "ms-debug-summary-border-radius", "category": "debug", "usage": "Debug section heading corner radius" },
|
|
401
|
+
{ "name": "ms-debug-stats-bg", "category": "debug", "usage": "Debug stats nested panel background" },
|
|
402
|
+
{ "name": "ms-debug-stats-border-radius", "category": "debug", "usage": "Debug stats nested panel corner radius" },
|
|
403
|
+
{ "name": "ms-debug-bullet-color", "category": "debug", "usage": "Debug stat bullet marker color" },
|
|
404
|
+
|
|
393
405
|
{ "name": "ms-transform-center-y", "category": "transform", "usage": "Center Y transform" },
|
|
394
406
|
{ "name": "ms-transform-rotate-180", "category": "transform", "usage": "180 degree rotation" },
|
|
395
407
|
{ "name": "ms-transform-scale-hover", "category": "transform", "usage": "Hover scale transform" },
|