@keenmate/web-multiselect 1.12.0-rc07 → 1.12.0-rc08
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 +8 -11
- package/component-variables.manifest.json +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/multiselect.js +783 -702
- package/dist/multiselect.umd.js +15 -14
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/css/controls.css +10 -2
- package/src/css/floating.css +1 -0
- package/src/css/variables.css +29 -10
package/README.md
CHANGED
|
@@ -21,23 +21,20 @@ Reads `--base-*` variables from the page if [`@keenmate/theme-designer`](https:/
|
|
|
21
21
|
- Custom rendering callbacks for options, badges, and group headers.
|
|
22
22
|
- Form integration via standard hidden inputs (FormData-compatible).
|
|
23
23
|
|
|
24
|
+
## What's New in v1.12.0-rc08
|
|
25
|
+
|
|
26
|
+
- **Panel sizing — dropdown and popover are independently sizable via CSS variables** — The options dropdown and selected-items popover no longer inherit the input's width. `--ms-dropdown-width` (defaults to the live input width) and `--ms-selected-popover-width` (intrinsic 32rem) drive them, alongside the existing max-height variables. Set them at app level (`web-multiselect { --ms-dropdown-width: 60rem }`) or override a single instance with the new `dropdown-width` / `selected-popover-width` attributes, which write those variables inline on the element. This also fixes a latent bug where `--ms-selected-popover-width` was dead (an internal width-sync always overrode it), so the popover now honours its 32rem default. See section 14 of `examples-tree.html`.
|
|
27
|
+
- **Tree rendering — the option render callback receives full tree context** — `renderOptionContentCallback(item, ctx)` gains `isTreeNode`, `isBranch`, `isLeaf`, `childCount`, `level`, `depth`, `path`, `isSelectable`, and the cascade `isIndeterminate` tristate. Rendering a child-count badge on branches or branch/leaf-specific markup is now a one-liner, without re-deriving the hierarchy yourself. All fields are optional (flat options report `isTreeNode: false`), so existing callbacks are untouched. Demoed as the new "Custom Node Rendering" section.
|
|
28
|
+
- **Cascade counter — the `[N]` chip counts what you actually picked** — In cascade mode the counter used to show the emitted value count, which balloons under `cascade-select-policy="leaves"` / `"all"` (one branch click can emit five values) — jarring next to a couple of rolled-up badges. It now counts the rolled-up minimal cover — the branches you selected — regardless of emit policy, and gained a hover tooltip listing those items. Under the default `rolled-up` policy nothing changes.
|
|
29
|
+
- **Theming cleanup — dead input size-variant surface removed from the bundle** — The unused `.ms__input--xs/sm/lg/xl` preset classes and their `--ms-input-size-*` variable chain were never wired to anything (no `size` attribute toggles them), so they've been commented out — kept for a possible future preset API but no longer shipped as dead CSS (the compiled stylesheet shrank ~2 kB). Input sizing still works through `--ms-rem` for proportional global scale or the individual `--ms-input-*` variables for targeted overrides.
|
|
30
|
+
- **Fixes — badge hover and live cascade switching** — Badge hover no longer washes the chip to white (the hover background fell through to the white input background; it now deepens the accent tint, dark-mode aware). And switching `checkbox-mode` or `cascade-select-policy` live rebuilds the cascade index and silently re-projects the current selection, so badges, form value, and checkboxes all reflect the new mode instantly.
|
|
31
|
+
|
|
24
32
|
## What's New in v1.12.0-rc07
|
|
25
33
|
|
|
26
34
|
- **Selection — `setSelected(values, { notify: true })` announces programmatic changes** — `setSelected()` stays silent by default (restoring saved state, cascade/dependent resets, and server-authoritative corrections must not re-fire `change`, or they trip "the user changed it" handlers and can bounce in a feedback loop), but the new `{ notify: true }` option fires a **single aggregate `change`** — no per-item `select`/`deselect` flood — for when a programmatic change is a deliberate user gesture, e.g. a custom action button that sets the selection and should reach the same listeners a manual pick does. Threaded through both the internal picker and the web component's `setSelected`.
|
|
27
35
|
- **Cascade mode — Select All now honours the value policy** — the built-in `select-all` action added every selectable node's value directly, bypassing the cascade projection, so with `checkbox-mode="cascade"` + `cascade-select-policy="rolled-up"` it emitted every node instead of the rolled-up roots (unlike a click, which rolls up). `selectAll()` is now cascade-aware — it fills the checked-atom set from the visible nodes and projects through the active policy via a shared `commitCascadeAtoms` helper — so Select All emits the same shape a click does. Shown in the new "Action Buttons" section of `examples-tree.html`.
|
|
28
36
|
- **Options no longer text-select on click-drag** — clicking a row, or dragging across the dropdown, used to highlight the labels like selectable text, which reads as broken for a pure selection gesture (most visible on the denser tree rows). Options now set `user-select: none` (with the `-webkit-` prefix) on `.ms__option`. Purely presentational — no API or behaviour change.
|
|
29
37
|
|
|
30
|
-
## What's New in v1.12.0-rc06
|
|
31
|
-
|
|
32
|
-
- **Tree of options — options can render as an always-expanded hierarchy** — give each option a materialized dot-path (`"1"`, `"1.1"`, `"1.1.1"`, …) and set `path-member` (or `el.getPathCallback`) and tree mode auto-enables, deriving parent/level from the path and rendering depth-first with indentation. The hierarchy model is a trimmed lift of `@keenmate/web-treeview`'s `ltree` (`src/tree/`) so ordering matches the treeview. There is no collapse/chevron — reach for `@keenmate/web-treeview` when you need expand/collapse. A separate `renderTreeNode` path carries the same selection/checkbox/icon/subtitle content plus depth indentation (via `--ms-tree-depth` → `src/css/tree.css`, tuned with `--ms-tree-indent`), and search filters the hierarchy to matches plus their ancestors so indentation stays coherent.
|
|
33
|
-
- **Per-node selectability — mark tree nodes non-selectable without greying them out** — `is-selectable-member` (a data flag) or `el.getIsSelectableCallback` (a predicate over the built `LTreeNode`, so it can read the derived `node.hasChildren`) makes the common "leaves only" rule a one-liner. A non-selectable node is distinct from a disabled one: it renders *normally* but drops its checkbox, is skipped by keyboard focus, and can't be toggled by click/Enter or Select All. New `.ms__option--tree-unselectable` theming hook (plus `data-selectable="false"`) ships with only `cursor: default` and no hover highlight, so structural branch rows read as structure while staying visually normal.
|
|
34
|
-
- **External search now composes with tree mode** — previously the async `searchCallback` path set the flat `filteredOptions` but not the parallel `treeNodes`, so an externalized search over a tree rendered blank or mis-indexed. It now rebuilds the hierarchy from the returned matches, keeping their ancestors (`rebuildTreeVisibleFromMatches`) — the async analogue of the built-in matches-plus-ancestors behaviour — and the below-min-length / error fallbacks are tree-aware too. A new `examples-search-index.html` demonstrates delegating the whole search to FlexSearch (fuzzy / accent-insensitive / ranked) over both a flat list and the full ISCO-08 tree, with an exact/prefix code lookup so `2211` resolves to its node and `72` to the whole subtree. FlexSearch stays a dev/consumer dependency — never in the shipped bundle.
|
|
35
|
-
- **Badge full title — render a supplied breadcrumb on badges** — new `full-title-member` (or `el.getFullTitleCallback`) reads a fully-qualified label that ships with the data (e.g. `"Fruit / Pome fruit / Apple"`); it is never computed. Turn on `show-badge-full-title` and badges render that full title instead of the display value, falling back to the display value for options without one, while an explicit `getBadgeDisplayCallback` still wins. Pairs naturally with tree mode to show the full path in the badge.
|
|
36
|
-
- **Adjustable row height and long-title handling** — new CSS variables (no new attributes) control every `.ms__option`, flat and tree: `--ms-option-min-height` sets a consistent minimum row height for non-virtual rows (they still grow if content is taller; virtual rows keep the fixed `--ms-option-height`), and `--ms-option-title-white-space` / `-overflow` / `-text-overflow` flip a title from the default wrap to a one-line ellipsis. `.ms__option-title` is the label hook (the analog of web-treeview's `.wtv__node-label`), and because its flex ancestors already set `min-width: 0`, ellipsis works with no extra CSS — pair it with `enable-option-tooltips` to reveal the full text on hover.
|
|
37
|
-
- **Cascade checkboxes for tree mode, with a value policy** — set `checkbox-mode="cascade"` and checking a node toggles its whole subtree while a partially-selected branch shows a tristate (dash) box. Orthogonally, `cascade-select-policy` decides *which values* the selection emits: `rolled-up` (default) collapses a fully-selected subtree to one "complete node" value and surfaces individual descendants under partially-selected branches (the minimal cover — the bit svelte-treeview lacks); `leaves` emits only checked leaves; `all` emits every checked node like web-treeview. Canonical state is the set of checked leaf atoms and the emitted `selectedValues` is a pure projection, so badges/form/`change` are untouched and every policy round-trips. Non-breaking — `independent` (the previous behaviour) is the default. Logic is isolated in `src/tree/cascade.ts`; tristate renders from a CSS modifier class (virtual-scroll-safe). Demoed as §10 on `examples-tree.html`.
|
|
38
|
-
- **More pronounced option checkboxes** — the unchecked box draws its border from a dedicated mid-grey token (`--ms-checkbox-border-color`, default `#8f8f8f`) instead of the faint generic `--ms-border`, so it reads as a real, clickable control, with a slightly bolder checkmark. New themeable tokens `--ms-checkbox-border-width` (1px), `--ms-checkbox-border-color`, and `--ms-checkbox-checkmark-thickness` drive it, and `--ms-checkbox-border` / `--ms-checkbox-checked-border` recompose from the width token — override any of them to restyle.
|
|
39
|
-
- **Fixes — stable tree rows across search** — two virtual-scroll/tree regressions are fixed: row height no longer jumps as filtering crosses the virtual-scroll threshold (non-virtual rows now pin to `--ms-option-height` when virtual scroll is enabled), and clearing a search with Escape (or reopening after a search) no longer leaves the dropdown blank — both the Escape-clear and `close()` paths route through a tree-aware `resetVisibleToAll()` that rebuilds `treeNodes` from the full tree.
|
|
40
|
-
|
|
41
38
|
> ⚠️ **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 [docs/examples.md → HTML Injection (XSS) notice](./docs/examples.md#html-injection-xss-notice) for the complete list of affected callbacks.
|
|
42
39
|
|
|
43
40
|
## Demos & docs
|
|
@@ -147,6 +147,7 @@
|
|
|
147
147
|
{ "name": "ms-dropdown-border-radius", "category": "dropdown", "usage": "Dropdown border radius" },
|
|
148
148
|
{ "name": "ms-dropdown-box-shadow", "category": "dropdown", "usage": "Dropdown shadow" },
|
|
149
149
|
{ "name": "ms-dropdown-box-shadow-semantic", "category": "dropdown", "usage": "Dropdown semantic shadow" },
|
|
150
|
+
{ "name": "ms-dropdown-width", "category": "dropdown", "usage": "Options dropdown width (defaults to the input width; also set via the dropdown-width attribute)" },
|
|
150
151
|
{ "name": "ms-options-max-height", "category": "dropdown", "usage": "Options list max height" },
|
|
151
152
|
{ "name": "ms-z-index-dropdown", "category": "dropdown", "usage": "Dropdown z-index" },
|
|
152
153
|
{ "name": "ms-z-index-sticky", "category": "dropdown", "usage": "Sticky elements z-index" },
|
package/dist/index.d.ts
CHANGED
|
@@ -745,6 +745,24 @@ declare interface OptionContentRenderContext {
|
|
|
745
745
|
isMatched: boolean;
|
|
746
746
|
/** Whether the option is disabled */
|
|
747
747
|
isDisabled: boolean;
|
|
748
|
+
/** True when this row is a tree node (path-member / tree mode). Absent/false for flat options. */
|
|
749
|
+
isTreeNode?: boolean;
|
|
750
|
+
/** Tree only: the node has children (a branch). */
|
|
751
|
+
isBranch?: boolean;
|
|
752
|
+
/** Tree only: the node has no children (a leaf). */
|
|
753
|
+
isLeaf?: boolean;
|
|
754
|
+
/** Tree only: number of direct children (0 for a leaf). */
|
|
755
|
+
childCount?: number;
|
|
756
|
+
/** Tree only: 1-based depth level as derived from the path (top level = 1). */
|
|
757
|
+
level?: number;
|
|
758
|
+
/** Tree only: 0-based indentation depth (`level - 1`), matching `--ms-tree-depth`. */
|
|
759
|
+
depth?: number;
|
|
760
|
+
/** Tree only: the node's materialized path (e.g. "1.1.2"). */
|
|
761
|
+
path?: string;
|
|
762
|
+
/** Tree only: the node is selectable (branches marked non-selectable are `false`). */
|
|
763
|
+
isSelectable?: boolean;
|
|
764
|
+
/** Tree only: cascade tristate — a partially-checked branch (some but not all descendants). */
|
|
765
|
+
isIndeterminate?: boolean;
|
|
748
766
|
}
|
|
749
767
|
|
|
750
768
|
/**
|
|
@@ -894,6 +912,17 @@ export declare class WebMultiSelect<T = any> {
|
|
|
894
912
|
* policy-projected shape (e.g. a full subtree rolls up to one value).
|
|
895
913
|
*/
|
|
896
914
|
private commitCascadeAtoms;
|
|
915
|
+
/**
|
|
916
|
+
* The "meaningful selection" list used by the counter chip — the rolled-up
|
|
917
|
+
* minimal cover, regardless of the active emit policy. In cascade mode
|
|
918
|
+
* `leaves`/`all` emit many values for a single branch pick, which made the
|
|
919
|
+
* counter read e.g. `[5]` for what a person experiences as two selections.
|
|
920
|
+
* The counter should count the branches actually chosen, and stay stable when
|
|
921
|
+
* the policy knob flips. Outside cascade this is just the selected options.
|
|
922
|
+
*/
|
|
923
|
+
private counterSelection;
|
|
924
|
+
/** Native `title` for the counter chip: the picked items, capped so it can't grow unbounded. */
|
|
925
|
+
private buildCounterTooltip;
|
|
897
926
|
/**
|
|
898
927
|
* Derive `treeNodes` + `filteredOptions` from the full tree, applying the
|
|
899
928
|
* current search term. Matching nodes keep all their ancestors visible so
|