@ixfx/components 0.10.0 → 0.10.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/bundle/index.d.ts +60 -1
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +257 -30
- package/bundle/index.js.map +1 -1
- package/bundle/style.css +38 -85
- package/dist/ac-text.d.ts +1 -1
- package/dist/{ac-token--_vCHXWw.d.ts → ac-token-TCLAZeVg.d.ts} +2 -2
- package/dist/{ac-token--_vCHXWw.d.ts.map → ac-token-TCLAZeVg.d.ts.map} +1 -1
- package/dist/ac-token.d.ts +1 -1
- package/dist/button.d.ts +1 -1
- package/dist/button.d.ts.map +1 -1
- package/dist/colour-picker.d.ts +1 -1
- package/dist/crumbs.d.ts +2 -2
- package/dist/{data-grid-C5hk_pzK.d.ts → data-grid-BT1d_nlu.d.ts} +4 -4
- package/dist/{data-grid-C5hk_pzK.d.ts.map → data-grid-BT1d_nlu.d.ts.map} +1 -1
- package/dist/data-grid.d.ts +2 -2
- package/dist/data-grid.js +1 -1
- package/dist/{detail-list-CxPpv89T.d.ts → detail-list-BCaIN7nx.d.ts} +5 -5
- package/dist/{detail-list-CxPpv89T.d.ts.map → detail-list-BCaIN7nx.d.ts.map} +1 -1
- package/dist/detail-list.d.ts +3 -3
- package/dist/detail-list.js +1 -1
- package/dist/{grid-list-BGvoWbZz.d.ts → grid-list-CiwlNE4c.d.ts} +4 -4
- package/dist/{grid-list-BGvoWbZz.d.ts.map → grid-list-CiwlNE4c.d.ts.map} +1 -1
- package/dist/{grid-list-DSnYOGh7.js → grid-list-DLfw5HI4.js} +10 -5
- package/dist/grid-list-DLfw5HI4.js.map +1 -0
- package/dist/grid-list.d.ts +2 -2
- package/dist/grid-list.js +1 -1
- package/dist/{grouped-item-lister-fdZHVxFM.d.ts → grouped-item-lister-CEZ72VOs.d.ts} +2 -2
- package/dist/{grouped-item-lister-fdZHVxFM.d.ts.map → grouped-item-lister-CEZ72VOs.d.ts.map} +1 -1
- package/dist/grouped-item-lister.d.ts +1 -1
- package/dist/{icon-CDGprSdE.d.ts → icon-DR_3rSyZ.d.ts} +2 -2
- package/dist/icon-DR_3rSyZ.d.ts.map +1 -0
- package/dist/icons.d.ts +2 -2
- package/dist/incr-search.d.ts +1 -1
- package/dist/{index-tq6f8007.d.ts → index-BOUaDIW-.d.ts} +2 -2
- package/dist/{index-tq6f8007.d.ts.map → index-BOUaDIW-.d.ts.map} +1 -1
- package/dist/{index-CoqtMSd9.d.ts → index-BUB5SICW.d.ts} +2 -2
- package/dist/{index-CoqtMSd9.d.ts.map → index-BUB5SICW.d.ts.map} +1 -1
- package/dist/{index-9AhaHIT2.d.ts → index-C59-JEPl.d.ts} +3 -3
- package/dist/{index-9AhaHIT2.d.ts.map → index-C59-JEPl.d.ts.map} +1 -1
- package/dist/{index-UvnoZUAo.d.ts → index-CJ5fshD3.d.ts} +2 -2
- package/dist/{index-UvnoZUAo.d.ts.map → index-CJ5fshD3.d.ts.map} +1 -1
- package/dist/{index--5BSdbnL.d.ts → index-DPFrRhKL.d.ts} +2 -2
- package/dist/{index--5BSdbnL.d.ts.map → index-DPFrRhKL.d.ts.map} +1 -1
- package/dist/{index-CS9yM8L-.d.ts → index-DsjpDksO.d.ts} +2 -2
- package/dist/{index-CS9yM8L-.d.ts.map → index-DsjpDksO.d.ts.map} +1 -1
- package/dist/index.d.ts +66 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +247 -27
- package/dist/index.js.map +1 -1
- package/dist/{labelled-input-base-DiTme1JO.d.ts → labelled-input-base-Dp_9KP0G.d.ts} +2 -2
- package/dist/{labelled-input-base-DiTme1JO.d.ts.map → labelled-input-base-Dp_9KP0G.d.ts.map} +1 -1
- package/dist/labelled-radial-input.d.ts +2 -2
- package/dist/labelled-radial-input.d.ts.map +1 -1
- package/dist/labelled-range-input.d.ts +1 -1
- package/dist/labelled-slider-input.d.ts +1 -1
- package/dist/{list-native-drag-controller-D97TYjn1.js → list-native-drag-controller-B9xO0XWn.js} +6 -4
- package/dist/list-native-drag-controller-B9xO0XWn.js.map +1 -0
- package/dist/{list-native-drag-controller-DWiXQZou.d.ts → list-native-drag-controller-BAuWAtyQ.d.ts} +2 -2
- package/dist/{list-native-drag-controller-DWiXQZou.d.ts.map → list-native-drag-controller-BAuWAtyQ.d.ts.map} +1 -1
- package/dist/{menu-item-CZi9vy5O.d.ts → menu-item-ZmkXNjek.d.ts} +2 -2
- package/dist/{menu-item-CZi9vy5O.d.ts.map → menu-item-ZmkXNjek.d.ts.map} +1 -1
- package/dist/menu.d.ts +2 -2
- package/dist/miller.d.ts +2 -2
- package/dist/panel.d.ts +1 -1
- package/dist/{split-layout-JK3xWVX2.d.ts → split-layout-C5SYbDrq.d.ts} +2 -2
- package/dist/{split-layout-JK3xWVX2.d.ts.map → split-layout-C5SYbDrq.d.ts.map} +1 -1
- package/dist/split-layout.d.ts +1 -1
- package/dist/style.css +38 -85
- package/dist/{tab-list-CGyPt07Z.d.ts → tab-list-DbMIL520.d.ts} +2 -2
- package/dist/{tab-list-CGyPt07Z.d.ts.map → tab-list-DbMIL520.d.ts.map} +1 -1
- package/dist/tabs.d.ts +1 -1
- package/dist/{titlebar-Tqu-VvMU.d.ts → titlebar-B5zSTZnF.d.ts} +2 -2
- package/dist/{titlebar-Tqu-VvMU.d.ts.map → titlebar-B5zSTZnF.d.ts.map} +1 -1
- package/dist/titlebar.d.ts +1 -1
- package/dist/{tree-C25xYUa6.js → tree-BuzWn18_.js} +2 -2
- package/dist/{tree-C25xYUa6.js.map → tree-BuzWn18_.js.map} +1 -1
- package/dist/{tree-component-mw8x-n2Y.d.ts → tree-component-DGmKBbpy.d.ts} +14 -1
- package/dist/tree-component-DGmKBbpy.d.ts.map +1 -0
- package/dist/tree.d.ts +3 -3
- package/dist/tree.js +1 -1
- package/dist/{vertical-list--tFanQwM.d.ts → vertical-list-BLvJ4-Zf.d.ts} +3 -3
- package/dist/{vertical-list--tFanQwM.d.ts.map → vertical-list-BLvJ4-Zf.d.ts.map} +1 -1
- package/dist/vertical-list.d.ts +2 -2
- package/dist/vertical-list.js +1 -1
- package/docs-user/index.json +2 -2
- package/package.json +1 -1
- package/dist/grid-list-DSnYOGh7.js.map +0 -1
- package/dist/icon-CDGprSdE.d.ts.map +0 -1
- package/dist/list-native-drag-controller-D97TYjn1.js.map +0 -1
- package/dist/tree-component-mw8x-n2Y.d.ts.map +0 -1
package/bundle/index.js
CHANGED
|
@@ -5707,14 +5707,12 @@ function fontOf(style) {
|
|
|
5707
5707
|
} catch {}
|
|
5708
5708
|
return `12px system-ui, sans-serif`;
|
|
5709
5709
|
}
|
|
5710
|
-
/** Caption for a drag entry — element labels win, then
|
|
5710
|
+
/** Caption for a drag entry — explicit element labels win, then data values, then generic element text, then the key. */
|
|
5711
5711
|
function captionForEntry(entry) {
|
|
5712
5712
|
const el = entry.element ?? (entry.item instanceof Element ? entry.item : void 0);
|
|
5713
5713
|
if (el) {
|
|
5714
5714
|
const labelled = el.getAttribute(`data-label`) ?? el.querySelector(`[data-grid-list-caption]`)?.textContent?.trim() ?? el.getAttribute(`data-search-label`) ?? el.querySelector(`.cell`)?.textContent?.trim();
|
|
5715
5715
|
if (labelled) return labelled.slice(0, 80);
|
|
5716
|
-
const text = el.textContent?.trim();
|
|
5717
|
-
if (text) return text.slice(0, 80);
|
|
5718
5716
|
}
|
|
5719
5717
|
const item = entry.item;
|
|
5720
5718
|
if (typeof item === `string` && item.length > 0) return item.slice(0, 80);
|
|
@@ -5730,6 +5728,10 @@ function captionForEntry(entry) {
|
|
|
5730
5728
|
if (typeof value === `string` && value.length > 0) return value.slice(0, 80);
|
|
5731
5729
|
}
|
|
5732
5730
|
}
|
|
5731
|
+
if (el) {
|
|
5732
|
+
const text = el.textContent?.trim();
|
|
5733
|
+
if (text) return text.slice(0, 80);
|
|
5734
|
+
}
|
|
5733
5735
|
return entry.key;
|
|
5734
5736
|
}
|
|
5735
5737
|
function glyphFor(caption) {
|
|
@@ -23784,6 +23786,10 @@ let GridListElement = class GridListElement extends i {
|
|
|
23784
23786
|
#postDragSuppressTimer;
|
|
23785
23787
|
#nativeDrag;
|
|
23786
23788
|
/** Origin rule + display-ordered entry resolution for native drag-out (both modes). */
|
|
23789
|
+
#renderedCellForKey(key) {
|
|
23790
|
+
const selector = `.cell[data-key="${CSS.escape(key)}"]`;
|
|
23791
|
+
return this.renderRoot.querySelector(selector) ?? void 0;
|
|
23792
|
+
}
|
|
23787
23793
|
#prepareNativeDrag(originKey) {
|
|
23788
23794
|
const index = this.#source.indexOfKey(originKey);
|
|
23789
23795
|
if (index < 0 || !this.#source.isSelectable(index)) return void 0;
|
|
@@ -23794,14 +23800,15 @@ let GridListElement = class GridListElement extends i {
|
|
|
23794
23800
|
const entryIndex = this.#source.indexOfKey(key);
|
|
23795
23801
|
if (entryIndex < 0) continue;
|
|
23796
23802
|
const data = this.#source.resolveKeyToData(key);
|
|
23797
|
-
const
|
|
23798
|
-
const
|
|
23803
|
+
const sourceElement = this.#source.resolveKeyToElement(key);
|
|
23804
|
+
const renderedElement = sourceElement ?? (this.#source instanceof DataGridListSource ? this.#renderedCellForKey(key) : void 0);
|
|
23805
|
+
const item = data ?? sourceElement;
|
|
23799
23806
|
if (item === void 0) continue;
|
|
23800
23807
|
selected.push({
|
|
23801
23808
|
key,
|
|
23802
23809
|
index: entryIndex,
|
|
23803
23810
|
item,
|
|
23804
|
-
...
|
|
23811
|
+
...renderedElement ? { element: renderedElement } : {}
|
|
23805
23812
|
});
|
|
23806
23813
|
}
|
|
23807
23814
|
const origin = selected.find((entry) => entry.key === originKey);
|
|
@@ -45932,12 +45939,16 @@ function subdivide(box, weights, method, relativeDepth) {
|
|
|
45932
45939
|
*/
|
|
45933
45940
|
function computeTreemapLayout(root, options = {}) {
|
|
45934
45941
|
if (!root?.children?.length) return [];
|
|
45935
|
-
const { maxDepth = Number.POSITIVE_INFINITY, valueAccessor = () => 1, zoomKey, tilingMethod = `squarify
|
|
45942
|
+
const { maxDepth = Number.POSITIVE_INFINITY, valueAccessor = () => 1, zoomKey, tilingMethod = `squarify`, hideLeaves = false } = options;
|
|
45936
45943
|
if (maxDepth <= 0) return [];
|
|
45944
|
+
const visibleChildren = (node) => {
|
|
45945
|
+
const children = node.children ?? [];
|
|
45946
|
+
return hideLeaves ? children.filter((n) => n.item.isLeaf !== true) : children;
|
|
45947
|
+
};
|
|
45937
45948
|
const zoomNode = zoomKey === void 0 ? root : findTreemapNode(root, zoomKey) ?? root;
|
|
45938
45949
|
const zoomPath = findTreemapPath(root, zoomNode.item.key);
|
|
45939
45950
|
const zoomDepth = zoomPath ? zoomPath.length - 2 : -1;
|
|
45940
|
-
const siblings = zoomNode
|
|
45951
|
+
const siblings = visibleChildren(zoomNode);
|
|
45941
45952
|
if (siblings.length === 0) return [];
|
|
45942
45953
|
const rects = [];
|
|
45943
45954
|
const layoutLevel = (nodes, box, depth, relativeDepth, parentKey) => {
|
|
@@ -45946,7 +45957,7 @@ function computeTreemapLayout(root, options = {}) {
|
|
|
45946
45957
|
const setSize = nodes.length;
|
|
45947
45958
|
nodes.forEach((node, index) => {
|
|
45948
45959
|
const childBox = boxes[index];
|
|
45949
|
-
const children = node
|
|
45960
|
+
const children = visibleChildren(node);
|
|
45950
45961
|
rects.push({
|
|
45951
45962
|
node,
|
|
45952
45963
|
depth,
|
|
@@ -45981,8 +45992,11 @@ let TreemapListElement = class TreemapListElement extends i {
|
|
|
45981
45992
|
this.interactionMode = `standard`;
|
|
45982
45993
|
this.tilingMethod = `squarify`;
|
|
45983
45994
|
this.maxDepth = 4;
|
|
45995
|
+
this.hideLeaves = false;
|
|
45984
45996
|
this.minLabelArea = 1600;
|
|
45997
|
+
this.minTileWidth = 24;
|
|
45985
45998
|
this.padding = 4;
|
|
45999
|
+
this.minChildArea = 400;
|
|
45986
46000
|
this.valueAccessor = () => 1;
|
|
45987
46001
|
this._selectedNodes = /* @__PURE__ */ new Set();
|
|
45988
46002
|
this.disableKeyboardNavigation = false;
|
|
@@ -46016,6 +46030,7 @@ let TreemapListElement = class TreemapListElement extends i {
|
|
|
46016
46030
|
});
|
|
46017
46031
|
this.#pendingKeys = /* @__PURE__ */ new Set();
|
|
46018
46032
|
this.#aborters = /* @__PURE__ */ new Map();
|
|
46033
|
+
this.#wheelCooldownUntil = 0;
|
|
46019
46034
|
}
|
|
46020
46035
|
get selectedNodes() {
|
|
46021
46036
|
return this._selectedNodes;
|
|
@@ -46032,15 +46047,22 @@ let TreemapListElement = class TreemapListElement extends i {
|
|
|
46032
46047
|
#ownedRegistry;
|
|
46033
46048
|
#unregisterSearchCommands;
|
|
46034
46049
|
#resizeObserver;
|
|
46050
|
+
#pendingFlip;
|
|
46051
|
+
/** `performance.now()` timestamp before which further Cmd+wheel zoom steps are ignored. */
|
|
46052
|
+
#wheelCooldownUntil;
|
|
46035
46053
|
get #effectiveRoot() {
|
|
46036
46054
|
return this.model?.root ?? this.root;
|
|
46037
46055
|
}
|
|
46038
46056
|
#rects() {
|
|
46057
|
+
return this.#rectsForZoom(this._zoomKey);
|
|
46058
|
+
}
|
|
46059
|
+
#rectsForZoom(zoomKey) {
|
|
46039
46060
|
return computeTreemapLayout(this.#effectiveRoot, {
|
|
46040
46061
|
valueAccessor: this.valueAccessor,
|
|
46041
46062
|
maxDepth: this.maxDepth,
|
|
46042
|
-
zoomKey
|
|
46043
|
-
tilingMethod: this.tilingMethod
|
|
46063
|
+
zoomKey,
|
|
46064
|
+
tilingMethod: this.tilingMethod,
|
|
46065
|
+
hideLeaves: this.hideLeaves
|
|
46044
46066
|
});
|
|
46045
46067
|
}
|
|
46046
46068
|
connectedCallback() {
|
|
@@ -46116,8 +46138,14 @@ let TreemapListElement = class TreemapListElement extends i {
|
|
|
46116
46138
|
if (changedProps.has(`searchModes`)) this.#syncSearchCommands();
|
|
46117
46139
|
if (this._zoomKey !== void 0 && !findTreemapNode(this.#effectiveRoot, this._zoomKey)) this._zoomKey = void 0;
|
|
46118
46140
|
this.#ensureVisibleChildren();
|
|
46141
|
+
if (this.#pendingFlip) {
|
|
46142
|
+
const flip = this.#pendingFlip;
|
|
46143
|
+
this.#pendingFlip = void 0;
|
|
46144
|
+
this.#applyFlip(flip);
|
|
46145
|
+
}
|
|
46119
46146
|
}
|
|
46120
46147
|
#resetViewState() {
|
|
46148
|
+
this.#pendingFlip = void 0;
|
|
46121
46149
|
this.#clearSelectionInternal();
|
|
46122
46150
|
this.tickled.clearTickled();
|
|
46123
46151
|
this._zoomKey = void 0;
|
|
@@ -46230,6 +46258,7 @@ let TreemapListElement = class TreemapListElement extends i {
|
|
|
46230
46258
|
*/
|
|
46231
46259
|
zoomTo(node) {
|
|
46232
46260
|
if (this._zoomKey === node.item.key) return;
|
|
46261
|
+
this.#pendingFlip = this.#planFlip(node.item.key);
|
|
46233
46262
|
this._zoomKey = node.item.key;
|
|
46234
46263
|
this.tickled.clearTickled();
|
|
46235
46264
|
const depth = findTreemapPath(this.#effectiveRoot, node.item.key)?.length;
|
|
@@ -46258,6 +46287,7 @@ let TreemapListElement = class TreemapListElement extends i {
|
|
|
46258
46287
|
*/
|
|
46259
46288
|
zoomOut() {
|
|
46260
46289
|
if (this._zoomKey === void 0) return;
|
|
46290
|
+
this.#pendingFlip = this.#planFlip(void 0);
|
|
46261
46291
|
const previous = this.focusedNode;
|
|
46262
46292
|
const path = this._zoomKey === void 0 ? void 0 : findTreemapPath(this.#effectiveRoot, this._zoomKey);
|
|
46263
46293
|
const absoluteDepth = path === void 0 ? -1 : path.length - 2;
|
|
@@ -46281,9 +46311,66 @@ let TreemapListElement = class TreemapListElement extends i {
|
|
|
46281
46311
|
}));
|
|
46282
46312
|
this.requestUpdate();
|
|
46283
46313
|
}
|
|
46314
|
+
/**
|
|
46315
|
+
* Work out (before `_zoomKey` changes) whether the upcoming zoom should
|
|
46316
|
+
* animate, and how — see `FlipPlan`. Returns `undefined` to skip the
|
|
46317
|
+
* animation: reduced-motion is requested, or the node needed to anchor it
|
|
46318
|
+
* isn't in either the old or new layout's visible window.
|
|
46319
|
+
*/
|
|
46320
|
+
#planFlip(targetKey) {
|
|
46321
|
+
if (typeof matchMedia === `function` && matchMedia(`(prefers-reduced-motion: reduce)`).matches) return void 0;
|
|
46322
|
+
if (targetKey !== void 0) {
|
|
46323
|
+
const visible = this.#rects().find((r) => r.node.item.key === targetKey);
|
|
46324
|
+
if (visible) return {
|
|
46325
|
+
direction: `in`,
|
|
46326
|
+
rect: {
|
|
46327
|
+
x: visible.x,
|
|
46328
|
+
y: visible.y,
|
|
46329
|
+
width: visible.width,
|
|
46330
|
+
height: visible.height
|
|
46331
|
+
}
|
|
46332
|
+
};
|
|
46333
|
+
}
|
|
46334
|
+
const fromKey = this._zoomKey;
|
|
46335
|
+
if (fromKey === void 0) return void 0;
|
|
46336
|
+
const landing = this.#rectsForZoom(targetKey).find((r) => r.node.item.key === fromKey);
|
|
46337
|
+
if (!landing) return void 0;
|
|
46338
|
+
return {
|
|
46339
|
+
direction: `out`,
|
|
46340
|
+
rect: {
|
|
46341
|
+
x: landing.x,
|
|
46342
|
+
y: landing.y,
|
|
46343
|
+
width: landing.width,
|
|
46344
|
+
height: landing.height
|
|
46345
|
+
}
|
|
46346
|
+
};
|
|
46347
|
+
}
|
|
46348
|
+
/** Apply a planned FLIP animation once the new layout has rendered — see `FlipPlan`. */
|
|
46349
|
+
#applyFlip(flip) {
|
|
46350
|
+
const inner = this.renderRoot.querySelector(`.viewport-inner`);
|
|
46351
|
+
const viewport = this.renderRoot.querySelector(`.viewport`);
|
|
46352
|
+
if (!(inner instanceof HTMLElement) || !(viewport instanceof HTMLElement)) return;
|
|
46353
|
+
const vw = viewport.clientWidth;
|
|
46354
|
+
const vh = viewport.clientHeight;
|
|
46355
|
+
if (vw <= 0 || vh <= 0) return;
|
|
46356
|
+
const { rect, direction } = flip;
|
|
46357
|
+
const startTransform = direction === `in` ? `translate(${rect.x * vw}px, ${rect.y * vh}px) scale(${Math.max(rect.width, 1e-4)}, ${Math.max(rect.height, 1e-4)})` : (() => {
|
|
46358
|
+
const sx = rect.width > 0 ? 1 / rect.width : 1;
|
|
46359
|
+
const sy = rect.height > 0 ? 1 / rect.height : 1;
|
|
46360
|
+
return `translate(${-rect.x * sx * vw}px, ${-rect.y * sy * vh}px) scale(${sx}, ${sy})`;
|
|
46361
|
+
})();
|
|
46362
|
+
inner.classList.remove(`flipping`);
|
|
46363
|
+
inner.style.transform = startTransform;
|
|
46364
|
+
inner.offsetWidth;
|
|
46365
|
+
requestAnimationFrame(() => {
|
|
46366
|
+
inner.classList.add(`flipping`);
|
|
46367
|
+
inner.style.transform = `none`;
|
|
46368
|
+
});
|
|
46369
|
+
inner.addEventListener(`transitionend`, () => inner.classList.remove(`flipping`), { once: true });
|
|
46370
|
+
}
|
|
46284
46371
|
#canZoom(node) {
|
|
46285
46372
|
if (node.item.isLeaf === true) return false;
|
|
46286
|
-
if (node.children !== void 0) return node.children.length > 0;
|
|
46373
|
+
if (node.children !== void 0) return this.hideLeaves ? node.children.some((n) => n.item.isLeaf !== true) : node.children.length > 0;
|
|
46287
46374
|
return this.model !== void 0 || this.loadChildren !== void 0;
|
|
46288
46375
|
}
|
|
46289
46376
|
/**
|
|
@@ -46510,6 +46597,39 @@ let TreemapListElement = class TreemapListElement extends i {
|
|
|
46510
46597
|
}
|
|
46511
46598
|
}
|
|
46512
46599
|
}
|
|
46600
|
+
/**
|
|
46601
|
+
* Cmd+wheel zooms: scrolling backward (deltaY < 0, towards the user) zooms
|
|
46602
|
+
* into the tile under the pointer — the same as clicking it; scrolling
|
|
46603
|
+
* forward (deltaY > 0, away from the user) zooms out one level at a time
|
|
46604
|
+
* (see `#zoomOutOneStep`), not straight to the root. Plain wheel (no Cmd)
|
|
46605
|
+
* is left alone for normal page scroll. A short cooldown after each step
|
|
46606
|
+
* keeps a single trackpad gesture (which fires many small wheel events)
|
|
46607
|
+
* from firing a cascade of zoom steps.
|
|
46608
|
+
*/
|
|
46609
|
+
#handleWheel(event) {
|
|
46610
|
+
if (!event.metaKey || event.deltaY === 0) return;
|
|
46611
|
+
event.preventDefault();
|
|
46612
|
+
if (performance.now() < this.#wheelCooldownUntil) return;
|
|
46613
|
+
if (event.deltaY > 0) {
|
|
46614
|
+
if (this._zoomKey === void 0) return;
|
|
46615
|
+
this.#wheelCooldownUntil = performance.now() + 260;
|
|
46616
|
+
this.#zoomOutOneStep();
|
|
46617
|
+
return;
|
|
46618
|
+
}
|
|
46619
|
+
const key = (event.target?.closest(`.tile`))?.getAttribute(`data-key`) ?? void 0;
|
|
46620
|
+
if (key === void 0) return;
|
|
46621
|
+
const rect = this.#rects().find((r) => r.node.item.key === key);
|
|
46622
|
+
if (!rect || !this.#canZoom(rect.node)) return;
|
|
46623
|
+
this.#wheelCooldownUntil = performance.now() + 260;
|
|
46624
|
+
this.zoomTo(rect.node);
|
|
46625
|
+
}
|
|
46626
|
+
/** Zoom to the current zoom node's parent, or fully out when it's a direct child of the root. */
|
|
46627
|
+
#zoomOutOneStep() {
|
|
46628
|
+
const path = this._zoomKey === void 0 ? void 0 : findTreemapPath(this.#effectiveRoot, this._zoomKey);
|
|
46629
|
+
const parent = path && path.length > 2 ? path[path.length - 2] : void 0;
|
|
46630
|
+
if (parent) this.zoomTo(parent);
|
|
46631
|
+
else this.zoomOut();
|
|
46632
|
+
}
|
|
46513
46633
|
#renderBreadcrumb() {
|
|
46514
46634
|
const zoomNode = this.focusedNode;
|
|
46515
46635
|
if (zoomNode === void 0) return A;
|
|
@@ -46539,25 +46659,60 @@ let TreemapListElement = class TreemapListElement extends i {
|
|
|
46539
46659
|
if (node.item.key === this.#effectiveRoot?.item.key) this.zoomOut();
|
|
46540
46660
|
else this.zoomTo(node);
|
|
46541
46661
|
}
|
|
46542
|
-
|
|
46662
|
+
/** On-screen size (px) of `rect`, or `undefined` before the host has been measured. */
|
|
46663
|
+
#pixelSize(rect) {
|
|
46543
46664
|
const hostWidth = this.clientWidth || 0;
|
|
46544
46665
|
const hostHeight = this.clientHeight || 0;
|
|
46545
|
-
if (hostWidth <= 0 || hostHeight <= 0) return
|
|
46546
|
-
return
|
|
46666
|
+
if (hostWidth <= 0 || hostHeight <= 0) return void 0;
|
|
46667
|
+
return {
|
|
46668
|
+
width: rect.width * hostWidth,
|
|
46669
|
+
height: rect.height * hostHeight
|
|
46670
|
+
};
|
|
46671
|
+
}
|
|
46672
|
+
/** Hide when too small by area, or too narrow to fit any readable text even truncated. */
|
|
46673
|
+
#hideLabel(rect) {
|
|
46674
|
+
const size = this.#pixelSize(rect);
|
|
46675
|
+
if (size === void 0) return false;
|
|
46676
|
+
return size.width * size.height < this.minLabelArea || size.width < this.minTileWidth;
|
|
46677
|
+
}
|
|
46678
|
+
/** Whether `rect` is large enough on-screen for its own children to be subdivided and drawn. */
|
|
46679
|
+
#canDescend(rect) {
|
|
46680
|
+
const size = this.#pixelSize(rect);
|
|
46681
|
+
if (size === void 0) return true;
|
|
46682
|
+
return size.width * size.height >= this.minChildArea && size.width >= this.minTileWidth;
|
|
46683
|
+
}
|
|
46684
|
+
/** Slugify a category name into a CSS custom-property-safe token. */
|
|
46685
|
+
#categorySlug(category) {
|
|
46686
|
+
return category.replace(/[^\w-]/g, `-`);
|
|
46547
46687
|
}
|
|
46548
|
-
|
|
46688
|
+
/**
|
|
46689
|
+
* Inline colour overrides for `node`'s category, or `undefined` for none.
|
|
46690
|
+
* Set as real `background-color`/`color` (not custom properties) so they
|
|
46691
|
+
* simply win over `.tile`'s CSS-variable-driven defaults by specificity —
|
|
46692
|
+
* no risk of an unresolvable `var()` chain leaving the property invalid.
|
|
46693
|
+
*/
|
|
46694
|
+
#categoryStyle(node) {
|
|
46695
|
+
const category = this.categoryAccessor?.(node.item);
|
|
46696
|
+
if (!category) return void 0;
|
|
46697
|
+
const slug = this.#categorySlug(category);
|
|
46698
|
+
return `background-color:var(--treemap-category-${slug}-bg, var(--treemap-tile-bg));color:var(--treemap-category-${slug}-text, var(--treemap-tile-text));`;
|
|
46699
|
+
}
|
|
46700
|
+
#renderTileBox(rect, positionStyle, hasVisibleChildren, childrenContent) {
|
|
46549
46701
|
const { node } = rect;
|
|
46550
46702
|
const selected = this._selectedNodes.has(node);
|
|
46551
46703
|
const tickled = this.tickled.isTickled(node.item.key);
|
|
46552
46704
|
const filtered = !this.#matchesFilter(node, rect.depth);
|
|
46553
46705
|
const pending = this.#pendingKeys.has(node.item.key);
|
|
46554
46706
|
const hideLabel = this.#hideLabel(rect);
|
|
46555
|
-
const showHeader =
|
|
46707
|
+
const showHeader = hasVisibleChildren && !hideLabel;
|
|
46708
|
+
const category = this.categoryAccessor?.(node.item);
|
|
46709
|
+
const categoryStyle = this.#categoryStyle(node);
|
|
46556
46710
|
return b`
|
|
46557
46711
|
<div
|
|
46558
|
-
class="item tile ${
|
|
46712
|
+
class="item tile ${selected ? `selected` : ``} ${tickled ? `tickled` : ``} ${filtered ? `filtered` : ``} ${pending ? `loading` : ``} ${rect.width <= 0 || rect.height <= 0 ? `empty` : ``}"
|
|
46559
46713
|
data-key=${node.item.key}
|
|
46560
46714
|
data-depth=${rect.relativeDepth}
|
|
46715
|
+
data-category=${category ?? A}
|
|
46561
46716
|
role="treeitem"
|
|
46562
46717
|
tabindex="-1"
|
|
46563
46718
|
aria-level=${rect.depth + 1}
|
|
@@ -46567,7 +46722,7 @@ let TreemapListElement = class TreemapListElement extends i {
|
|
|
46567
46722
|
aria-label=${node.item.label}
|
|
46568
46723
|
title=${node.item.label}
|
|
46569
46724
|
part="tile"
|
|
46570
|
-
style=${positionStyle}
|
|
46725
|
+
style=${categoryStyle ? `${positionStyle};${categoryStyle}` : positionStyle}
|
|
46571
46726
|
@click=${(e) => {
|
|
46572
46727
|
e.stopPropagation();
|
|
46573
46728
|
this.#handleItemClick(rect, this.#rects().findIndex((r) => r.node.item.key === node.item.key), e);
|
|
@@ -46579,23 +46734,46 @@ let TreemapListElement = class TreemapListElement extends i {
|
|
|
46579
46734
|
@pointerenter=${() => this.tickled.handlePointerEnter(node.item.key)}
|
|
46580
46735
|
>
|
|
46581
46736
|
${showHeader ? b`<div class="tile-header" part="tile-header"><span class="treemap-label" part="label">${node.item.label}</span></div>` : b`<span class="treemap-label ${hideLabel ? `hide-label` : ``}" part="label">${node.item.label}</span>`}
|
|
46582
|
-
${
|
|
46583
|
-
<div class="tile-children" role="group">
|
|
46584
|
-
${repeat(children, (r) => r.node.item.key, (r) => this.#renderNestedTile(r, rect, byParent))}
|
|
46585
|
-
</div>
|
|
46586
|
-
` : A}
|
|
46737
|
+
${childrenContent}
|
|
46587
46738
|
</div>
|
|
46588
46739
|
`;
|
|
46589
46740
|
}
|
|
46741
|
+
/**
|
|
46742
|
+
* Render `rect` plus (if it's large enough to descend into — see
|
|
46743
|
+
* `#canDescend`) a `.tile-children` holding its own children, each
|
|
46744
|
+
* positioned relative to `rect` itself and recursing the same way.
|
|
46745
|
+
*
|
|
46746
|
+
* Each level gets its own real `.tile-header` + `.tile-children` box, so a
|
|
46747
|
+
* header reserves its own space via normal box-model layout (flex column:
|
|
46748
|
+
* header, then the remaining space for children) at *every* level — not
|
|
46749
|
+
* just the top one. That matters because layout rects are purely
|
|
46750
|
+
* geometric (no allowance for header height), so a folder whose one child
|
|
46751
|
+
* fills ~100% of its area gets a child rect nearly identical to its own;
|
|
46752
|
+
* positioning that child against its direct parent (not some flattened
|
|
46753
|
+
* shared ancestor) is what keeps the parent's header from being painted
|
|
46754
|
+
* over by an opaque, near-identically-sized child box.
|
|
46755
|
+
*/
|
|
46756
|
+
#renderTile(rect, positionStyle, byParent) {
|
|
46757
|
+
const children = rect.hasChildren && this.#canDescend(rect) ? byParent.get(rect.node.item.key) ?? [] : [];
|
|
46758
|
+
const childrenContent = children.length > 0 ? b`
|
|
46759
|
+
<div class="tile-children" role="group">
|
|
46760
|
+
${repeat(children, (r) => r.node.item.key, (r) => this.#renderNestedTile(r, rect, byParent))}
|
|
46761
|
+
</div>
|
|
46762
|
+
` : A;
|
|
46763
|
+
return this.#renderTileBox(rect, positionStyle, children.length > 0, childrenContent);
|
|
46764
|
+
}
|
|
46765
|
+
/** A child tile, positioned as a percentage of `parent`'s own box. */
|
|
46590
46766
|
#renderNestedTile(rect, parent, byParent) {
|
|
46591
46767
|
const relX = parent.width > 0 ? (rect.x - parent.x) / parent.width : 0;
|
|
46592
46768
|
const relY = parent.height > 0 ? (rect.y - parent.y) / parent.height : 0;
|
|
46593
46769
|
const relW = parent.width > 0 ? rect.width / parent.width : 0;
|
|
46594
46770
|
const relH = parent.height > 0 ? rect.height / parent.height : 0;
|
|
46595
|
-
|
|
46771
|
+
const style = `left:${(relX * 100).toFixed(4)}%;top:${(relY * 100).toFixed(4)}%;width:${(relW * 100).toFixed(4)}%;height:${(relH * 100).toFixed(4)}%`;
|
|
46772
|
+
return this.#renderTile(rect, style, byParent);
|
|
46596
46773
|
}
|
|
46597
46774
|
#renderTopTile(rect, byParent) {
|
|
46598
|
-
|
|
46775
|
+
const style = `left:${(rect.x * 100).toFixed(4)}%;top:${(rect.y * 100).toFixed(4)}%;width:${(rect.width * 100).toFixed(4)}%;height:${(rect.height * 100).toFixed(4)}%`;
|
|
46776
|
+
return this.#renderTile(rect, style, byParent);
|
|
46599
46777
|
}
|
|
46600
46778
|
render() {
|
|
46601
46779
|
const rects = this.#rects();
|
|
@@ -46617,11 +46795,14 @@ let TreemapListElement = class TreemapListElement extends i {
|
|
|
46617
46795
|
style=${`--treemap-padding:${this.padding}px`}
|
|
46618
46796
|
@keydown=${(e) => this.#handleKeyDown(e)}
|
|
46619
46797
|
@pointerleave=${() => this.tickled.clearTickled()}
|
|
46798
|
+
@wheel=${(e) => this.#handleWheel(e)}
|
|
46620
46799
|
>
|
|
46621
46800
|
${this.#renderBreadcrumb()}
|
|
46622
46801
|
${rects.length === 0 ? b`<div class="empty-state">No data</div>` : b`
|
|
46623
46802
|
<div class="viewport" part="viewport">
|
|
46624
|
-
|
|
46803
|
+
<div class="viewport-inner">
|
|
46804
|
+
${repeat(topLevel, (r) => r.node.item.key, (r) => this.#renderTopTile(r, byParent))}
|
|
46805
|
+
</div>
|
|
46625
46806
|
</div>
|
|
46626
46807
|
`}
|
|
46627
46808
|
</div>
|
|
@@ -46644,11 +46825,18 @@ let TreemapListElement = class TreemapListElement extends i {
|
|
|
46644
46825
|
--treemap-tile-border: var(--border-subtle);
|
|
46645
46826
|
--treemap-header-bg: rgb(0 0 0 / 0.12);
|
|
46646
46827
|
--treemap-font-size: var(--text-s);
|
|
46828
|
+
--treemap-zoom-duration: 220ms;
|
|
46647
46829
|
|
|
46648
46830
|
display: block;
|
|
46649
|
-
overflow:
|
|
46831
|
+
overflow: hidden;
|
|
46650
46832
|
}
|
|
46651
46833
|
|
|
46834
|
+
/* Per-category tile colours (set categoryAccessor to opt in): define
|
|
46835
|
+
--treemap-category-SLUG-bg / -text at whatever scope suits (:host
|
|
46836
|
+
here, or globally) for each category your accessor can return —
|
|
46837
|
+
e.g. --treemap-category-urgent-bg: oklch(55% 0.18 25). A category
|
|
46838
|
+
with no matching pair falls back to --treemap-tile-bg/-text. */
|
|
46839
|
+
|
|
46652
46840
|
.treemap {
|
|
46653
46841
|
display: flex;
|
|
46654
46842
|
flex-direction: column;
|
|
@@ -46677,18 +46865,44 @@ let TreemapListElement = class TreemapListElement extends i {
|
|
|
46677
46865
|
.viewport {
|
|
46678
46866
|
position: relative;
|
|
46679
46867
|
width: 100%;
|
|
46680
|
-
|
|
46681
|
-
|
|
46868
|
+
/* flex-basis of --treemap-height (its size when nothing forces a
|
|
46869
|
+
different one — the common case of an auto-height host) but
|
|
46870
|
+
allowed to grow/shrink like any flex item, so it shares the
|
|
46871
|
+
.treemap column's height with the breadcrumb instead of a plain
|
|
46872
|
+
fixed height always claiming that full amount regardless of what
|
|
46873
|
+
else needs space — which is what let the breadcrumb push the
|
|
46874
|
+
host past its own height and scroll once a zoom made it appear. */
|
|
46875
|
+
flex: 1 1 var(--treemap-height);
|
|
46876
|
+
min-height: 0;
|
|
46682
46877
|
overflow: hidden;
|
|
46683
46878
|
border-radius: var(--radius-m);
|
|
46684
46879
|
}
|
|
46685
46880
|
|
|
46881
|
+
/* Transform target for the zoom-in/zoom-out FLIP animation (see
|
|
46882
|
+
#planFlip/#applyFlip) — kept separate from .viewport so the
|
|
46883
|
+
transform never fights that element's own sizing/overflow. */
|
|
46884
|
+
.viewport-inner {
|
|
46885
|
+
position: absolute;
|
|
46886
|
+
inset: 0;
|
|
46887
|
+
transform-origin: 0 0;
|
|
46888
|
+
}
|
|
46889
|
+
|
|
46890
|
+
.viewport-inner.flipping {
|
|
46891
|
+
transition: transform var(--treemap-zoom-duration, 220ms) ease-out;
|
|
46892
|
+
}
|
|
46893
|
+
|
|
46686
46894
|
.tile {
|
|
46687
46895
|
position: absolute;
|
|
46688
46896
|
box-sizing: border-box;
|
|
46689
46897
|
overflow: hidden;
|
|
46690
46898
|
display: flex;
|
|
46691
46899
|
flex-direction: column;
|
|
46900
|
+
/* Override the shared .item class's align-items:center (built for
|
|
46901
|
+
icon+label rows) — tiles need their flex children to stretch to
|
|
46902
|
+
full width, or .tile-children collapses to its (empty) content
|
|
46903
|
+
width and every nested tile collapses with it. */
|
|
46904
|
+
align-items: stretch;
|
|
46905
|
+
white-space: normal;
|
|
46692
46906
|
background: var(--treemap-tile-bg);
|
|
46693
46907
|
color: var(--treemap-tile-text);
|
|
46694
46908
|
border: var(--treemap-tile-border);
|
|
@@ -46781,12 +46995,25 @@ __decorate([property({
|
|
|
46781
46995
|
type: Number,
|
|
46782
46996
|
attribute: `max-depth`
|
|
46783
46997
|
})], TreemapListElement.prototype, "maxDepth", void 0);
|
|
46998
|
+
__decorate([property({
|
|
46999
|
+
type: Boolean,
|
|
47000
|
+
attribute: `hide-leaves`
|
|
47001
|
+
})], TreemapListElement.prototype, "hideLeaves", void 0);
|
|
46784
47002
|
__decorate([property({
|
|
46785
47003
|
type: Number,
|
|
46786
47004
|
attribute: `min-label-area`
|
|
46787
47005
|
})], TreemapListElement.prototype, "minLabelArea", void 0);
|
|
47006
|
+
__decorate([property({
|
|
47007
|
+
type: Number,
|
|
47008
|
+
attribute: `min-tile-width`
|
|
47009
|
+
})], TreemapListElement.prototype, "minTileWidth", void 0);
|
|
46788
47010
|
__decorate([property({ type: Number })], TreemapListElement.prototype, "padding", void 0);
|
|
47011
|
+
__decorate([property({
|
|
47012
|
+
type: Number,
|
|
47013
|
+
attribute: `min-child-area`
|
|
47014
|
+
})], TreemapListElement.prototype, "minChildArea", void 0);
|
|
46789
47015
|
__decorate([property({ attribute: false })], TreemapListElement.prototype, "valueAccessor", void 0);
|
|
47016
|
+
__decorate([property({ attribute: false })], TreemapListElement.prototype, "categoryAccessor", void 0);
|
|
46790
47017
|
__decorate([property({ attribute: false })], TreemapListElement.prototype, "selectedNode", void 0);
|
|
46791
47018
|
__decorate([state()], TreemapListElement.prototype, "_selectedNodes", void 0);
|
|
46792
47019
|
__decorate([property({ attribute: false })], TreemapListElement.prototype, "filterPredicate", void 0);
|