@ixfx/components 0.14.0 → 0.14.2
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/bundle/index.d.ts +2 -0
- package/bundle/index.js +66 -61
- package/dist/index.d.ts +2 -0
- package/dist/index.js +48 -17
- package/dist/{tree-9Hs7VxuX.js → tree-BM2CY6uu.js} +4 -0
- package/dist/tree.js +1 -1
- package/dist/vertical-list.js +4 -1
- package/docs-user/index.json +2 -2
- package/docs-user/multicol-list.md +1 -1
- package/docs-user/tree.md +3 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -2442,6 +2442,7 @@ type MulticolCategoryDefaults = {
|
|
|
2442
2442
|
groupBy?: (item: MulticolItem) => string;
|
|
2443
2443
|
allLabel?: string;
|
|
2444
2444
|
sort?: SortDirection;
|
|
2445
|
+
menu?: boolean;
|
|
2445
2446
|
};
|
|
2446
2447
|
type MulticolCategory = {
|
|
2447
2448
|
readonly key: string;
|
|
@@ -2456,6 +2457,7 @@ type MulticolColumnState = {
|
|
|
2456
2457
|
readonly categoryKey: string;
|
|
2457
2458
|
readonly sort: SortDirection;
|
|
2458
2459
|
readonly grouped: boolean;
|
|
2460
|
+
readonly menu: boolean;
|
|
2459
2461
|
readonly width?: number;
|
|
2460
2462
|
};
|
|
2461
2463
|
type MulticolColumnsChangeReason = `add` | `remove` | `reorder` | `category` | `sort` | `grouping` | `resize`;
|
package/dist/index.js
CHANGED
|
@@ -27,7 +27,7 @@ import { t as CheckedSelect } from "./checked-select-lDgAQQ7v.js";
|
|
|
27
27
|
import { n as ColourPicker, t as ColourPickerPopup } from "./colour-picker-BCMU7W7R.js";
|
|
28
28
|
import { LabelledRangeInput } from "./labelled-range-input.js";
|
|
29
29
|
import { t as collectDataResult } from "./data-provider-35TyWclX.js";
|
|
30
|
-
import { a as TreeDataModel, c as pruneDraggedDescendants, i as TreeDropController, n as TreeListElement, o as applyTreeDrop, r as TreeBaseElement, s as dropTargetFor, t as TreeController } from "./tree-
|
|
30
|
+
import { a as TreeDataModel, c as pruneDraggedDescendants, i as TreeDropController, n as TreeListElement, o as applyTreeDrop, r as TreeBaseElement, s as dropTargetFor, t as TreeController } from "./tree-BM2CY6uu.js";
|
|
31
31
|
import { t as scrollFadeStyles } from "./scroll-fade-Xx28D7mH.js";
|
|
32
32
|
import { NarrowedTextElement } from "./narrowed-text.js";
|
|
33
33
|
import { CrumbNavigationElement } from "./crumbs.js";
|
|
@@ -9449,6 +9449,28 @@ __decorate([state()], IcicleTreeListElement.prototype, "_zoomKey", void 0);
|
|
|
9449
9449
|
__decorate([query(`#icicle-tooltip`)], IcicleTreeListElement.prototype, "_tooltipEl", void 0);
|
|
9450
9450
|
IcicleTreeListElement = __decorate([safeCustomElement(`ixfx-icicletree-list`)], IcicleTreeListElement);
|
|
9451
9451
|
//#endregion
|
|
9452
|
+
//#region src/multicol-list/categories.ts
|
|
9453
|
+
/** A group node only organises the picker menu; it is not a selectable category. */
|
|
9454
|
+
function isGroup(category) {
|
|
9455
|
+
return category.children !== void 0 && category.children.length > 0;
|
|
9456
|
+
}
|
|
9457
|
+
/** All selectable categories (leaves) of a category tree, depth-first. */
|
|
9458
|
+
function flattenCategories(categories) {
|
|
9459
|
+
return categories.flatMap((c) => isGroup(c) ? flattenCategories(c.children) : [c]);
|
|
9460
|
+
}
|
|
9461
|
+
/** Finds any node (group or leaf) by key, searching the whole tree depth-first. */
|
|
9462
|
+
function findCategory(categories, key) {
|
|
9463
|
+
for (const category of categories) {
|
|
9464
|
+
if (category.key === key) return category;
|
|
9465
|
+
const nested = category.children ? findCategory(category.children, key) : void 0;
|
|
9466
|
+
if (nested) return nested;
|
|
9467
|
+
}
|
|
9468
|
+
}
|
|
9469
|
+
/** Like `findCategory`, but only resolves selectable leaves (never a group node). */
|
|
9470
|
+
function findLeafCategory(categories, key) {
|
|
9471
|
+
return flattenCategories(categories).find((c) => c.key === key);
|
|
9472
|
+
}
|
|
9473
|
+
//#endregion
|
|
9452
9474
|
//#region src/multicol-list/types.ts
|
|
9453
9475
|
const ALL_KEY = `__all__`;
|
|
9454
9476
|
//#endregion
|
|
@@ -9522,6 +9544,7 @@ var MulticolColumnController = class {
|
|
|
9522
9544
|
categoryKey: options.category.key,
|
|
9523
9545
|
sort: options.categoryDefaults?.sort ?? `asc`,
|
|
9524
9546
|
grouped: options.categoryDefaults?.grouped ?? false,
|
|
9547
|
+
menu: options.categoryDefaults?.menu ?? true,
|
|
9525
9548
|
width: 220
|
|
9526
9549
|
};
|
|
9527
9550
|
}
|
|
@@ -9532,6 +9555,9 @@ var MulticolColumnController = class {
|
|
|
9532
9555
|
get categoryKey() {
|
|
9533
9556
|
return this.#category.key;
|
|
9534
9557
|
}
|
|
9558
|
+
get menu() {
|
|
9559
|
+
return this.#state.menu;
|
|
9560
|
+
}
|
|
9535
9561
|
getState() {
|
|
9536
9562
|
return { ...this.#state };
|
|
9537
9563
|
}
|
|
@@ -9585,7 +9611,8 @@ var MulticolColumnController = class {
|
|
|
9585
9611
|
...this.#state,
|
|
9586
9612
|
categoryKey: category.key,
|
|
9587
9613
|
sort: category.defaults?.sort ?? `asc`,
|
|
9588
|
-
grouped: category.defaults?.grouped ?? false
|
|
9614
|
+
grouped: category.defaults?.grouped ?? false,
|
|
9615
|
+
menu: category.defaults?.menu ?? true
|
|
9589
9616
|
};
|
|
9590
9617
|
this.clearSelection();
|
|
9591
9618
|
this.#syncGrouping();
|
|
@@ -9775,7 +9802,7 @@ function renderItem(item) {
|
|
|
9775
9802
|
}
|
|
9776
9803
|
//#endregion
|
|
9777
9804
|
//#region src/multicol-list/multicol-list.ts
|
|
9778
|
-
registerIcon(`menu`, `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><
|
|
9805
|
+
registerIcon(`menu`, `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg>`);
|
|
9779
9806
|
const DEFAULT_COLUMN_WIDTH = 220;
|
|
9780
9807
|
const MIN_COLUMN_WIDTH = 80;
|
|
9781
9808
|
const MAX_COLUMN_WIDTH = 480;
|
|
@@ -9877,7 +9904,7 @@ let MulticolListElement = class MulticolListElement extends LitElement {
|
|
|
9877
9904
|
}
|
|
9878
9905
|
.reorder-handle .ixfx-handle {
|
|
9879
9906
|
--ixfx-handle-length: 14px;
|
|
9880
|
-
--ixfx-handle-thickness: var(--multicol-list-reorder-handle-width,
|
|
9907
|
+
--ixfx-handle-thickness: var(--multicol-list-reorder-handle-width, 6px);
|
|
9881
9908
|
--ixfx-handle-dot-size: 3px;
|
|
9882
9909
|
}
|
|
9883
9910
|
.column-label {
|
|
@@ -9956,6 +9983,7 @@ let MulticolListElement = class MulticolListElement extends LitElement {
|
|
|
9956
9983
|
position: relative;
|
|
9957
9984
|
display: flex;
|
|
9958
9985
|
flex-direction: column;
|
|
9986
|
+
--list-gutter: 0;
|
|
9959
9987
|
}
|
|
9960
9988
|
.all-row {
|
|
9961
9989
|
display: flex;
|
|
@@ -10010,7 +10038,7 @@ let MulticolListElement = class MulticolListElement extends LitElement {
|
|
|
10010
10038
|
const existing = existingMap.get(colState.id);
|
|
10011
10039
|
if (existing) {
|
|
10012
10040
|
if (existing.categoryKey !== colState.categoryKey) {
|
|
10013
|
-
const newCategory = this.categories
|
|
10041
|
+
const newCategory = findLeafCategory(this.categories, colState.categoryKey);
|
|
10014
10042
|
if (newCategory) existing.setCategory(newCategory);
|
|
10015
10043
|
}
|
|
10016
10044
|
existing.updateState(colState);
|
|
@@ -10018,7 +10046,7 @@ let MulticolListElement = class MulticolListElement extends LitElement {
|
|
|
10018
10046
|
existingMap.delete(colState.id);
|
|
10019
10047
|
continue;
|
|
10020
10048
|
}
|
|
10021
|
-
const category = this.categories
|
|
10049
|
+
const category = findLeafCategory(this.categories, colState.categoryKey);
|
|
10022
10050
|
if (!category) continue;
|
|
10023
10051
|
const controller = this.#createController(colState.id, category);
|
|
10024
10052
|
controller.updateState(colState);
|
|
@@ -10033,7 +10061,7 @@ let MulticolListElement = class MulticolListElement extends LitElement {
|
|
|
10033
10061
|
}
|
|
10034
10062
|
addColumn(categoryKey, position) {
|
|
10035
10063
|
if (this.maxColumns > 0 && this._columns.length >= this.maxColumns) return;
|
|
10036
|
-
const category = this.categories
|
|
10064
|
+
const category = findLeafCategory(this.categories, categoryKey);
|
|
10037
10065
|
if (!category) return;
|
|
10038
10066
|
const id = `col-${++this._idCounter}`;
|
|
10039
10067
|
const controller = this.#createController(id, category);
|
|
@@ -10075,9 +10103,10 @@ let MulticolListElement = class MulticolListElement extends LitElement {
|
|
|
10075
10103
|
`;
|
|
10076
10104
|
}
|
|
10077
10105
|
updated(changedProperties) {
|
|
10078
|
-
|
|
10106
|
+
const seedCategory = flattenCategories(this.categories)[0];
|
|
10107
|
+
if (!this._autoSeeded && this._columns.length === 0 && seedCategory) {
|
|
10079
10108
|
this._autoSeeded = true;
|
|
10080
|
-
this.addColumn(
|
|
10109
|
+
this.addColumn(seedCategory.key);
|
|
10081
10110
|
}
|
|
10082
10111
|
if (changedProperties.has(`selectionMode`)) for (const col of this._columns) col.setSelectionMode(this.selectionMode);
|
|
10083
10112
|
if (changedProperties.has(`dataProvider`)) for (const col of this._columns) col.setDataProvider(this.dataProvider);
|
|
@@ -10116,6 +10145,7 @@ let MulticolListElement = class MulticolListElement extends LitElement {
|
|
|
10116
10145
|
this._openCategoryPicker(col, e.currentTarget);
|
|
10117
10146
|
}}
|
|
10118
10147
|
>${this._getCategoryLabel(col.categoryKey)}</button>
|
|
10148
|
+
${col.menu ? html`
|
|
10119
10149
|
<button
|
|
10120
10150
|
class="burger-btn"
|
|
10121
10151
|
data-tooltip="Column options"
|
|
@@ -10125,7 +10155,7 @@ let MulticolListElement = class MulticolListElement extends LitElement {
|
|
|
10125
10155
|
}}
|
|
10126
10156
|
>
|
|
10127
10157
|
<ixfx-icon name="menu" size="14"></ixfx-icon>
|
|
10128
|
-
</button
|
|
10158
|
+
</button>` : nothing}
|
|
10129
10159
|
<span
|
|
10130
10160
|
class="resize-handle"
|
|
10131
10161
|
?data-active=${this._resizingColumnId === col.id}
|
|
@@ -10138,11 +10168,11 @@ let MulticolListElement = class MulticolListElement extends LitElement {
|
|
|
10138
10168
|
`;
|
|
10139
10169
|
}
|
|
10140
10170
|
_getCategoryLabel(key) {
|
|
10141
|
-
return this.categories
|
|
10171
|
+
return findCategory(this.categories, key)?.label ?? key;
|
|
10142
10172
|
}
|
|
10143
10173
|
/** Category description if present, else the default 'Change category' hint. */
|
|
10144
10174
|
_getCategoryTooltip(key) {
|
|
10145
|
-
return this.categories
|
|
10175
|
+
return findCategory(this.categories, key)?.description ?? `Change category`;
|
|
10146
10176
|
}
|
|
10147
10177
|
#createController(id, category) {
|
|
10148
10178
|
return new MulticolColumnController({
|
|
@@ -10313,7 +10343,7 @@ let MulticolListElement = class MulticolListElement extends LitElement {
|
|
|
10313
10343
|
container.appendChild(separator);
|
|
10314
10344
|
const atMax = this.maxColumns > 0 && this._columns.length >= this.maxColumns;
|
|
10315
10345
|
const usedCats = new Set(this._columns.map((c) => c.categoryKey));
|
|
10316
|
-
const unused = this.categories.filter((c) => !usedCats.has(c.key));
|
|
10346
|
+
const unused = flattenCategories(this.categories).filter((c) => !usedCats.has(c.key));
|
|
10317
10347
|
const canAdd = !atMax && unused.length > 0;
|
|
10318
10348
|
const addSub = document.createElement(`ixfx-menu-sub-trigger`);
|
|
10319
10349
|
addSub.setAttribute(`label`, `Add column`);
|
|
@@ -10357,7 +10387,7 @@ let MulticolListElement = class MulticolListElement extends LitElement {
|
|
|
10357
10387
|
this.addColumn(categoryKey, position);
|
|
10358
10388
|
}
|
|
10359
10389
|
_changeColumnCategory(col, categoryKey) {
|
|
10360
|
-
const category = this.categories
|
|
10390
|
+
const category = findLeafCategory(this.categories, categoryKey);
|
|
10361
10391
|
if (!category) return;
|
|
10362
10392
|
col.setCategory(category);
|
|
10363
10393
|
this._emitColumnsChange(`category`);
|
|
@@ -10393,10 +10423,11 @@ let MulticolListElement = class MulticolListElement extends LitElement {
|
|
|
10393
10423
|
}
|
|
10394
10424
|
_syncColumnsWithCategories() {
|
|
10395
10425
|
let changed = false;
|
|
10426
|
+
const leaves = flattenCategories(this.categories);
|
|
10396
10427
|
for (const col of this._columns) {
|
|
10397
|
-
if (
|
|
10398
|
-
if (
|
|
10399
|
-
col.setCategory(
|
|
10428
|
+
if (leaves.some((c) => c.key === col.categoryKey)) continue;
|
|
10429
|
+
if (leaves.length === 0) continue;
|
|
10430
|
+
col.setCategory(leaves[0]);
|
|
10400
10431
|
changed = true;
|
|
10401
10432
|
}
|
|
10402
10433
|
if (changed) this._emitColumnsChange(`category`);
|
|
@@ -2578,6 +2578,10 @@ let TreeBaseElement = class TreeBaseElement extends LitElement {
|
|
|
2578
2578
|
_handleItemClick(node, depth, event) {
|
|
2579
2579
|
if (this.#drop?.isDragging || this.#nativeDrag?.isDragging || this.#postDragSuppressTimer !== void 0) return;
|
|
2580
2580
|
if (event && event.detail >= 2) return;
|
|
2581
|
+
if (this.interactionMode === `checked` && event && !(event.target instanceof Element && event.target.closest(`.tree-label`))) {
|
|
2582
|
+
this._handleCheckboxClick(event, node, depth);
|
|
2583
|
+
return;
|
|
2584
|
+
}
|
|
2581
2585
|
if (this.#pendingNode && this._expandedKeys.has(this.#pendingNode.item.key)) this.#abortPending();
|
|
2582
2586
|
this.tickled.handlePointerEnter(node.item.key);
|
|
2583
2587
|
this._focusedDepth = depth;
|
package/dist/tree.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as TreeDataModel, i as TreeDropController, n as TreeListElement, r as TreeBaseElement, t as TreeController } from "./tree-
|
|
1
|
+
import { a as TreeDataModel, i as TreeDropController, n as TreeListElement, r as TreeBaseElement, t as TreeController } from "./tree-BM2CY6uu.js";
|
|
2
2
|
export { TreeBaseElement, TreeController, TreeDataModel, TreeDropController, TreeListElement };
|
package/dist/vertical-list.js
CHANGED
|
@@ -1543,6 +1543,8 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
1543
1543
|
box-sizing: border-box;
|
|
1544
1544
|
outline: none;
|
|
1545
1545
|
--ixfx-list-item-padding: var(--ixfx-list-item-padding, var(--list-item-padding, 4px var(--space-m, 8px)));
|
|
1546
|
+
--_item-padding:
|
|
1547
|
+
var(--ixfx-list-item-padding, var(--list-item-padding, 0 var(--space-xs, 3px)));
|
|
1546
1548
|
}
|
|
1547
1549
|
|
|
1548
1550
|
:host(:focus-visible) {
|
|
@@ -1579,7 +1581,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
1579
1581
|
::slotted(li) {
|
|
1580
1582
|
display: flex;
|
|
1581
1583
|
align-items: center;
|
|
1582
|
-
padding: var(--
|
|
1584
|
+
padding: var(--_item-padding);
|
|
1583
1585
|
/* Inset each row from the scroll container's edges (margin, not padding:
|
|
1584
1586
|
padding is inside the border box, so the tickle/selection outlines
|
|
1585
1587
|
would still sit flush against the edge and be clipped). */
|
|
@@ -1701,6 +1703,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
1701
1703
|
background: transparent;
|
|
1702
1704
|
color: inherit;
|
|
1703
1705
|
outline: 1px solid transparent;
|
|
1706
|
+
padding: var(--space-s);
|
|
1704
1707
|
}
|
|
1705
1708
|
|
|
1706
1709
|
:host([interaction-mode="checked"]) ::slotted([data-selected][data-tickled]) {
|
package/docs-user/index.json
CHANGED
|
@@ -17,7 +17,7 @@ provider returns that column's choices; items may carry a `count` for display.
|
|
|
17
17
|
|
|
18
18
|
| Property | Type | Default | Description |
|
|
19
19
|
|----------|------|---------|-------------|
|
|
20
|
-
| `categories` | `readonly MulticolCategory[]` | `[]` | Facet definitions (tree, shown in the header picker menu). Each may carry `description` (shown as a tooltip on the column header label) and `defaults`: `grouped`, `groupBy`, `allLabel`, `sort`. |
|
|
20
|
+
| `categories` | `readonly MulticolCategory[]` | `[]` | Facet definitions (tree, shown in the header picker menu). Only leaves are selectable as a column's category; a node with `children` is just a menu group. Keys are resolved across the whole tree. Each may carry `description` (shown as a tooltip on the column header label) and `defaults`: `grouped`, `groupBy`, `allLabel`, `sort`. |
|
|
21
21
|
| `dataProvider` | `IDataProvider<MulticolQuery, MulticolItem>` \| `undefined` | — | Called per column whenever that column's inputs change. Sync arrays, Promises and async-iterables are supported; the `AbortSignal` is honoured. |
|
|
22
22
|
| `selectionMode` | `ListSelectionMode` | `'multiple'` | `'none'`, `'single'` or `'multiple'` selection within a column. |
|
|
23
23
|
| `minColumns` | `number` | `1` | Floor for column removal. |
|
package/docs-user/tree.md
CHANGED
|
@@ -160,7 +160,7 @@ Controls how pointer and keyboard gestures translate to selection changes.
|
|
|
160
160
|
| `'implicit'` | Single selection follows every click; click also toggles expand/collapse |
|
|
161
161
|
| `'standard'` | Plain click selects + toggles expand; Ctrl/Cmd+click toggles item; Shift+click range-selects |
|
|
162
162
|
| `'manual'` | Component never auto-selects; use `select()` / `deselect()` / `clearSelection()` to drive state |
|
|
163
|
-
| `'checked'` | Checkboxes on every row; checkbox
|
|
163
|
+
| `'checked'` | Checkboxes on every row; clicking the checkbox — or anywhere left of the label (indent, caret, icon) — recursively selects/deselects loaded descendants; label click only expands/collapses |
|
|
164
164
|
| `'vscode'` | Like `standard` for clicks; Shift+Up/Down uses snapshot-based toggle-range (VS Code file-explorer style) |
|
|
165
165
|
|
|
166
166
|
Switching `interactionMode` clears the current selection.
|
|
@@ -190,6 +190,8 @@ tree.checkboxRenderer = (state) => state === `unchecked`
|
|
|
190
190
|
|
|
191
191
|
When `checkboxRenderer` is set, the checkbox becomes a `<span class="tree-checkbox" role="checkbox" part="checkbox">` holding your template, with `aria-checked` set to `"true"`, `"false"`, or `"mixed"` to match the tri-state. The span owns the click (same as the native input), so clicking anywhere in it — including empty space when you render nothing for `unchecked` — toggles the row.
|
|
192
192
|
|
|
193
|
+
To keep the checkbox easy to aim at, the entire row region left of the label — indent gutter, checkbox, caret and icon — acts as one checkbox hit target in `checked` mode. Only clicks on the label itself expand/collapse.
|
|
194
|
+
|
|
193
195
|
Both the native input and the custom span expose the `checkbox` CSS part for external styling:
|
|
194
196
|
|
|
195
197
|
```css
|