@ixfx/components 0.13.9 → 0.14.1

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/dist/index.js CHANGED
@@ -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
@@ -9820,6 +9842,9 @@ let MulticolListElement = class MulticolListElement extends LitElement {
9820
9842
 
9821
9843
  display: block;
9822
9844
  overflow: hidden;
9845
+ /* A sideways trackpad swipe over the component must never pan it
9846
+ (or the page behind it, or trigger history navigation) */
9847
+ overscroll-behavior-x: none;
9823
9848
  background: var(--multicol-list-bg);
9824
9849
  color: var(--surface-3-text);
9825
9850
  font-family: var(--font-family);
@@ -9829,6 +9854,7 @@ let MulticolListElement = class MulticolListElement extends LitElement {
9829
9854
  flex-direction: row;
9830
9855
  align-items: stretch;
9831
9856
  overflow: hidden;
9857
+ overscroll-behavior-x: none;
9832
9858
  position: relative;
9833
9859
  height: 100%;
9834
9860
  }
@@ -9945,6 +9971,10 @@ let MulticolListElement = class MulticolListElement extends LitElement {
9945
9971
  flex: 1;
9946
9972
  overflow-y: auto;
9947
9973
  overflow-x: hidden;
9974
+ /* Vertical scrolling only: horizontal deltas are swallowed here
9975
+ instead of chaining up and panning the whole component */
9976
+ overscroll-behavior-x: none;
9977
+ touch-action: pan-y;
9948
9978
  position: relative;
9949
9979
  display: flex;
9950
9980
  flex-direction: column;
@@ -10002,7 +10032,7 @@ let MulticolListElement = class MulticolListElement extends LitElement {
10002
10032
  const existing = existingMap.get(colState.id);
10003
10033
  if (existing) {
10004
10034
  if (existing.categoryKey !== colState.categoryKey) {
10005
- const newCategory = this.categories.find((c) => c.key === colState.categoryKey);
10035
+ const newCategory = findLeafCategory(this.categories, colState.categoryKey);
10006
10036
  if (newCategory) existing.setCategory(newCategory);
10007
10037
  }
10008
10038
  existing.updateState(colState);
@@ -10010,7 +10040,7 @@ let MulticolListElement = class MulticolListElement extends LitElement {
10010
10040
  existingMap.delete(colState.id);
10011
10041
  continue;
10012
10042
  }
10013
- const category = this.categories.find((c) => c.key === colState.categoryKey);
10043
+ const category = findLeafCategory(this.categories, colState.categoryKey);
10014
10044
  if (!category) continue;
10015
10045
  const controller = this.#createController(colState.id, category);
10016
10046
  controller.updateState(colState);
@@ -10025,7 +10055,7 @@ let MulticolListElement = class MulticolListElement extends LitElement {
10025
10055
  }
10026
10056
  addColumn(categoryKey, position) {
10027
10057
  if (this.maxColumns > 0 && this._columns.length >= this.maxColumns) return;
10028
- const category = this.categories.find((c) => c.key === categoryKey);
10058
+ const category = findLeafCategory(this.categories, categoryKey);
10029
10059
  if (!category) return;
10030
10060
  const id = `col-${++this._idCounter}`;
10031
10061
  const controller = this.#createController(id, category);
@@ -10067,9 +10097,10 @@ let MulticolListElement = class MulticolListElement extends LitElement {
10067
10097
  `;
10068
10098
  }
10069
10099
  updated(changedProperties) {
10070
- if (!this._autoSeeded && this._columns.length === 0 && this.categories.length > 0) {
10100
+ const seedCategory = flattenCategories(this.categories)[0];
10101
+ if (!this._autoSeeded && this._columns.length === 0 && seedCategory) {
10071
10102
  this._autoSeeded = true;
10072
- this.addColumn(this.categories[0].key);
10103
+ this.addColumn(seedCategory.key);
10073
10104
  }
10074
10105
  if (changedProperties.has(`selectionMode`)) for (const col of this._columns) col.setSelectionMode(this.selectionMode);
10075
10106
  if (changedProperties.has(`dataProvider`)) for (const col of this._columns) col.setDataProvider(this.dataProvider);
@@ -10130,11 +10161,11 @@ let MulticolListElement = class MulticolListElement extends LitElement {
10130
10161
  `;
10131
10162
  }
10132
10163
  _getCategoryLabel(key) {
10133
- return this.categories.find((c) => c.key === key)?.label ?? key;
10164
+ return findCategory(this.categories, key)?.label ?? key;
10134
10165
  }
10135
10166
  /** Category description if present, else the default 'Change category' hint. */
10136
10167
  _getCategoryTooltip(key) {
10137
- return this.categories.find((c) => c.key === key)?.description ?? `Change category`;
10168
+ return findCategory(this.categories, key)?.description ?? `Change category`;
10138
10169
  }
10139
10170
  #createController(id, category) {
10140
10171
  return new MulticolColumnController({
@@ -10305,7 +10336,7 @@ let MulticolListElement = class MulticolListElement extends LitElement {
10305
10336
  container.appendChild(separator);
10306
10337
  const atMax = this.maxColumns > 0 && this._columns.length >= this.maxColumns;
10307
10338
  const usedCats = new Set(this._columns.map((c) => c.categoryKey));
10308
- const unused = this.categories.filter((c) => !usedCats.has(c.key));
10339
+ const unused = flattenCategories(this.categories).filter((c) => !usedCats.has(c.key));
10309
10340
  const canAdd = !atMax && unused.length > 0;
10310
10341
  const addSub = document.createElement(`ixfx-menu-sub-trigger`);
10311
10342
  addSub.setAttribute(`label`, `Add column`);
@@ -10349,7 +10380,7 @@ let MulticolListElement = class MulticolListElement extends LitElement {
10349
10380
  this.addColumn(categoryKey, position);
10350
10381
  }
10351
10382
  _changeColumnCategory(col, categoryKey) {
10352
- const category = this.categories.find((c) => c.key === categoryKey);
10383
+ const category = findLeafCategory(this.categories, categoryKey);
10353
10384
  if (!category) return;
10354
10385
  col.setCategory(category);
10355
10386
  this._emitColumnsChange(`category`);
@@ -10385,10 +10416,11 @@ let MulticolListElement = class MulticolListElement extends LitElement {
10385
10416
  }
10386
10417
  _syncColumnsWithCategories() {
10387
10418
  let changed = false;
10419
+ const leaves = flattenCategories(this.categories);
10388
10420
  for (const col of this._columns) {
10389
- if (this.categories.some((c) => c.key === col.categoryKey)) continue;
10390
- if (this.categories.length === 0) continue;
10391
- col.setCategory(this.categories[0]);
10421
+ if (leaves.some((c) => c.key === col.categoryKey)) continue;
10422
+ if (leaves.length === 0) continue;
10423
+ col.setCategory(leaves[0]);
10392
10424
  changed = true;
10393
10425
  }
10394
10426
  if (changed) this._emitColumnsChange(`category`);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ixfx/components",
3
- "version": "0.13.9",
4
- "generated": "2026-10-09T19:37:11.157Z",
3
+ "version": "0.14.1",
4
+ "generated": "2026-10-09T22:40:55.145Z",
5
5
  "components": [
6
6
  {
7
7
  "name": "ac-text",
@@ -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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ixfx/components",
3
3
  "type": "module",
4
- "version": "0.13.9",
4
+ "version": "0.14.1",
5
5
  "packageManager": "pnpm@10.0.0",
6
6
  "description": "Web components for ixfx — Lit-based UI toolkit",
7
7
  "author": "Clint Heyer",