@ixfx/components 0.8.6 → 0.8.8
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 +570 -389
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +1033 -200
- package/bundle/index.js.map +1 -1
- package/dist/crumbs.d.ts +1 -1
- package/dist/crumbs.js +2 -2
- package/dist/{data-grid-D-z7bx5-.d.ts → data-grid-BKa9i86q.d.ts} +15 -2
- package/dist/data-grid-BKa9i86q.d.ts.map +1 -0
- package/dist/data-grid.d.ts +3 -2
- package/dist/data-grid.js +95 -5
- package/dist/data-grid.js.map +1 -1
- package/dist/{detail-list-_ZJHYEBr.d.ts → detail-list-CHTomlbR.d.ts} +22 -5
- package/dist/detail-list-CHTomlbR.d.ts.map +1 -0
- package/dist/detail-list.d.ts +4 -3
- package/dist/detail-list.js +103 -3
- package/dist/detail-list.js.map +1 -1
- package/dist/{grid-list-j5C7qtlG.js → grid-list-C8oMxLl-.js} +77 -164
- package/dist/grid-list-C8oMxLl-.js.map +1 -0
- package/dist/{grid-list-x550wJ0X.d.ts → grid-list-CsZcXxMC.d.ts} +259 -109
- package/dist/grid-list-CsZcXxMC.d.ts.map +1 -0
- package/dist/grid-list.d.ts +3 -2
- package/dist/grid-list.js +1 -1
- package/dist/incr-search.d.ts +1 -1
- package/dist/{index-h6gxtfHH.d.ts → index-Dgrx-DIA.d.ts} +2 -2
- package/dist/{index-h6gxtfHH.d.ts.map → index-Dgrx-DIA.d.ts.map} +1 -1
- package/dist/index.d.ts +190 -252
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -7
- package/dist/index.js.map +1 -1
- package/dist/{interaction-B9AAlsFO.js → interaction-BskmlA9t.js} +1 -1
- package/dist/list-drag-types-kpaXz2pZ.d.ts +42 -0
- package/dist/list-drag-types-kpaXz2pZ.d.ts.map +1 -0
- package/dist/{list-item-animation-DuiwgN3l.js → list-item-animation-BUoEKi5s.js} +29 -10
- package/dist/list-item-animation-BUoEKi5s.js.map +1 -0
- package/dist/list-native-drag-controller-DrY3qeJM.js +555 -0
- package/dist/list-native-drag-controller-DrY3qeJM.js.map +1 -0
- package/dist/{menu-HMoxCPY2.js → menu-CMXhIaNZ.js} +3 -3
- package/dist/{menu-HMoxCPY2.js.map → menu-CMXhIaNZ.js.map} +1 -1
- package/dist/{menu-item-BQDYxk5A.js → menu-item-BYGQzyCe.js} +2 -2
- package/dist/{menu-item-BQDYxk5A.js.map → menu-item-BYGQzyCe.js.map} +1 -1
- package/dist/menu.js +2 -2
- package/dist/miller.d.ts +2 -2
- package/dist/miller.js +1 -1
- package/dist/narrowed-text.js +1 -1
- package/dist/select-horiz.js +1 -1
- package/dist/{tree-DTQon838.js → tree-DSMn566I.js} +90 -27
- package/dist/tree-DSMn566I.js.map +1 -0
- package/dist/{tree-component-F6qZ0Gdv.d.ts → tree-component-nPP5Y-WS.d.ts} +12 -2
- package/dist/tree-component-nPP5Y-WS.d.ts.map +1 -0
- package/dist/tree.d.ts +3 -2
- package/dist/tree.d.ts.map +1 -1
- package/dist/tree.js +1 -1
- package/dist/{vertical-list-CFuFDygi.d.ts → vertical-list-A6oWfivZ.d.ts} +21 -4
- package/dist/vertical-list-A6oWfivZ.d.ts.map +1 -0
- package/dist/vertical-list.d.ts +3 -2
- package/dist/vertical-list.js +103 -3
- package/dist/vertical-list.js.map +1 -1
- package/docs-user/README.md +1 -0
- package/docs-user/data-grid.md +30 -0
- package/docs-user/data-table.md +104 -0
- package/docs-user/detail-list.md +29 -0
- package/docs-user/grid-list.md +34 -4
- package/docs-user/index.json +7 -2
- package/docs-user/llms.txt +1 -0
- package/docs-user/tree.md +5 -4
- package/docs-user/vertical-list.md +30 -1
- package/llms.txt +1 -0
- package/package.json +1 -1
- package/dist/data-grid-D-z7bx5-.d.ts.map +0 -1
- package/dist/detail-list-_ZJHYEBr.d.ts.map +0 -1
- package/dist/grid-list-j5C7qtlG.js.map +0 -1
- package/dist/grid-list-x550wJ0X.d.ts.map +0 -1
- package/dist/list-item-animation-DuiwgN3l.js.map +0 -1
- package/dist/tree-DTQon838.js.map +0 -1
- package/dist/tree-component-F6qZ0Gdv.d.ts.map +0 -1
- package/dist/vertical-list-CFuFDygi.d.ts.map +0 -1
package/bundle/index.js
CHANGED
|
@@ -5686,6 +5686,363 @@ __decorate([state()], RadioGroup.prototype, "_icons", void 0);
|
|
|
5686
5686
|
__decorate([query(`slot`)], RadioGroup.prototype, "_slot", void 0);
|
|
5687
5687
|
RadioGroup = __decorate([safeCustomElement(`ixfx-radio-group`)], RadioGroup);
|
|
5688
5688
|
//#endregion
|
|
5689
|
+
//#region src/interaction/list-drag-preview-default.ts
|
|
5690
|
+
const CARD_DEFAULT = 72;
|
|
5691
|
+
const CARD_MIN = 48;
|
|
5692
|
+
const CARD_MAX = 96;
|
|
5693
|
+
const LIST_WIDTH = 220;
|
|
5694
|
+
const LIST_MAX_ROWS = 5;
|
|
5695
|
+
const MAX_CANVAS_DIM = 1024;
|
|
5696
|
+
function cssVar(style, name, fallback) {
|
|
5697
|
+
try {
|
|
5698
|
+
return style.getPropertyValue(name)?.trim() || fallback;
|
|
5699
|
+
} catch {
|
|
5700
|
+
return fallback;
|
|
5701
|
+
}
|
|
5702
|
+
}
|
|
5703
|
+
function fontOf(style) {
|
|
5704
|
+
try {
|
|
5705
|
+
const font = style.font?.trim();
|
|
5706
|
+
if (font) return font;
|
|
5707
|
+
} catch {}
|
|
5708
|
+
return `12px system-ui, sans-serif`;
|
|
5709
|
+
}
|
|
5710
|
+
/** Caption for a drag entry — element labels win, then string items, then common object fields, then the key. */
|
|
5711
|
+
function captionForEntry(entry) {
|
|
5712
|
+
const el = entry.element ?? (entry.item instanceof Element ? entry.item : void 0);
|
|
5713
|
+
if (el) {
|
|
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
|
+
if (labelled) return labelled.slice(0, 80);
|
|
5716
|
+
const text = el.textContent?.trim();
|
|
5717
|
+
if (text) return text.slice(0, 80);
|
|
5718
|
+
}
|
|
5719
|
+
const item = entry.item;
|
|
5720
|
+
if (typeof item === `string` && item.length > 0) return item.slice(0, 80);
|
|
5721
|
+
if (item !== null && typeof item === `object` && !(item instanceof Element)) {
|
|
5722
|
+
const record = item;
|
|
5723
|
+
for (const field of [
|
|
5724
|
+
`label`,
|
|
5725
|
+
`name`,
|
|
5726
|
+
`title`,
|
|
5727
|
+
`text`
|
|
5728
|
+
]) {
|
|
5729
|
+
const value = record[field];
|
|
5730
|
+
if (typeof value === `string` && value.length > 0) return value.slice(0, 80);
|
|
5731
|
+
}
|
|
5732
|
+
}
|
|
5733
|
+
return entry.key;
|
|
5734
|
+
}
|
|
5735
|
+
function glyphFor(caption) {
|
|
5736
|
+
const first = caption.trim().at(0);
|
|
5737
|
+
return first ? first.toLocaleUpperCase() : `?`;
|
|
5738
|
+
}
|
|
5739
|
+
/** A decoded `<img>` ready for `drawImage`, if the entry's element has one. */
|
|
5740
|
+
function decodedImage(entry) {
|
|
5741
|
+
const scope = entry.element ?? (entry.item instanceof Element ? entry.item : void 0);
|
|
5742
|
+
if (!scope || typeof scope.querySelector !== `function`) return void 0;
|
|
5743
|
+
if (scope instanceof HTMLImageElement) {
|
|
5744
|
+
if (scope.complete && scope.naturalWidth > 0) return scope;
|
|
5745
|
+
return;
|
|
5746
|
+
}
|
|
5747
|
+
try {
|
|
5748
|
+
const img = scope.querySelector(`img`);
|
|
5749
|
+
if (img instanceof HTMLImageElement && img.complete && img.naturalWidth > 0) return img;
|
|
5750
|
+
} catch {}
|
|
5751
|
+
}
|
|
5752
|
+
function cardSize(metrics) {
|
|
5753
|
+
if (metrics.itemSize !== void 0 && Number.isFinite(metrics.itemSize)) return Math.max(CARD_MIN, Math.min(CARD_MAX, Math.round(metrics.itemSize)));
|
|
5754
|
+
return CARD_DEFAULT;
|
|
5755
|
+
}
|
|
5756
|
+
function rowHeight(metrics) {
|
|
5757
|
+
const raw = metrics.rowHeight;
|
|
5758
|
+
if (raw !== void 0 && Number.isFinite(raw)) return Math.max(24, Math.min(36, Math.round(raw)));
|
|
5759
|
+
return 28;
|
|
5760
|
+
}
|
|
5761
|
+
function thumbCell(doc, caption, img, size) {
|
|
5762
|
+
const well = doc.createElement(`div`);
|
|
5763
|
+
well.setAttribute(`data-thumb`, ``);
|
|
5764
|
+
well.style.cssText = `width:${size}px;height:${size}px;border-radius:4px;overflow:hidden;background:var(--surface-5, rgba(128,128,128,0.25));flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:${Math.round(size * .4)}px;font-weight:600;`;
|
|
5765
|
+
if (img) try {
|
|
5766
|
+
const clone = img.cloneNode(true);
|
|
5767
|
+
clone.style.cssText = `width:100%;height:100%;object-fit:cover;`;
|
|
5768
|
+
clone.removeAttribute(`id`);
|
|
5769
|
+
well.appendChild(clone);
|
|
5770
|
+
} catch {
|
|
5771
|
+
well.textContent = glyphFor(caption);
|
|
5772
|
+
}
|
|
5773
|
+
else well.textContent = glyphFor(caption);
|
|
5774
|
+
return well;
|
|
5775
|
+
}
|
|
5776
|
+
function buildCardsElement(ctx, captions, images) {
|
|
5777
|
+
const doc = document;
|
|
5778
|
+
const size = cardSize(ctx.metrics);
|
|
5779
|
+
const gap = 6;
|
|
5780
|
+
const pad = 8;
|
|
5781
|
+
const root = doc.createElement(`div`);
|
|
5782
|
+
root.setAttribute(`data-preview`, `cards`);
|
|
5783
|
+
root.setAttribute(`part`, `drag-preview`);
|
|
5784
|
+
root.style.cssText = `position:fixed;top:-9999px;left:-9999px;display:flex;flex-direction:row;gap:${gap}px;padding:${pad}px;background:var(--surface-4, #333);color:var(--surface-4-text, #fff);border:1px solid var(--border-subtle, #555);border-radius:var(--radius-m, 8px);box-shadow:0 4px 16px rgba(0,0,0,0.3);font-family:system-ui,sans-serif;font-size:11px;max-width:320px;z-index:999999;pointer-events:none;`;
|
|
5785
|
+
const n = ctx.selected.length;
|
|
5786
|
+
for (let i = 0; i < n; i++) {
|
|
5787
|
+
const card = doc.createElement(`div`);
|
|
5788
|
+
card.setAttribute(`data-card`, ``);
|
|
5789
|
+
card.style.cssText = `display:flex;flex-direction:column;gap:4px;align-items:center;width:${size}px;`;
|
|
5790
|
+
card.appendChild(thumbCell(doc, captions[i], images[i], Math.round(size * .72)));
|
|
5791
|
+
const label = doc.createElement(`span`);
|
|
5792
|
+
label.setAttribute(`data-caption`, ``);
|
|
5793
|
+
label.style.cssText = `max-width:${size}px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;opacity:0.9;`;
|
|
5794
|
+
label.textContent = captions[i];
|
|
5795
|
+
card.appendChild(label);
|
|
5796
|
+
root.appendChild(card);
|
|
5797
|
+
}
|
|
5798
|
+
return root;
|
|
5799
|
+
}
|
|
5800
|
+
function buildListElement(ctx, captions, images) {
|
|
5801
|
+
const doc = document;
|
|
5802
|
+
const rh = rowHeight(ctx.metrics);
|
|
5803
|
+
const thumb = Math.round(rh * .78);
|
|
5804
|
+
const root = doc.createElement(`div`);
|
|
5805
|
+
root.setAttribute(`data-preview`, `list`);
|
|
5806
|
+
root.setAttribute(`part`, `drag-preview`);
|
|
5807
|
+
root.style.cssText = `position:fixed;top:-9999px;left:-9999px;display:flex;flex-direction:column;gap:4px;padding:8px;background:var(--surface-4, #333);color:var(--surface-4-text, #fff);border:1px solid var(--border-subtle, #555);border-radius:var(--radius-m, 8px);box-shadow:0 4px 16px rgba(0,0,0,0.3);font-family:system-ui,sans-serif;font-size:12px;width:${LIST_WIDTH}px;max-width:${LIST_WIDTH}px;z-index:999999;pointer-events:none;`;
|
|
5808
|
+
const header = doc.createElement(`div`);
|
|
5809
|
+
header.setAttribute(`data-header`, ``);
|
|
5810
|
+
header.style.cssText = `font-weight:600;padding-bottom:4px;border-bottom:1px solid var(--border-subtle, #555);margin-bottom:4px;`;
|
|
5811
|
+
header.textContent = `${ctx.selected.length} items`;
|
|
5812
|
+
root.appendChild(header);
|
|
5813
|
+
for (let i = 0; i < Math.min(LIST_MAX_ROWS, captions.length); i++) {
|
|
5814
|
+
const row = doc.createElement(`div`);
|
|
5815
|
+
row.setAttribute(`data-row`, ``);
|
|
5816
|
+
row.style.cssText = `display:flex;align-items:center;gap:6px;height:${rh}px;overflow:hidden;`;
|
|
5817
|
+
row.appendChild(thumbCell(doc, captions[i], images[i], thumb));
|
|
5818
|
+
const label = doc.createElement(`span`);
|
|
5819
|
+
label.setAttribute(`data-caption`, ``);
|
|
5820
|
+
label.style.cssText = `flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;`;
|
|
5821
|
+
label.textContent = captions[i];
|
|
5822
|
+
row.appendChild(label);
|
|
5823
|
+
root.appendChild(row);
|
|
5824
|
+
}
|
|
5825
|
+
if (captions.length > LIST_MAX_ROWS) {
|
|
5826
|
+
const more = doc.createElement(`div`);
|
|
5827
|
+
more.setAttribute(`data-more`, ``);
|
|
5828
|
+
more.style.cssText = `opacity:0.6;text-align:center;`;
|
|
5829
|
+
more.textContent = `+${captions.length - LIST_MAX_ROWS} more`;
|
|
5830
|
+
root.appendChild(more);
|
|
5831
|
+
}
|
|
5832
|
+
return root;
|
|
5833
|
+
}
|
|
5834
|
+
function paletteOf(style) {
|
|
5835
|
+
const bg = cssVar(style, `--surface-4`, `#333333`);
|
|
5836
|
+
const fg = cssVar(style, `--surface-4-text`, `#ffffff`);
|
|
5837
|
+
const subtle = cssVar(style, `--border-subtle`, `#555555`);
|
|
5838
|
+
const accent = cssVar(style, `--accent`, `#4da3ff`);
|
|
5839
|
+
const radiusRaw = cssVar(style, `--radius-m`, `8`);
|
|
5840
|
+
return {
|
|
5841
|
+
bg,
|
|
5842
|
+
fg,
|
|
5843
|
+
subtle,
|
|
5844
|
+
accent,
|
|
5845
|
+
radius: Number.parseFloat(radiusRaw) || 8,
|
|
5846
|
+
font: fontOf(style)
|
|
5847
|
+
};
|
|
5848
|
+
}
|
|
5849
|
+
function fitCanvas(canvas, cssW, cssH) {
|
|
5850
|
+
let scale = Math.max(1, Math.min(3, typeof devicePixelRatio === `number` && devicePixelRatio > 0 ? devicePixelRatio : 1));
|
|
5851
|
+
const maxScaleW = MAX_CANVAS_DIM / Math.max(1, cssW);
|
|
5852
|
+
const maxScaleH = MAX_CANVAS_DIM / Math.max(1, cssH);
|
|
5853
|
+
scale = Math.min(scale, maxScaleW, maxScaleH);
|
|
5854
|
+
canvas.width = Math.max(1, Math.round(cssW * scale));
|
|
5855
|
+
canvas.height = Math.max(1, Math.round(cssH * scale));
|
|
5856
|
+
canvas.style.width = `${cssW}px`;
|
|
5857
|
+
canvas.style.height = `${cssH}px`;
|
|
5858
|
+
return {
|
|
5859
|
+
scale,
|
|
5860
|
+
dpr: scale
|
|
5861
|
+
};
|
|
5862
|
+
}
|
|
5863
|
+
function roundRectPath(context, x, y, w, h, r) {
|
|
5864
|
+
const radius = Math.max(0, Math.min(r, w / 2, h / 2));
|
|
5865
|
+
if (typeof context.roundRect === `function`) {
|
|
5866
|
+
context.beginPath();
|
|
5867
|
+
context.roundRect(x, y, w, h, radius);
|
|
5868
|
+
return;
|
|
5869
|
+
}
|
|
5870
|
+
context.beginPath();
|
|
5871
|
+
context.moveTo(x + radius, y);
|
|
5872
|
+
context.arcTo(x + w, y, x + w, y + h, radius);
|
|
5873
|
+
context.arcTo(x + w, y + h, x, y + h, radius);
|
|
5874
|
+
context.arcTo(x, y + h, x, y, radius);
|
|
5875
|
+
context.arcTo(x, y, x + w, y, radius);
|
|
5876
|
+
context.closePath();
|
|
5877
|
+
}
|
|
5878
|
+
function paintCards(context, scale, palette, captions, images, size, cssW, cssH) {
|
|
5879
|
+
context.save();
|
|
5880
|
+
context.scale(scale, scale);
|
|
5881
|
+
roundRectPath(context, 0, 0, cssW, cssH, palette.radius);
|
|
5882
|
+
context.fillStyle = palette.bg;
|
|
5883
|
+
context.fill();
|
|
5884
|
+
context.strokeStyle = palette.subtle;
|
|
5885
|
+
context.lineWidth = 1;
|
|
5886
|
+
context.stroke();
|
|
5887
|
+
context.clip();
|
|
5888
|
+
const gap = 6;
|
|
5889
|
+
const pad = 8;
|
|
5890
|
+
const wellSize = Math.round(size * .72);
|
|
5891
|
+
context.font = palette.font;
|
|
5892
|
+
context.textBaseline = `middle`;
|
|
5893
|
+
for (let i = 0; i < captions.length; i++) {
|
|
5894
|
+
const x = pad + i * (size + gap);
|
|
5895
|
+
const wellX = x + (size - wellSize) / 2;
|
|
5896
|
+
const wellY = pad;
|
|
5897
|
+
roundRectPath(context, wellX, wellY, wellSize, wellSize, 4);
|
|
5898
|
+
context.fillStyle = palette.subtle;
|
|
5899
|
+
context.globalAlpha = .35;
|
|
5900
|
+
context.fill();
|
|
5901
|
+
context.globalAlpha = 1;
|
|
5902
|
+
const img = images[i];
|
|
5903
|
+
if (img) try {
|
|
5904
|
+
context.save();
|
|
5905
|
+
context.clip();
|
|
5906
|
+
context.drawImage(img, wellX, wellY, wellSize, wellSize);
|
|
5907
|
+
context.restore();
|
|
5908
|
+
} catch {}
|
|
5909
|
+
else {
|
|
5910
|
+
context.fillStyle = palette.fg;
|
|
5911
|
+
context.globalAlpha = .9;
|
|
5912
|
+
context.font = `600 ${Math.round(wellSize * .4)}px system-ui, sans-serif`;
|
|
5913
|
+
context.textAlign = `center`;
|
|
5914
|
+
context.fillText(glyphFor(captions[i]), wellX + wellSize / 2, wellY + wellSize / 2 + 1);
|
|
5915
|
+
context.globalAlpha = 1;
|
|
5916
|
+
context.textAlign = `left`;
|
|
5917
|
+
context.font = palette.font;
|
|
5918
|
+
}
|
|
5919
|
+
context.fillStyle = palette.fg;
|
|
5920
|
+
context.globalAlpha = .9;
|
|
5921
|
+
context.font = palette.font;
|
|
5922
|
+
const label = captions[i].length > 12 ? `${captions[i].slice(0, 11)}…` : captions[i];
|
|
5923
|
+
const textWidth = context.measureText(label).width;
|
|
5924
|
+
context.fillText(label, x + (size - Math.min(size, textWidth)) / 2, wellY + wellSize + 10, size);
|
|
5925
|
+
context.globalAlpha = 1;
|
|
5926
|
+
}
|
|
5927
|
+
context.restore();
|
|
5928
|
+
}
|
|
5929
|
+
function paintList(context, scale, palette, captions, images, rh, cssW, cssH) {
|
|
5930
|
+
context.save();
|
|
5931
|
+
context.scale(scale, scale);
|
|
5932
|
+
roundRectPath(context, 0, 0, cssW, cssH, palette.radius);
|
|
5933
|
+
context.fillStyle = palette.bg;
|
|
5934
|
+
context.fill();
|
|
5935
|
+
context.strokeStyle = palette.subtle;
|
|
5936
|
+
context.lineWidth = 1;
|
|
5937
|
+
context.stroke();
|
|
5938
|
+
context.clip();
|
|
5939
|
+
const pad = 8;
|
|
5940
|
+
context.fillStyle = palette.fg;
|
|
5941
|
+
context.font = `600 ${palette.font}`;
|
|
5942
|
+
context.textBaseline = `middle`;
|
|
5943
|
+
context.fillText(`${captions.length} items`, pad, 16, cssW - 16);
|
|
5944
|
+
context.strokeStyle = palette.subtle;
|
|
5945
|
+
context.beginPath();
|
|
5946
|
+
context.moveTo(pad, 28);
|
|
5947
|
+
context.lineTo(cssW - pad, 28);
|
|
5948
|
+
context.stroke();
|
|
5949
|
+
const thumb = Math.round(rh * .78);
|
|
5950
|
+
const rows = Math.min(LIST_MAX_ROWS, captions.length);
|
|
5951
|
+
context.font = palette.font;
|
|
5952
|
+
for (let i = 0; i < rows; i++) {
|
|
5953
|
+
const y = 32 + i * rh;
|
|
5954
|
+
roundRectPath(context, pad, y + (rh - thumb) / 2, thumb, thumb, 4);
|
|
5955
|
+
context.fillStyle = palette.subtle;
|
|
5956
|
+
context.globalAlpha = .35;
|
|
5957
|
+
context.fill();
|
|
5958
|
+
context.globalAlpha = 1;
|
|
5959
|
+
const img = images[i];
|
|
5960
|
+
if (img) try {
|
|
5961
|
+
context.save();
|
|
5962
|
+
context.clip();
|
|
5963
|
+
context.drawImage(img, pad, y + (rh - thumb) / 2, thumb, thumb);
|
|
5964
|
+
context.restore();
|
|
5965
|
+
} catch {}
|
|
5966
|
+
else {
|
|
5967
|
+
context.fillStyle = palette.fg;
|
|
5968
|
+
context.font = `600 ${Math.round(thumb * .45)}px system-ui, sans-serif`;
|
|
5969
|
+
context.textAlign = `center`;
|
|
5970
|
+
context.fillText(glyphFor(captions[i]), pad + thumb / 2, y + rh / 2 + 1);
|
|
5971
|
+
context.textAlign = `left`;
|
|
5972
|
+
context.font = palette.font;
|
|
5973
|
+
}
|
|
5974
|
+
context.fillStyle = palette.fg;
|
|
5975
|
+
context.globalAlpha = .92;
|
|
5976
|
+
const maxText = cssW - 16 - thumb - 6;
|
|
5977
|
+
context.fillText(captions[i], pad + thumb + 6, y + rh / 2 + 1, Math.max(8, maxText));
|
|
5978
|
+
context.globalAlpha = 1;
|
|
5979
|
+
}
|
|
5980
|
+
if (captions.length > LIST_MAX_ROWS) {
|
|
5981
|
+
context.fillStyle = palette.fg;
|
|
5982
|
+
context.globalAlpha = .6;
|
|
5983
|
+
context.textAlign = `center`;
|
|
5984
|
+
context.fillText(`+${captions.length - LIST_MAX_ROWS} more`, cssW / 2, cssH - pad - 6, cssW - 16);
|
|
5985
|
+
context.textAlign = `left`;
|
|
5986
|
+
context.globalAlpha = 1;
|
|
5987
|
+
}
|
|
5988
|
+
context.restore();
|
|
5989
|
+
}
|
|
5990
|
+
/**
|
|
5991
|
+
* Uniform built-in HTML+canvas drag preview for all four list components.
|
|
5992
|
+
*
|
|
5993
|
+
* - ≤5 selected → a row of small cards (thumbnail well + caption).
|
|
5994
|
+
* - >5 selected → a compact list (`N items` header, up to 5 rows, `+N more`).
|
|
5995
|
+
*
|
|
5996
|
+
* Always returns an offscreen `element` for `DataTransfer.setDragImage()` and,
|
|
5997
|
+
* when a 2D context is available, a DPR-aware painted `canvas` for native
|
|
5998
|
+
* hosts. Colours track the active theme via `ctx.hostStyle` CSS variables.
|
|
5999
|
+
*/
|
|
6000
|
+
function createDefaultListDragPreview(ctx) {
|
|
6001
|
+
const entries = ctx.selected;
|
|
6002
|
+
const captions = entries.map((entry) => captionForEntry(entry));
|
|
6003
|
+
const images = entries.map((entry) => decodedImage(entry));
|
|
6004
|
+
const isCards = entries.length <= 5;
|
|
6005
|
+
let element;
|
|
6006
|
+
let cssW;
|
|
6007
|
+
let cssH;
|
|
6008
|
+
if (isCards) {
|
|
6009
|
+
const size = cardSize(ctx.metrics);
|
|
6010
|
+
cssW = entries.length * size + Math.max(0, entries.length - 1) * 6 + 16;
|
|
6011
|
+
cssH = Math.round(size * .72) + 22 + 16;
|
|
6012
|
+
element = buildCardsElement(ctx, captions, images);
|
|
6013
|
+
} else {
|
|
6014
|
+
const rh = rowHeight(ctx.metrics);
|
|
6015
|
+
const rows = Math.min(LIST_MAX_ROWS, entries.length);
|
|
6016
|
+
const more = entries.length > LIST_MAX_ROWS ? 18 : 0;
|
|
6017
|
+
cssW = 236;
|
|
6018
|
+
cssH = 40 + rows * rh + more;
|
|
6019
|
+
element = buildListElement(ctx, captions, images);
|
|
6020
|
+
}
|
|
6021
|
+
let canvas;
|
|
6022
|
+
try {
|
|
6023
|
+
const candidate = document.createElement(`canvas`);
|
|
6024
|
+
const paint = candidate.getContext(`2d`);
|
|
6025
|
+
if (paint) {
|
|
6026
|
+
const { scale } = fitCanvas(candidate, cssW, cssH);
|
|
6027
|
+
const palette = paletteOf(ctx.hostStyle);
|
|
6028
|
+
if (isCards) paintCards(paint, scale, palette, captions, images, cardSize(ctx.metrics), cssW, cssH);
|
|
6029
|
+
else paintList(paint, scale, palette, captions, images, rowHeight(ctx.metrics), cssW, cssH);
|
|
6030
|
+
canvas = candidate;
|
|
6031
|
+
}
|
|
6032
|
+
} catch {
|
|
6033
|
+
canvas = void 0;
|
|
6034
|
+
}
|
|
6035
|
+
return {
|
|
6036
|
+
element,
|
|
6037
|
+
hotspot: {
|
|
6038
|
+
x: 16,
|
|
6039
|
+
y: 16
|
|
6040
|
+
},
|
|
6041
|
+
...canvas ? { canvas } : {},
|
|
6042
|
+
dispose: () => {}
|
|
6043
|
+
};
|
|
6044
|
+
}
|
|
6045
|
+
//#endregion
|
|
5689
6046
|
//#region src/interaction/list-drag-select-controller.ts
|
|
5690
6047
|
const DEFAULT_POINTER_TYPES = [`mouse`, `pen`];
|
|
5691
6048
|
const DEFAULT_THRESHOLD = 4;
|
|
@@ -6075,24 +6432,238 @@ function animateListItemIn(el, options = {}) {
|
|
|
6075
6432
|
easing
|
|
6076
6433
|
});
|
|
6077
6434
|
}
|
|
6435
|
+
function outResult(finished, animation) {
|
|
6436
|
+
return Object.assign(finished, { animation });
|
|
6437
|
+
}
|
|
6078
6438
|
/**
|
|
6079
|
-
*
|
|
6080
|
-
*
|
|
6081
|
-
*
|
|
6082
|
-
*
|
|
6439
|
+
* Start the collapse + fade-out animation for `el` and return the handle.
|
|
6440
|
+
* Returns `undefined` when no animation was started (reduced motion or zero
|
|
6441
|
+
* size). The caller owns the handle and must `cancel()` it if the removal is
|
|
6442
|
+
* reversed — a retained `fill: forwards` frame otherwise keeps overriding the
|
|
6443
|
+
* element's ordinary CSS indefinitely.
|
|
6083
6444
|
*/
|
|
6084
|
-
function
|
|
6085
|
-
if (prefersReducedMotion()) return
|
|
6445
|
+
function startListItemOutAnimation(el, options = {}) {
|
|
6446
|
+
if (prefersReducedMotion()) return void 0;
|
|
6086
6447
|
const { axis = `block`, easing = `ease` } = options;
|
|
6087
6448
|
const duration = resolveDuration(el, options.duration);
|
|
6088
6449
|
const size = measure(el, axis);
|
|
6089
|
-
if (size <= 0) return
|
|
6450
|
+
if (size <= 0) return void 0;
|
|
6090
6451
|
return el.animate([fullFrame(size, axis), collapsedFrame(axis)], {
|
|
6091
6452
|
duration,
|
|
6092
6453
|
easing,
|
|
6093
6454
|
fill: `forwards`
|
|
6094
|
-
})
|
|
6455
|
+
});
|
|
6095
6456
|
}
|
|
6457
|
+
/**
|
|
6458
|
+
* Collapse + fade `el` out. Resolves once the animation finishes (or straight
|
|
6459
|
+
* away under reduced motion); the caller detaches the element after. The final
|
|
6460
|
+
* collapsed state is held (`fill: forwards`) so there's no flash back to full
|
|
6461
|
+
* size in the gap before removal.
|
|
6462
|
+
*
|
|
6463
|
+
* The returned promise carries an `.animation` handle. If the removal is
|
|
6464
|
+
* reversed (the same key becomes visible again), cancel that handle so its
|
|
6465
|
+
* filled final frame stops overriding the reused element's style.
|
|
6466
|
+
*/
|
|
6467
|
+
function animateListItemOut(el, options = {}) {
|
|
6468
|
+
const animation = startListItemOutAnimation(el, options);
|
|
6469
|
+
if (!animation) return outResult(Promise.resolve(), void 0);
|
|
6470
|
+
return outResult(animation.finished.then(() => void 0, () => void 0), animation);
|
|
6471
|
+
}
|
|
6472
|
+
//#endregion
|
|
6473
|
+
//#region src/interaction/list-native-drag-controller.ts
|
|
6474
|
+
/**
|
|
6475
|
+
* Shared native item/row drag-out for list components.
|
|
6476
|
+
*
|
|
6477
|
+
* Owns capture-phase `dragstart` / `dragend` listeners on the host and its
|
|
6478
|
+
* render root, a `MutationObserver` that keeps light-DOM / slotted item `draggable`
|
|
6479
|
+
* attributes in sync, and a single post-dispatch disposal on
|
|
6480
|
+
* `requestAnimationFrame`. All DOM / selection knowledge lives in the host
|
|
6481
|
+
* config callbacks.
|
|
6482
|
+
*/
|
|
6483
|
+
var ListNativeDragController = class {
|
|
6484
|
+
#host;
|
|
6485
|
+
#config;
|
|
6486
|
+
#dragging = false;
|
|
6487
|
+
#boundRoot;
|
|
6488
|
+
#boundHost = false;
|
|
6489
|
+
#seenDragStarts = /* @__PURE__ */ new WeakSet();
|
|
6490
|
+
#observer;
|
|
6491
|
+
constructor(host, config) {
|
|
6492
|
+
this.#host = host;
|
|
6493
|
+
this.#config = config;
|
|
6494
|
+
host.addController(this);
|
|
6495
|
+
}
|
|
6496
|
+
get isDragging() {
|
|
6497
|
+
return this.#dragging;
|
|
6498
|
+
}
|
|
6499
|
+
/** `"true"` when enabled, else `"false"` — for shadow-row template bindings. */
|
|
6500
|
+
get draggableAttr() {
|
|
6501
|
+
try {
|
|
6502
|
+
return this.#config.isEnabled() ? `true` : `false`;
|
|
6503
|
+
} catch {
|
|
6504
|
+
return `false`;
|
|
6505
|
+
}
|
|
6506
|
+
}
|
|
6507
|
+
/** Re-run the light-DOM `draggable` sync (e.g. after `itemsDraggable` flips). */
|
|
6508
|
+
refreshDraggable() {
|
|
6509
|
+
try {
|
|
6510
|
+
this.#config.syncLightDomDraggable?.();
|
|
6511
|
+
} catch {}
|
|
6512
|
+
}
|
|
6513
|
+
hostConnected() {
|
|
6514
|
+
this.#bind();
|
|
6515
|
+
this.#observer ??= new MutationObserver(() => this.refreshDraggable());
|
|
6516
|
+
try {
|
|
6517
|
+
this.#observer.observe(this.#host, {
|
|
6518
|
+
childList: true,
|
|
6519
|
+
subtree: true
|
|
6520
|
+
});
|
|
6521
|
+
} catch {}
|
|
6522
|
+
this.refreshDraggable();
|
|
6523
|
+
}
|
|
6524
|
+
hostDisconnected() {
|
|
6525
|
+
this.#unbind();
|
|
6526
|
+
try {
|
|
6527
|
+
this.#observer?.disconnect();
|
|
6528
|
+
} catch {}
|
|
6529
|
+
this.#dragging = false;
|
|
6530
|
+
}
|
|
6531
|
+
#renderRoot() {
|
|
6532
|
+
return this.#host.renderRoot ?? this.#host;
|
|
6533
|
+
}
|
|
6534
|
+
#bind() {
|
|
6535
|
+
const root = this.#renderRoot();
|
|
6536
|
+
if (root !== this.#boundRoot) {
|
|
6537
|
+
this.#unbind();
|
|
6538
|
+
this.#boundRoot = root;
|
|
6539
|
+
root.addEventListener(`dragstart`, this.#onDragStart, { capture: true });
|
|
6540
|
+
root.addEventListener(`dragend`, this.#onDragEnd, { capture: true });
|
|
6541
|
+
}
|
|
6542
|
+
if (!this.#boundHost) {
|
|
6543
|
+
this.#boundHost = true;
|
|
6544
|
+
this.#host.addEventListener(`dragstart`, this.#onDragStart, { capture: true });
|
|
6545
|
+
this.#host.addEventListener(`dragend`, this.#onDragEnd, { capture: true });
|
|
6546
|
+
}
|
|
6547
|
+
}
|
|
6548
|
+
#unbind() {
|
|
6549
|
+
this.#boundRoot?.removeEventListener(`dragstart`, this.#onDragStart, { capture: true });
|
|
6550
|
+
this.#boundRoot?.removeEventListener(`dragend`, this.#onDragEnd, { capture: true });
|
|
6551
|
+
this.#boundRoot = void 0;
|
|
6552
|
+
if (this.#boundHost) {
|
|
6553
|
+
this.#boundHost = false;
|
|
6554
|
+
this.#host.removeEventListener(`dragstart`, this.#onDragStart, { capture: true });
|
|
6555
|
+
this.#host.removeEventListener(`dragend`, this.#onDragEnd, { capture: true });
|
|
6556
|
+
}
|
|
6557
|
+
}
|
|
6558
|
+
#onDragStart = (event) => {
|
|
6559
|
+
if (!(event instanceof DragEvent)) return;
|
|
6560
|
+
if (this.#seenDragStarts.has(event)) return;
|
|
6561
|
+
this.#seenDragStarts.add(event);
|
|
6562
|
+
let enabled = false;
|
|
6563
|
+
try {
|
|
6564
|
+
enabled = this.#config.isEnabled();
|
|
6565
|
+
} catch {
|
|
6566
|
+
return;
|
|
6567
|
+
}
|
|
6568
|
+
if (!enabled) return;
|
|
6569
|
+
let originKey;
|
|
6570
|
+
try {
|
|
6571
|
+
originKey = this.#config.resolveEventToKey(event.target);
|
|
6572
|
+
} catch {
|
|
6573
|
+
return;
|
|
6574
|
+
}
|
|
6575
|
+
if (!originKey) return;
|
|
6576
|
+
let prepared;
|
|
6577
|
+
try {
|
|
6578
|
+
prepared = this.#config.prepareSelection(originKey);
|
|
6579
|
+
} catch {
|
|
6580
|
+
return;
|
|
6581
|
+
}
|
|
6582
|
+
if (!prepared || prepared.selected.length === 0) return;
|
|
6583
|
+
const { origin, selected } = prepared;
|
|
6584
|
+
let hostStyle;
|
|
6585
|
+
try {
|
|
6586
|
+
hostStyle = getComputedStyle(this.#host);
|
|
6587
|
+
} catch {
|
|
6588
|
+
hostStyle = document.createElement(`div`).style;
|
|
6589
|
+
}
|
|
6590
|
+
let metrics = {};
|
|
6591
|
+
try {
|
|
6592
|
+
metrics = this.#config.getMetrics() ?? {};
|
|
6593
|
+
} catch {
|
|
6594
|
+
metrics = {};
|
|
6595
|
+
}
|
|
6596
|
+
const context = {
|
|
6597
|
+
source: this.#config.source,
|
|
6598
|
+
origin,
|
|
6599
|
+
selected,
|
|
6600
|
+
metrics,
|
|
6601
|
+
hostStyle
|
|
6602
|
+
};
|
|
6603
|
+
let renderer;
|
|
6604
|
+
try {
|
|
6605
|
+
renderer = this.#config.getRenderer();
|
|
6606
|
+
} catch {
|
|
6607
|
+
renderer = void 0;
|
|
6608
|
+
}
|
|
6609
|
+
let preview;
|
|
6610
|
+
try {
|
|
6611
|
+
preview = renderer ? renderer(context) : createDefaultListDragPreview(context);
|
|
6612
|
+
} catch {
|
|
6613
|
+
preview = createDefaultListDragPreview(context);
|
|
6614
|
+
}
|
|
6615
|
+
try {
|
|
6616
|
+
document.body.appendChild(preview.element);
|
|
6617
|
+
} catch {}
|
|
6618
|
+
const detail = {
|
|
6619
|
+
key: origin.key,
|
|
6620
|
+
index: origin.index,
|
|
6621
|
+
item: origin.item,
|
|
6622
|
+
selectedKeys: selected.map((entry) => entry.key),
|
|
6623
|
+
selected,
|
|
6624
|
+
preview
|
|
6625
|
+
};
|
|
6626
|
+
let notCancelled = true;
|
|
6627
|
+
try {
|
|
6628
|
+
notCancelled = this.#config.dispatch(detail);
|
|
6629
|
+
} catch {
|
|
6630
|
+
notCancelled = true;
|
|
6631
|
+
}
|
|
6632
|
+
if (notCancelled) {
|
|
6633
|
+
const hotspot = preview.hotspot ?? {
|
|
6634
|
+
x: 16,
|
|
6635
|
+
y: 16
|
|
6636
|
+
};
|
|
6637
|
+
try {
|
|
6638
|
+
event.dataTransfer?.setDragImage(preview.element, hotspot.x, hotspot.y);
|
|
6639
|
+
} catch {}
|
|
6640
|
+
} else try {
|
|
6641
|
+
event.preventDefault();
|
|
6642
|
+
} catch {}
|
|
6643
|
+
this.#dragging = true;
|
|
6644
|
+
try {
|
|
6645
|
+
this.#config.onActiveChange(true, origin.key);
|
|
6646
|
+
} catch {}
|
|
6647
|
+
requestAnimationFrame(() => {
|
|
6648
|
+
try {
|
|
6649
|
+
preview.element.remove();
|
|
6650
|
+
} catch {}
|
|
6651
|
+
try {
|
|
6652
|
+
preview.dispose?.();
|
|
6653
|
+
} catch {}
|
|
6654
|
+
});
|
|
6655
|
+
};
|
|
6656
|
+
#onDragEnd = () => {
|
|
6657
|
+
if (!this.#dragging) return;
|
|
6658
|
+
this.#dragging = false;
|
|
6659
|
+
try {
|
|
6660
|
+
this.#config.onActiveChange(false);
|
|
6661
|
+
} catch {}
|
|
6662
|
+
try {
|
|
6663
|
+
this.#config.onEnd();
|
|
6664
|
+
} catch {}
|
|
6665
|
+
};
|
|
6666
|
+
};
|
|
6096
6667
|
//#endregion
|
|
6097
6668
|
//#region src/interaction/list-selection-controller.ts
|
|
6098
6669
|
/** Whether the interaction mode allows building a multi-item selection. */
|
|
@@ -13115,6 +13686,7 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
13115
13686
|
this.allowGrouping = false;
|
|
13116
13687
|
this.crossGroupSelection = false;
|
|
13117
13688
|
this.columnMenu = `auto`;
|
|
13689
|
+
this.itemsDraggable = false;
|
|
13118
13690
|
this._columnFormatters = /* @__PURE__ */ new Map();
|
|
13119
13691
|
this._selectedKeys = /* @__PURE__ */ new Set();
|
|
13120
13692
|
this._scrollTop = 0;
|
|
@@ -13132,7 +13704,45 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
13132
13704
|
id: k,
|
|
13133
13705
|
enabled: true
|
|
13134
13706
|
})),
|
|
13135
|
-
onStateChange: () => this.requestUpdate()
|
|
13707
|
+
onStateChange: () => this.requestUpdate(),
|
|
13708
|
+
hoverDisabled: () => this.#nativeDrag.isDragging
|
|
13709
|
+
});
|
|
13710
|
+
this.#nativeDragging = false;
|
|
13711
|
+
this.#postDragSuppressTimer = 0;
|
|
13712
|
+
this.#nativeDrag = new ListNativeDragController(this, {
|
|
13713
|
+
source: `data-grid`,
|
|
13714
|
+
isEnabled: () => this.itemsDraggable && this.selectionMode !== `none` && this._flat.some((f) => f.type === `row`),
|
|
13715
|
+
resolveEventToKey: (target) => {
|
|
13716
|
+
if (!(target instanceof Element)) return void 0;
|
|
13717
|
+
if (target.closest?.(`.header-cell`)) return void 0;
|
|
13718
|
+
return (target.closest?.(`.row`))?.dataset.key;
|
|
13719
|
+
},
|
|
13720
|
+
prepareSelection: (originKey) => this.#prepareNativeDrag(originKey),
|
|
13721
|
+
getMetrics: () => ({ rowHeight: this.rowHeight }),
|
|
13722
|
+
getRenderer: () => this.dragPreviewRenderer,
|
|
13723
|
+
dispatch: (detail) => this.dispatchEvent(new CustomEvent(`list-native-drag-start`, {
|
|
13724
|
+
detail,
|
|
13725
|
+
bubbles: true,
|
|
13726
|
+
composed: true,
|
|
13727
|
+
cancelable: true
|
|
13728
|
+
})),
|
|
13729
|
+
onActiveChange: (active, originKey) => {
|
|
13730
|
+
this.#nativeDragging = active;
|
|
13731
|
+
this.#dragOriginKey = active ? originKey : void 0;
|
|
13732
|
+
this.toggleAttribute(`data-native-dragging`, active);
|
|
13733
|
+
if (active) {
|
|
13734
|
+
const count = this._selectedKeys.size;
|
|
13735
|
+
this.setAttribute(`aria-label`, count <= 1 ? `Dragging 1 item` : `Dragging ${count} items`);
|
|
13736
|
+
} else this.removeAttribute(`aria-label`);
|
|
13737
|
+
this.requestUpdate();
|
|
13738
|
+
},
|
|
13739
|
+
onEnd: () => {
|
|
13740
|
+
this.#nativeDragging = false;
|
|
13741
|
+
this.#dragOriginKey = void 0;
|
|
13742
|
+
this.toggleAttribute(`data-native-dragging`, false);
|
|
13743
|
+
this.removeAttribute(`aria-label`);
|
|
13744
|
+
this.#startPostDragSuppressTimer();
|
|
13745
|
+
}
|
|
13136
13746
|
});
|
|
13137
13747
|
this._sortedRows = [];
|
|
13138
13748
|
this._flat = [];
|
|
@@ -13404,6 +14014,7 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
13404
14014
|
.row.item.tickled { background: var(--item-bg-tickled); border: var(--item-border-tickled); color: var(--item-text-tickled); }
|
|
13405
14015
|
.row.item.selected { background: var(--item-bg-selected); border: var(--item-border-selected); color: var(--item-text-selected); }
|
|
13406
14016
|
.row.item.selected.tickled { background: var(--item-bg-selected-tickled); }
|
|
14017
|
+
.row.item.dragging-origin { opacity: 0.6; }
|
|
13407
14018
|
|
|
13408
14019
|
/* Insertion / removal animation. Only while [reflowing] — the ~0.3s after
|
|
13409
14020
|
the row set changes — do rows slide (their top transitions) to make or
|
|
@@ -13449,6 +14060,43 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
13449
14060
|
`
|
|
13450
14061
|
];
|
|
13451
14062
|
}
|
|
14063
|
+
#nativeDragging;
|
|
14064
|
+
#dragOriginKey;
|
|
14065
|
+
#postDragSuppressTimer;
|
|
14066
|
+
#nativeDrag;
|
|
14067
|
+
#prepareNativeDrag(originKey) {
|
|
14068
|
+
const rows = this._flat.filter((f) => f.type === `row`);
|
|
14069
|
+
if (!rows.some((f) => f.key === originKey)) return void 0;
|
|
14070
|
+
if (!this._selectedKeys.has(originKey)) this._replaceSelection(originKey);
|
|
14071
|
+
const selected = [];
|
|
14072
|
+
let displayIndex = 0;
|
|
14073
|
+
for (const entry of rows) {
|
|
14074
|
+
if (!this._selectedKeys.has(entry.key)) {
|
|
14075
|
+
displayIndex++;
|
|
14076
|
+
continue;
|
|
14077
|
+
}
|
|
14078
|
+
const rowEl = this.renderRoot.querySelector(`.row[data-key="${CSS.escape(entry.key)}"]`) ?? void 0;
|
|
14079
|
+
selected.push({
|
|
14080
|
+
key: entry.key,
|
|
14081
|
+
index: displayIndex,
|
|
14082
|
+
item: entry.row,
|
|
14083
|
+
...rowEl ? { element: rowEl } : {}
|
|
14084
|
+
});
|
|
14085
|
+
displayIndex++;
|
|
14086
|
+
}
|
|
14087
|
+
const origin = selected.find((entry) => entry.key === originKey);
|
|
14088
|
+
if (!origin) return void 0;
|
|
14089
|
+
return {
|
|
14090
|
+
origin,
|
|
14091
|
+
selected
|
|
14092
|
+
};
|
|
14093
|
+
}
|
|
14094
|
+
#startPostDragSuppressTimer() {
|
|
14095
|
+
if (this.#postDragSuppressTimer) clearTimeout(this.#postDragSuppressTimer);
|
|
14096
|
+
this.#postDragSuppressTimer = window.setTimeout(() => {
|
|
14097
|
+
this.#postDragSuppressTimer = 0;
|
|
14098
|
+
}, 0);
|
|
14099
|
+
}
|
|
13452
14100
|
#searchRegistry;
|
|
13453
14101
|
#unregisterSearchCommands;
|
|
13454
14102
|
#searchKeyByRow;
|
|
@@ -13525,6 +14173,10 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
13525
14173
|
clearTimeout(this.#rowReflowTimer);
|
|
13526
14174
|
this.#rowReflowTimer = 0;
|
|
13527
14175
|
}
|
|
14176
|
+
if (this.#postDragSuppressTimer) {
|
|
14177
|
+
clearTimeout(this.#postDragSuppressTimer);
|
|
14178
|
+
this.#postDragSuppressTimer = 0;
|
|
14179
|
+
}
|
|
13528
14180
|
}
|
|
13529
14181
|
/**
|
|
13530
14182
|
* Dispatch a command to this grid — routes through the command registry so
|
|
@@ -13707,6 +14359,7 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
13707
14359
|
}));
|
|
13708
14360
|
}
|
|
13709
14361
|
_onRowClick(rowKey, col, e) {
|
|
14362
|
+
if (this.#nativeDrag.isDragging || this.#postDragSuppressTimer !== 0) return;
|
|
13710
14363
|
if (col && col.selectable === false) return;
|
|
13711
14364
|
if (this.selectionMode === `none` && this.interactionMode !== `checked` && this.interactionMode !== `sticky`) return;
|
|
13712
14365
|
if (this.interactionMode === `manual`) return;
|
|
@@ -14366,8 +15019,9 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
14366
15019
|
const selected = this._selectedKeys.has(rowKey);
|
|
14367
15020
|
const tickled = this._tickled.isTickled(rowKey);
|
|
14368
15021
|
return b`
|
|
14369
|
-
<div class="row item ${selected ? `selected` : ``} ${tickled ? `tickled` : ``} ${this.#enteringRowKeys.has(rowKey) ? `entering` : ``}" style="top:${absIdx * rh}px; height:${rh}px"
|
|
15022
|
+
<div class="row item ${selected ? `selected` : ``} ${tickled ? `tickled` : ``} ${this.#enteringRowKeys.has(rowKey) ? `entering` : ``} ${this.#nativeDragging && rowKey === this.#dragOriginKey ? `dragging-origin` : ``}" style="top:${absIdx * rh}px; height:${rh}px"
|
|
14370
15023
|
data-key=${rowKey}
|
|
15024
|
+
draggable=${this.#nativeDrag.draggableAttr}
|
|
14371
15025
|
@click=${(e) => {
|
|
14372
15026
|
this._onRowClick(rowKey, null, e);
|
|
14373
15027
|
this.dispatchEvent(new CustomEvent(`datagrid-cell-click`, {
|
|
@@ -14550,6 +15204,12 @@ __decorate([property({
|
|
|
14550
15204
|
attribute: `search-modes`,
|
|
14551
15205
|
reflect: true
|
|
14552
15206
|
})], DataGridElement.prototype, "searchModes", void 0);
|
|
15207
|
+
__decorate([property({
|
|
15208
|
+
type: Boolean,
|
|
15209
|
+
attribute: `items-draggable`,
|
|
15210
|
+
reflect: true
|
|
15211
|
+
})], DataGridElement.prototype, "itemsDraggable", void 0);
|
|
15212
|
+
__decorate([property({ attribute: false })], DataGridElement.prototype, "dragPreviewRenderer", void 0);
|
|
14553
15213
|
__decorate([state()], DataGridElement.prototype, "_selectedKeys", void 0);
|
|
14554
15214
|
__decorate([state()], DataGridElement.prototype, "_scrollTop", void 0);
|
|
14555
15215
|
__decorate([state()], DataGridElement.prototype, "_scrollLeft", void 0);
|
|
@@ -14846,6 +15506,7 @@ let DetailListElement = class DetailListElement extends i {
|
|
|
14846
15506
|
this.iconProperty = ``;
|
|
14847
15507
|
this.keyProperty = ``;
|
|
14848
15508
|
this.itemWrap = `stop`;
|
|
15509
|
+
this.itemsDraggable = false;
|
|
14849
15510
|
this.#itemData = /* @__PURE__ */ new WeakMap();
|
|
14850
15511
|
this.#grid = [];
|
|
14851
15512
|
this.#positions = /* @__PURE__ */ new Map();
|
|
@@ -14881,7 +15542,41 @@ let DetailListElement = class DetailListElement extends i {
|
|
|
14881
15542
|
},
|
|
14882
15543
|
onStateChange: () => this._syncItemStates(),
|
|
14883
15544
|
itemWrap: this.itemWrap,
|
|
14884
|
-
hoverDisabled: () => this.#dragSelect.isDragging
|
|
15545
|
+
hoverDisabled: () => this.#dragSelect.isDragging || this.#nativeDrag.isDragging
|
|
15546
|
+
});
|
|
15547
|
+
this.#nativeDragging = false;
|
|
15548
|
+
this.#postDragSuppressTimer = 0;
|
|
15549
|
+
this.#nativeDrag = new ListNativeDragController(this, {
|
|
15550
|
+
source: `detail-list`,
|
|
15551
|
+
isEnabled: () => this.itemsDraggable && this.selectionMode !== `none` && this._getVisibleItems().length > 0,
|
|
15552
|
+
resolveEventToKey: (target) => {
|
|
15553
|
+
if (!(target instanceof Element)) return void 0;
|
|
15554
|
+
const li = target.closest?.(`li`);
|
|
15555
|
+
if (!li || !this.contains(li)) return void 0;
|
|
15556
|
+
return keyForElement(li);
|
|
15557
|
+
},
|
|
15558
|
+
prepareSelection: (originKey) => this.#prepareNativeDrag(originKey),
|
|
15559
|
+
getMetrics: () => ({}),
|
|
15560
|
+
getRenderer: () => this.dragPreviewRenderer,
|
|
15561
|
+
dispatch: (detail) => this._dispatchCancelable(`list-native-drag-start`, detail),
|
|
15562
|
+
onActiveChange: (active, originKey) => {
|
|
15563
|
+
this.#nativeDragging = active;
|
|
15564
|
+
this.toggleAttribute(`data-native-dragging`, active);
|
|
15565
|
+
for (const el of this.querySelectorAll(`li`)) el.toggleAttribute(`data-drag-origin`, active && originKey !== void 0 && keyForElement(el) === originKey);
|
|
15566
|
+
if (active) {
|
|
15567
|
+
const count = this.selection.selected.size;
|
|
15568
|
+
this.setAttribute(`aria-label`, count <= 1 ? `Dragging 1 item` : `Dragging ${count} items`);
|
|
15569
|
+
} else this.removeAttribute(`aria-label`);
|
|
15570
|
+
this.requestUpdate();
|
|
15571
|
+
},
|
|
15572
|
+
onEnd: () => {
|
|
15573
|
+
this.#nativeDragging = false;
|
|
15574
|
+
this.toggleAttribute(`data-native-dragging`, false);
|
|
15575
|
+
this.removeAttribute(`aria-label`);
|
|
15576
|
+
for (const el of this.querySelectorAll(`li`)) el.removeAttribute(`data-drag-origin`);
|
|
15577
|
+
this.#startPostDragSuppressTimer();
|
|
15578
|
+
},
|
|
15579
|
+
syncLightDomDraggable: () => this._syncNativeDraggable()
|
|
14885
15580
|
});
|
|
14886
15581
|
this.#dragSelect = new ListDragSelectController(this, {
|
|
14887
15582
|
getSurface: () => this.renderRoot.querySelector(`.container`),
|
|
@@ -14978,7 +15673,7 @@ let DetailListElement = class DetailListElement extends i {
|
|
|
14978
15673
|
}
|
|
14979
15674
|
};
|
|
14980
15675
|
this._onClick = (e) => {
|
|
14981
|
-
if (this.#dragSelect.isDragging) return;
|
|
15676
|
+
if (this.#dragSelect.isDragging || this.#nativeDrag.isDragging || this.#postDragSuppressTimer !== 0) return;
|
|
14982
15677
|
const item = this._findListItem(e.composedPath());
|
|
14983
15678
|
if (!item) return;
|
|
14984
15679
|
this.focus();
|
|
@@ -15005,6 +15700,42 @@ let DetailListElement = class DetailListElement extends i {
|
|
|
15005
15700
|
#builtFromProvider;
|
|
15006
15701
|
#providerBuilt;
|
|
15007
15702
|
#data;
|
|
15703
|
+
#nativeDragging;
|
|
15704
|
+
#postDragSuppressTimer;
|
|
15705
|
+
#nativeDrag;
|
|
15706
|
+
#prepareNativeDrag(originKey) {
|
|
15707
|
+
const visible = this._getVisibleItems();
|
|
15708
|
+
const originEl = visible.find((el) => keyForElement(el) === originKey);
|
|
15709
|
+
if (!originEl || !this._isCheckable(originEl)) return void 0;
|
|
15710
|
+
if (!this.selection.selected.has(originEl)) this.selection.replace(originEl);
|
|
15711
|
+
const selected = [];
|
|
15712
|
+
visible.forEach((el, index) => {
|
|
15713
|
+
if (!this.selection.selected.has(el)) return;
|
|
15714
|
+
const key = keyForElement(el) ?? originKey;
|
|
15715
|
+
selected.push({
|
|
15716
|
+
key,
|
|
15717
|
+
index,
|
|
15718
|
+
item: this.#itemData.get(el) ?? el,
|
|
15719
|
+
element: el
|
|
15720
|
+
});
|
|
15721
|
+
});
|
|
15722
|
+
const origin = selected.find((entry) => entry.key === originKey);
|
|
15723
|
+
if (!origin) return void 0;
|
|
15724
|
+
return {
|
|
15725
|
+
origin,
|
|
15726
|
+
selected
|
|
15727
|
+
};
|
|
15728
|
+
}
|
|
15729
|
+
_syncNativeDraggable() {
|
|
15730
|
+
if (!this.isConnected) return;
|
|
15731
|
+
for (const el of this.querySelectorAll(`li`)) if (el instanceof HTMLElement) el.draggable = this.itemsDraggable && this._isCheckable(el);
|
|
15732
|
+
}
|
|
15733
|
+
#startPostDragSuppressTimer() {
|
|
15734
|
+
if (this.#postDragSuppressTimer) clearTimeout(this.#postDragSuppressTimer);
|
|
15735
|
+
this.#postDragSuppressTimer = window.setTimeout(() => {
|
|
15736
|
+
this.#postDragSuppressTimer = 0;
|
|
15737
|
+
}, 0);
|
|
15738
|
+
}
|
|
15008
15739
|
/** Live drag-select preview rect (surface-relative); the covered items carry `data-marquee`. */
|
|
15009
15740
|
#marqueeRect;
|
|
15010
15741
|
#dragSelect;
|
|
@@ -15107,11 +15838,16 @@ let DetailListElement = class DetailListElement extends i {
|
|
|
15107
15838
|
this.#unregisterSearchCommands?.();
|
|
15108
15839
|
this.#unregisterSearchCommands = void 0;
|
|
15109
15840
|
this.#searchRegistry = void 0;
|
|
15841
|
+
if (this.#postDragSuppressTimer) {
|
|
15842
|
+
clearTimeout(this.#postDragSuppressTimer);
|
|
15843
|
+
this.#postDragSuppressTimer = 0;
|
|
15844
|
+
}
|
|
15110
15845
|
}
|
|
15111
15846
|
firstUpdated() {
|
|
15112
15847
|
this.#processChildren();
|
|
15113
15848
|
if (this.filterPredicate) this.#applyFilterPredicate();
|
|
15114
15849
|
this.#recomputeGeometry();
|
|
15850
|
+
this._syncNativeDraggable();
|
|
15115
15851
|
}
|
|
15116
15852
|
updated(changed) {
|
|
15117
15853
|
super.updated(changed);
|
|
@@ -15135,7 +15871,12 @@ let DetailListElement = class DetailListElement extends i {
|
|
|
15135
15871
|
if (changed.has(`interactionMode`)) {
|
|
15136
15872
|
this.selection.clearAnchor();
|
|
15137
15873
|
this._syncItemStates();
|
|
15874
|
+
this._syncNativeDraggable();
|
|
15138
15875
|
} else if (changed.has(`checkboxRenderer`) && this.interactionMode === `checked`) this._syncCheckboxes();
|
|
15876
|
+
if (changed.has(`itemsDraggable`)) {
|
|
15877
|
+
this._syncNativeDraggable();
|
|
15878
|
+
this.#nativeDrag.refreshDraggable();
|
|
15879
|
+
}
|
|
15139
15880
|
}
|
|
15140
15881
|
/** The most recently selected item, or `undefined` if nothing is selected. */
|
|
15141
15882
|
get selectedItem() {
|
|
@@ -15700,6 +16441,14 @@ let DetailListElement = class DetailListElement extends i {
|
|
|
15700
16441
|
composed: true
|
|
15701
16442
|
}));
|
|
15702
16443
|
}
|
|
16444
|
+
_dispatchCancelable(name, detail) {
|
|
16445
|
+
return this.dispatchEvent(new CustomEvent(name, {
|
|
16446
|
+
detail,
|
|
16447
|
+
bubbles: true,
|
|
16448
|
+
composed: true,
|
|
16449
|
+
cancelable: true
|
|
16450
|
+
}));
|
|
16451
|
+
}
|
|
15703
16452
|
_activateItem(item) {
|
|
15704
16453
|
if (this.interactionMode !== `manual`) this.selection.replace(item);
|
|
15705
16454
|
this._dispatch(`list-activate`, { item });
|
|
@@ -15817,6 +16566,10 @@ let DetailListElement = class DetailListElement extends i {
|
|
|
15817
16566
|
color: var(--item-text-selected);
|
|
15818
16567
|
}
|
|
15819
16568
|
|
|
16569
|
+
::slotted([data-drag-origin]) {
|
|
16570
|
+
opacity: 0.6;
|
|
16571
|
+
}
|
|
16572
|
+
|
|
15820
16573
|
/* checked mode: the injected checkbox communicates selection — suppress bg */
|
|
15821
16574
|
:host([interaction-mode="checked"]) ::slotted([data-selected]) {
|
|
15822
16575
|
background: transparent;
|
|
@@ -15906,6 +16659,12 @@ __decorate([property({
|
|
|
15906
16659
|
attribute: `search-modes`,
|
|
15907
16660
|
reflect: true
|
|
15908
16661
|
})], DetailListElement.prototype, "searchModes", void 0);
|
|
16662
|
+
__decorate([property({
|
|
16663
|
+
type: Boolean,
|
|
16664
|
+
attribute: `items-draggable`,
|
|
16665
|
+
reflect: true
|
|
16666
|
+
})], DetailListElement.prototype, "itemsDraggable", void 0);
|
|
16667
|
+
__decorate([property({ attribute: false })], DetailListElement.prototype, "dragPreviewRenderer", void 0);
|
|
15909
16668
|
__decorate([query(`ul`)], DetailListElement.prototype, "_listEl", void 0);
|
|
15910
16669
|
DetailListElement = __decorate([safeCustomElement(`ixfx-detail-list`)], DetailListElement);
|
|
15911
16670
|
//#endregion
|
|
@@ -21944,12 +22703,50 @@ let GridListElement = class GridListElement extends i {
|
|
|
21944
22703
|
},
|
|
21945
22704
|
onStateChange: () => this._syncItemStates(),
|
|
21946
22705
|
itemWrap: this.#itemWrap,
|
|
21947
|
-
hoverDisabled: () => this.disableHoverTickle || this.#dragSelect.isDragging
|
|
22706
|
+
hoverDisabled: () => this.disableHoverTickle || this.#dragSelect.isDragging || this.#nativeDrag.isDragging
|
|
21948
22707
|
});
|
|
21949
22708
|
this.#marqueePreview = /* @__PURE__ */ new Set();
|
|
21950
22709
|
this.#nativeDragging = false;
|
|
21951
22710
|
this.#dragOriginKey = void 0;
|
|
21952
22711
|
this.#postDragSuppressTimer = 0;
|
|
22712
|
+
this.#nativeDrag = new ListNativeDragController(this, {
|
|
22713
|
+
source: `grid-list`,
|
|
22714
|
+
isEnabled: () => this.itemsDraggable && this.selectionMode !== `none` && this.#source.count > 0,
|
|
22715
|
+
resolveEventToKey: (target) => {
|
|
22716
|
+
if (target instanceof Element) {
|
|
22717
|
+
const key = (target.closest?.(`.cell`))?.dataset.key;
|
|
22718
|
+
if (key) return key;
|
|
22719
|
+
const keyed = (target.closest?.(`[data-key]`))?.dataset.key ?? target.dataset?.key ?? keyForElement(target);
|
|
22720
|
+
if (keyed) return keyed;
|
|
22721
|
+
}
|
|
22722
|
+
},
|
|
22723
|
+
prepareSelection: (originKey) => this.#prepareNativeDrag(originKey),
|
|
22724
|
+
getMetrics: () => ({
|
|
22725
|
+
itemSize: this.itemSize,
|
|
22726
|
+
captionStyle: this.captionStyle,
|
|
22727
|
+
captionHeight: this.captionHeight,
|
|
22728
|
+
rowHeight: this.#rowHeight()
|
|
22729
|
+
}),
|
|
22730
|
+
getRenderer: () => this.dragPreviewRenderer,
|
|
22731
|
+
dispatch: (detail) => this._dispatch(`list-native-drag-start`, detail, true),
|
|
22732
|
+
onActiveChange: (active, originKey) => {
|
|
22733
|
+
this.#nativeDragging = active;
|
|
22734
|
+
this.#dragOriginKey = active ? originKey : void 0;
|
|
22735
|
+
this.toggleAttribute(`data-native-dragging`, active);
|
|
22736
|
+
if (active) {
|
|
22737
|
+
const count = [...this.selection.selectedKeys].filter((k) => !isSyntheticKey(k)).length;
|
|
22738
|
+
this.setAttribute(`aria-label`, count <= 1 ? `Dragging 1 item` : `Dragging ${count} items`);
|
|
22739
|
+
} else this.removeAttribute(`aria-label`);
|
|
22740
|
+
this.requestUpdate();
|
|
22741
|
+
},
|
|
22742
|
+
onEnd: () => {
|
|
22743
|
+
this.#clearNativeDragState();
|
|
22744
|
+
this.#startPostDragSuppressTimer();
|
|
22745
|
+
},
|
|
22746
|
+
syncLightDomDraggable: () => {
|
|
22747
|
+
for (const child of this.children) if (child instanceof HTMLElement) child.draggable = this.itemsDraggable;
|
|
22748
|
+
}
|
|
22749
|
+
});
|
|
21953
22750
|
this.#activeCaptionPan = null;
|
|
21954
22751
|
this.#dragSelect = new ListDragSelectController(this, {
|
|
21955
22752
|
getSurface: () => this.#viewportRef.value,
|
|
@@ -21995,23 +22792,6 @@ let GridListElement = class GridListElement extends i {
|
|
|
21995
22792
|
this.#emitViewportChange();
|
|
21996
22793
|
});
|
|
21997
22794
|
};
|
|
21998
|
-
this.#onDragStart = (e, key) => {
|
|
21999
|
-
this.#doDragStart(key, () => e.preventDefault(), e);
|
|
22000
|
-
};
|
|
22001
|
-
this.#onSlottedDragStart = (e) => {
|
|
22002
|
-
if (!this.itemsDraggable) return;
|
|
22003
|
-
let cell = e.composedPath().find((n) => n instanceof Element && n.classList.contains(`cell`));
|
|
22004
|
-
if (!cell && e.target instanceof Element) cell = e.target.closest?.(`.cell`);
|
|
22005
|
-
if (!cell) return;
|
|
22006
|
-
const key = cell.dataset.key;
|
|
22007
|
-
if (!key) return;
|
|
22008
|
-
if (e instanceof DragEvent) this.#doDragStart(key, () => e.preventDefault(), e);
|
|
22009
|
-
else this.#doDragStart(key, () => {});
|
|
22010
|
-
};
|
|
22011
|
-
this.#onDragEnd = () => {
|
|
22012
|
-
this.#clearNativeDragState();
|
|
22013
|
-
this.#startPostDragSuppressTimer();
|
|
22014
|
-
};
|
|
22015
22795
|
this._onKeyDown = (e) => {
|
|
22016
22796
|
if ((e.ctrlKey || e.metaKey) && e.key === `f`) return;
|
|
22017
22797
|
if ((e.ctrlKey || e.metaKey) && e.key === `a`) {
|
|
@@ -22448,6 +23228,35 @@ let GridListElement = class GridListElement extends i {
|
|
|
22448
23228
|
#dragOriginKey;
|
|
22449
23229
|
/** Timer handle for post-drag click suppression. */
|
|
22450
23230
|
#postDragSuppressTimer;
|
|
23231
|
+
#nativeDrag;
|
|
23232
|
+
/** Origin rule + display-ordered entry resolution for native drag-out (both modes). */
|
|
23233
|
+
#prepareNativeDrag(originKey) {
|
|
23234
|
+
const index = this.#source.indexOfKey(originKey);
|
|
23235
|
+
if (index < 0 || !this.#source.isSelectable(index)) return void 0;
|
|
23236
|
+
if (!this.selection.selectedKeys.has(originKey)) this.selection.replace(originKey);
|
|
23237
|
+
const ordered = this.#source.keys().filter((k) => !isSyntheticKey(k) && this.selection.selectedKeys.has(k));
|
|
23238
|
+
const selected = [];
|
|
23239
|
+
for (const key of ordered) {
|
|
23240
|
+
const entryIndex = this.#source.indexOfKey(key);
|
|
23241
|
+
if (entryIndex < 0) continue;
|
|
23242
|
+
const data = this.#source.resolveKeyToData(key);
|
|
23243
|
+
const element = this.#source.resolveKeyToElement(key);
|
|
23244
|
+
const item = data ?? element;
|
|
23245
|
+
if (item === void 0) continue;
|
|
23246
|
+
selected.push({
|
|
23247
|
+
key,
|
|
23248
|
+
index: entryIndex,
|
|
23249
|
+
item,
|
|
23250
|
+
...element ? { element } : {}
|
|
23251
|
+
});
|
|
23252
|
+
}
|
|
23253
|
+
const origin = selected.find((entry) => entry.key === originKey);
|
|
23254
|
+
if (!origin) return void 0;
|
|
23255
|
+
return {
|
|
23256
|
+
origin,
|
|
23257
|
+
selected
|
|
23258
|
+
};
|
|
23259
|
+
}
|
|
22451
23260
|
/**
|
|
22452
23261
|
* The single caption pan-text currently scrolling. At most one caption is
|
|
22453
23262
|
* a pan-text in loop mode at a time — when tickle moves, the old one is
|
|
@@ -22580,7 +23389,7 @@ let GridListElement = class GridListElement extends i {
|
|
|
22580
23389
|
clearTimeout(this.#reflowTimer);
|
|
22581
23390
|
this.#reflowTimer = 0;
|
|
22582
23391
|
}
|
|
22583
|
-
if (this.#nativeDragging) this.#clearNativeDragState();
|
|
23392
|
+
if (this.#nativeDragging || this.#nativeDrag.isDragging) this.#clearNativeDragState();
|
|
22584
23393
|
}
|
|
22585
23394
|
#onChildrenChanged(records) {
|
|
22586
23395
|
const previousLength = this.#items.length;
|
|
@@ -22661,7 +23470,7 @@ let GridListElement = class GridListElement extends i {
|
|
|
22661
23470
|
this.#measureViewport(false);
|
|
22662
23471
|
this.#syncItems();
|
|
22663
23472
|
this.requestUpdate();
|
|
22664
|
-
this.#
|
|
23473
|
+
this.#nativeDrag.refreshDraggable();
|
|
22665
23474
|
}
|
|
22666
23475
|
/** (Re)construct {@link #source} for the current mode and re-apply the filters. */
|
|
22667
23476
|
#rebuildSource() {
|
|
@@ -22751,7 +23560,7 @@ let GridListElement = class GridListElement extends i {
|
|
|
22751
23560
|
this.selection.clearAnchor();
|
|
22752
23561
|
this.#syncAriaMultiselectable();
|
|
22753
23562
|
}
|
|
22754
|
-
if (changed.has(`itemsDraggable`)) this.#
|
|
23563
|
+
if (changed.has(`itemsDraggable`)) this.#nativeDrag.refreshDraggable();
|
|
22755
23564
|
if (changed.has(`orientation`)) {
|
|
22756
23565
|
const vp = this.#viewportRef.value;
|
|
22757
23566
|
if (vp) {
|
|
@@ -23170,8 +23979,6 @@ let GridListElement = class GridListElement extends i {
|
|
|
23170
23979
|
@click=${(e) => this.#onCellClick(e, key)}
|
|
23171
23980
|
@dblclick=${() => this.#onCellActivate(key)}
|
|
23172
23981
|
@pointerenter=${() => this.tickled.handlePointerEnter(key)}
|
|
23173
|
-
@dragstart=${(e) => this.#onDragStart(e, key)}
|
|
23174
|
-
@dragend=${() => this.#onDragEnd()}
|
|
23175
23982
|
>
|
|
23176
23983
|
<div class="content" part="content">${this.#source.renderCellContent(index)}</div>
|
|
23177
23984
|
${showCaption ? this.#renderCaption(caption, captionCss, tickled) : ``}
|
|
@@ -23256,8 +24063,6 @@ let GridListElement = class GridListElement extends i {
|
|
|
23256
24063
|
@click=${(e) => this.#onCellClick(e, key)}
|
|
23257
24064
|
@dblclick=${() => this.#onCellActivate(key)}
|
|
23258
24065
|
@pointerenter=${() => this.tickled.handlePointerEnter(key)}
|
|
23259
|
-
@dragstart=${(e) => this.#onDragStart(e, key)}
|
|
23260
|
-
@dragend=${() => this.#onDragEnd()}
|
|
23261
24066
|
>
|
|
23262
24067
|
<div class="thumb" part="thumb" style=${thumbStyle}>
|
|
23263
24068
|
${this.#source.renderCellContent(index)}
|
|
@@ -23274,145 +24079,10 @@ let GridListElement = class GridListElement extends i {
|
|
|
23274
24079
|
}
|
|
23275
24080
|
}
|
|
23276
24081
|
#onCellClick(e, key) {
|
|
23277
|
-
if (this.#dragSelect.isDragging || this.#nativeDragging || this.#postDragSuppressTimer !== 0) return;
|
|
24082
|
+
if (this.#dragSelect.isDragging || this.#nativeDragging || this.#nativeDrag.isDragging || this.#postDragSuppressTimer !== 0) return;
|
|
23278
24083
|
this.selection.handleClick(key, e);
|
|
23279
24084
|
this.#emitItemEvent(`list-item-click`, key);
|
|
23280
24085
|
}
|
|
23281
|
-
#doDragStart(key, cancelled, dragEvent) {
|
|
23282
|
-
if (!this.itemsDraggable) return false;
|
|
23283
|
-
const index = this.#source.indexOfKey(key);
|
|
23284
|
-
if (index < 0 || !this.#source.isSelectable(index)) return false;
|
|
23285
|
-
if (!this.selection.selectedKeys.has(key)) this.selection.replace(key);
|
|
23286
|
-
const selectedKeys = this.#source.keys().filter((k) => !isSyntheticKey(k)).filter((k) => this.selection.selectedKeys.has(k));
|
|
23287
|
-
const detail = {
|
|
23288
|
-
key,
|
|
23289
|
-
index: this.#source.indexOfKey(key),
|
|
23290
|
-
item: this.#source.resolveKeyToData(key) ?? this.#source.resolveKeyToElement(key),
|
|
23291
|
-
selectedKeys
|
|
23292
|
-
};
|
|
23293
|
-
if (!this._dispatch(`grid-list-native-drag-start`, detail, true)) {
|
|
23294
|
-
cancelled();
|
|
23295
|
-
return false;
|
|
23296
|
-
}
|
|
23297
|
-
this.#nativeDragging = true;
|
|
23298
|
-
this.#dragOriginKey = key;
|
|
23299
|
-
this.toggleAttribute(`data-native-dragging`, true);
|
|
23300
|
-
const count = selectedKeys.length;
|
|
23301
|
-
this.setAttribute(`aria-label`, count === 1 ? `Dragging 1 item` : `Dragging ${count} items`);
|
|
23302
|
-
if (dragEvent && count > 1) this.#setMultiItemDragImage(dragEvent, selectedKeys);
|
|
23303
|
-
return true;
|
|
23304
|
-
}
|
|
23305
|
-
#setMultiItemDragImage(e, selectedKeys) {
|
|
23306
|
-
const preview = this.#createMultiItemPreview(selectedKeys);
|
|
23307
|
-
document.body.appendChild(preview);
|
|
23308
|
-
const rect = preview.getBoundingClientRect();
|
|
23309
|
-
e.dataTransfer?.setDragImage(preview, rect.width / 2, rect.height / 2);
|
|
23310
|
-
requestAnimationFrame(() => preview.remove());
|
|
23311
|
-
}
|
|
23312
|
-
#createMultiItemPreview(selectedKeys) {
|
|
23313
|
-
const preview = document.createElement(`div`);
|
|
23314
|
-
preview.style.cssText = `
|
|
23315
|
-
position: fixed;
|
|
23316
|
-
top: -9999px;
|
|
23317
|
-
left: -9999px;
|
|
23318
|
-
display: flex;
|
|
23319
|
-
flex-direction: column;
|
|
23320
|
-
gap: 4px;
|
|
23321
|
-
padding: 8px;
|
|
23322
|
-
background: var(--surface-4, #333);
|
|
23323
|
-
border: 1px solid var(--border, #555);
|
|
23324
|
-
border-radius: 8px;
|
|
23325
|
-
box-shadow: 0 4px 16px rgba(0,0,0,0.3);
|
|
23326
|
-
font-family: system-ui, sans-serif;
|
|
23327
|
-
font-size: 12px;
|
|
23328
|
-
color: var(--surface-text, #fff);
|
|
23329
|
-
max-width: 200px;
|
|
23330
|
-
z-index: 999999;
|
|
23331
|
-
`;
|
|
23332
|
-
const header = document.createElement(`div`);
|
|
23333
|
-
header.style.cssText = `
|
|
23334
|
-
font-weight: 600;
|
|
23335
|
-
padding-bottom: 4px;
|
|
23336
|
-
border-bottom: 1px solid var(--border, #555);
|
|
23337
|
-
margin-bottom: 4px;
|
|
23338
|
-
`;
|
|
23339
|
-
header.textContent = `${selectedKeys.length} items`;
|
|
23340
|
-
preview.appendChild(header);
|
|
23341
|
-
for (const key of selectedKeys.slice(0, 5)) {
|
|
23342
|
-
const row = this.#createPreviewRow(key);
|
|
23343
|
-
if (row) preview.appendChild(row);
|
|
23344
|
-
}
|
|
23345
|
-
if (selectedKeys.length > 5) {
|
|
23346
|
-
const more = document.createElement(`div`);
|
|
23347
|
-
more.style.cssText = `opacity: 0.6; text-align: center;`;
|
|
23348
|
-
more.textContent = `+${selectedKeys.length - 5} more`;
|
|
23349
|
-
preview.appendChild(more);
|
|
23350
|
-
}
|
|
23351
|
-
return preview;
|
|
23352
|
-
}
|
|
23353
|
-
#createPreviewRow(key) {
|
|
23354
|
-
const el = this.#source.resolveKeyToElement(key);
|
|
23355
|
-
if (!el) return null;
|
|
23356
|
-
const row = document.createElement(`div`);
|
|
23357
|
-
row.style.cssText = `
|
|
23358
|
-
display: flex;
|
|
23359
|
-
align-items: center;
|
|
23360
|
-
gap: 6px;
|
|
23361
|
-
`;
|
|
23362
|
-
const thumb = document.createElement(`div`);
|
|
23363
|
-
thumb.style.cssText = `
|
|
23364
|
-
width: 32px;
|
|
23365
|
-
height: 32px;
|
|
23366
|
-
border-radius: 4px;
|
|
23367
|
-
overflow: hidden;
|
|
23368
|
-
background: var(--surface-5, #444);
|
|
23369
|
-
flex-shrink: 0;
|
|
23370
|
-
display: flex;
|
|
23371
|
-
align-items: center;
|
|
23372
|
-
justify-content: center;
|
|
23373
|
-
`;
|
|
23374
|
-
const slottedImg = el.querySelector(`img`);
|
|
23375
|
-
const slottedSvg = el.querySelector(`svg`);
|
|
23376
|
-
const slottedPlaceholder = el.querySelector(`.placeholder`);
|
|
23377
|
-
if (slottedImg) {
|
|
23378
|
-
const img = slottedImg.cloneNode(true);
|
|
23379
|
-
img.style.cssText = `width: 100%; height: 100%; object-fit: cover;`;
|
|
23380
|
-
thumb.appendChild(img);
|
|
23381
|
-
} else if (slottedSvg) {
|
|
23382
|
-
const svg = slottedSvg.cloneNode(true);
|
|
23383
|
-
svg.style.cssText = `width: 70%; height: 70%; opacity: 0.8;`;
|
|
23384
|
-
thumb.appendChild(svg);
|
|
23385
|
-
} else if (slottedPlaceholder) thumb.textContent = slottedPlaceholder.textContent || `?`;
|
|
23386
|
-
const label = document.createElement(`span`);
|
|
23387
|
-
label.style.cssText = `
|
|
23388
|
-
flex: 1;
|
|
23389
|
-
overflow: hidden;
|
|
23390
|
-
text-overflow: ellipsis;
|
|
23391
|
-
white-space: nowrap;
|
|
23392
|
-
`;
|
|
23393
|
-
label.textContent = el.getAttribute(`data-label`) || key;
|
|
23394
|
-
row.appendChild(thumb);
|
|
23395
|
-
row.appendChild(label);
|
|
23396
|
-
return row;
|
|
23397
|
-
}
|
|
23398
|
-
#onDragStart;
|
|
23399
|
-
#onSlottedDragStart;
|
|
23400
|
-
#initSlottedDragInterceptor() {
|
|
23401
|
-
this.renderRoot.addEventListener(`dragstart`, this.#onSlottedDragStart, { capture: true });
|
|
23402
|
-
const observer = new MutationObserver(() => this.#syncSlottedDraggable());
|
|
23403
|
-
observer.observe(this, {
|
|
23404
|
-
childList: true,
|
|
23405
|
-
subtree: true
|
|
23406
|
-
});
|
|
23407
|
-
this.#slottedDragObserver = observer;
|
|
23408
|
-
this.#syncSlottedDraggable();
|
|
23409
|
-
}
|
|
23410
|
-
#slottedDragObserver;
|
|
23411
|
-
#syncSlottedDraggable() {
|
|
23412
|
-
const draggable = this.itemsDraggable;
|
|
23413
|
-
for (const child of this.children) if (child instanceof HTMLElement) child.draggable = draggable;
|
|
23414
|
-
}
|
|
23415
|
-
#onDragEnd;
|
|
23416
24086
|
#startPostDragSuppressTimer() {
|
|
23417
24087
|
if (this.#postDragSuppressTimer) clearTimeout(this.#postDragSuppressTimer);
|
|
23418
24088
|
this.#postDragSuppressTimer = window.setTimeout(() => {
|
|
@@ -23487,6 +24157,7 @@ __decorate([property({
|
|
|
23487
24157
|
attribute: `items-draggable`,
|
|
23488
24158
|
reflect: true
|
|
23489
24159
|
})], GridListElement.prototype, "itemsDraggable", void 0);
|
|
24160
|
+
__decorate([property({ attribute: false })], GridListElement.prototype, "dragPreviewRenderer", void 0);
|
|
23490
24161
|
__decorate([property({
|
|
23491
24162
|
type: String,
|
|
23492
24163
|
attribute: `search-modes`,
|
|
@@ -23915,7 +24586,7 @@ let TreeBaseElement = class TreeBaseElement extends i {
|
|
|
23915
24586
|
this.#lastNodeByKey = /* @__PURE__ */ new Map();
|
|
23916
24587
|
this.#enteringKeys = /* @__PURE__ */ new Set();
|
|
23917
24588
|
this.#leaving = /* @__PURE__ */ new Map();
|
|
23918
|
-
this.#
|
|
24589
|
+
this.#leavingAnimations = /* @__PURE__ */ new Map();
|
|
23919
24590
|
this.#treeAnimReady = false;
|
|
23920
24591
|
this.#onKeyDown = (event) => {
|
|
23921
24592
|
if (this.search.isOpen) return;
|
|
@@ -24026,11 +24697,17 @@ let TreeBaseElement = class TreeBaseElement extends i {
|
|
|
24026
24697
|
if (!key) return;
|
|
24027
24698
|
const node = this.#getAllNodes().find((n) => n.node.item.key === key);
|
|
24028
24699
|
if (!node) return;
|
|
24700
|
+
const detail = {
|
|
24701
|
+
node: node.node,
|
|
24702
|
+
depth: node.depth
|
|
24703
|
+
};
|
|
24704
|
+
this.dispatchEvent(new CustomEvent(`item-dblclick`, {
|
|
24705
|
+
detail,
|
|
24706
|
+
bubbles: true,
|
|
24707
|
+
composed: true
|
|
24708
|
+
}));
|
|
24029
24709
|
this.dispatchEvent(new CustomEvent(`activate`, {
|
|
24030
|
-
detail
|
|
24031
|
-
node: node.node,
|
|
24032
|
-
depth: node.depth
|
|
24033
|
-
},
|
|
24710
|
+
detail,
|
|
24034
24711
|
bubbles: true,
|
|
24035
24712
|
composed: true
|
|
24036
24713
|
}));
|
|
@@ -24062,8 +24739,18 @@ let TreeBaseElement = class TreeBaseElement extends i {
|
|
|
24062
24739
|
#lastNodeByKey;
|
|
24063
24740
|
#enteringKeys;
|
|
24064
24741
|
#leaving;
|
|
24065
|
-
#
|
|
24742
|
+
#leavingAnimations;
|
|
24066
24743
|
#treeAnimReady;
|
|
24744
|
+
#cancelLeavingAnimation(key) {
|
|
24745
|
+
this.#leavingAnimations.get(key)?.cancel();
|
|
24746
|
+
this.#leavingAnimations.delete(key);
|
|
24747
|
+
}
|
|
24748
|
+
#cancelAllLeavingAnimations() {
|
|
24749
|
+
for (const animation of this.#leavingAnimations.values()) try {
|
|
24750
|
+
animation.cancel();
|
|
24751
|
+
} catch {}
|
|
24752
|
+
this.#leavingAnimations.clear();
|
|
24753
|
+
}
|
|
24067
24754
|
willUpdate(changedProps) {
|
|
24068
24755
|
super.willUpdate(changedProps);
|
|
24069
24756
|
this.#diffVisibleNodes();
|
|
@@ -24082,12 +24769,12 @@ let TreeBaseElement = class TreeBaseElement extends i {
|
|
|
24082
24769
|
}
|
|
24083
24770
|
}
|
|
24084
24771
|
for (const key of [...this.#leaving.keys()]) if (nowKeys.has(key)) {
|
|
24772
|
+
this.#cancelLeavingAnimation(key);
|
|
24085
24773
|
this.#leaving.delete(key);
|
|
24086
|
-
this.#leavingAnimating.delete(key);
|
|
24087
24774
|
}
|
|
24088
24775
|
if (this.#leaving.size > MAX_ANIMATED_ROWS) {
|
|
24776
|
+
this.#cancelAllLeavingAnimations();
|
|
24089
24777
|
this.#leaving.clear();
|
|
24090
|
-
this.#leavingAnimating.clear();
|
|
24091
24778
|
}
|
|
24092
24779
|
}
|
|
24093
24780
|
/** True while `node` is a fading ghost row (removed / collapsed, still animating out). */
|
|
@@ -24124,18 +24811,38 @@ let TreeBaseElement = class TreeBaseElement extends i {
|
|
|
24124
24811
|
if (this.#enteringKeys.size > 0) {
|
|
24125
24812
|
for (const el of this.renderRoot.querySelectorAll(`.item`)) {
|
|
24126
24813
|
const key = el.dataset.key;
|
|
24127
|
-
if (key
|
|
24814
|
+
if (key === void 0 || !this.#enteringKeys.has(key)) continue;
|
|
24815
|
+
if (this.#leavingAnimations.has(key)) this.#cancelLeavingAnimation(key);
|
|
24816
|
+
else for (const animation of el.getAnimations()) animation.cancel();
|
|
24817
|
+
animateListItemIn(el);
|
|
24128
24818
|
}
|
|
24129
24819
|
this.#enteringKeys.clear();
|
|
24130
24820
|
}
|
|
24131
24821
|
if (this.#leaving.size > 0) for (const el of this.renderRoot.querySelectorAll(`.item.leaving`)) {
|
|
24132
24822
|
const key = el.dataset.key;
|
|
24133
|
-
if (key === void 0 || this.#
|
|
24134
|
-
|
|
24135
|
-
|
|
24823
|
+
if (key === void 0 || this.#leavingAnimations.has(key)) continue;
|
|
24824
|
+
const result = animateListItemOut(el);
|
|
24825
|
+
const animation = result.animation;
|
|
24826
|
+
if (!animation) {
|
|
24827
|
+
result.then(() => {
|
|
24828
|
+
if (!this.#leaving.has(key)) return;
|
|
24829
|
+
this.#leaving.delete(key);
|
|
24830
|
+
this.requestUpdate();
|
|
24831
|
+
});
|
|
24832
|
+
continue;
|
|
24833
|
+
}
|
|
24834
|
+
this.#cancelLeavingAnimation(key);
|
|
24835
|
+
this.#leavingAnimations.set(key, animation);
|
|
24836
|
+
result.then(() => {
|
|
24837
|
+
if (this.#leavingAnimations.get(key) !== animation) return;
|
|
24838
|
+
this.#leavingAnimations.delete(key);
|
|
24136
24839
|
this.#leaving.delete(key);
|
|
24137
|
-
this.#leavingAnimating.delete(key);
|
|
24138
24840
|
this.requestUpdate();
|
|
24841
|
+
this.updateComplete.then(() => {
|
|
24842
|
+
try {
|
|
24843
|
+
animation.cancel();
|
|
24844
|
+
} catch {}
|
|
24845
|
+
});
|
|
24139
24846
|
});
|
|
24140
24847
|
}
|
|
24141
24848
|
const visible = this.root ? this.#getAllNodes() : [];
|
|
@@ -24151,6 +24858,9 @@ let TreeBaseElement = class TreeBaseElement extends i {
|
|
|
24151
24858
|
this.#clearSelectionInternal();
|
|
24152
24859
|
this.tickled.clearTickled();
|
|
24153
24860
|
this._focusedDepth = 0;
|
|
24861
|
+
this.#cancelAllLeavingAnimations();
|
|
24862
|
+
this.#leaving.clear();
|
|
24863
|
+
this.#enteringKeys.clear();
|
|
24154
24864
|
}
|
|
24155
24865
|
if (changedProps.has(`model`)) {
|
|
24156
24866
|
this.#modelUnsubscribe?.();
|
|
@@ -24201,6 +24911,9 @@ let TreeBaseElement = class TreeBaseElement extends i {
|
|
|
24201
24911
|
}
|
|
24202
24912
|
disconnectedCallback() {
|
|
24203
24913
|
super.disconnectedCallback();
|
|
24914
|
+
this.#cancelAllLeavingAnimations();
|
|
24915
|
+
this.#leaving.clear();
|
|
24916
|
+
this.#enteringKeys.clear();
|
|
24204
24917
|
this.#modelUnsubscribe?.();
|
|
24205
24918
|
this.#modelUnsubscribe = void 0;
|
|
24206
24919
|
this.#unregisterSearchCommands?.();
|
|
@@ -24379,6 +25092,7 @@ let TreeBaseElement = class TreeBaseElement extends i {
|
|
|
24379
25092
|
`;
|
|
24380
25093
|
}
|
|
24381
25094
|
_handleItemClick(node, depth, event) {
|
|
25095
|
+
if (event && event.detail >= 2) return;
|
|
24382
25096
|
if (this.#pendingNode && this._expandedKeys.has(this.#pendingNode.item.key)) this.#abortPending();
|
|
24383
25097
|
this.tickled.handlePointerEnter(node.item.key);
|
|
24384
25098
|
this._focusedDepth = depth;
|
|
@@ -24392,7 +25106,7 @@ let TreeBaseElement = class TreeBaseElement extends i {
|
|
|
24392
25106
|
}));
|
|
24393
25107
|
switch (this.interactionMode) {
|
|
24394
25108
|
case `implicit`:
|
|
24395
|
-
this.#handleImplicitClick(node, depth);
|
|
25109
|
+
this.#handleImplicitClick(node, depth, event);
|
|
24396
25110
|
break;
|
|
24397
25111
|
case `standard`:
|
|
24398
25112
|
this.#handleStandardClick(node, depth, event);
|
|
@@ -24407,8 +25121,20 @@ let TreeBaseElement = class TreeBaseElement extends i {
|
|
|
24407
25121
|
}
|
|
24408
25122
|
this.requestUpdate();
|
|
24409
25123
|
}
|
|
24410
|
-
|
|
24411
|
-
|
|
25124
|
+
/**
|
|
25125
|
+
* True when a click landed on the expand/collapse caret rather than the node
|
|
25126
|
+
* label. Caret clicks should only toggle expansion, never select or navigate.
|
|
25127
|
+
* The caret and label are siblings in the same shadow root, so `closest` on
|
|
25128
|
+
* the event target resolves reliably. See tree-fix.md.
|
|
25129
|
+
*/
|
|
25130
|
+
#clickedOnCaret(node, event) {
|
|
25131
|
+
if (node.item.isLeaf === true) return false;
|
|
25132
|
+
const target = event?.target;
|
|
25133
|
+
if (!(target instanceof Element)) return false;
|
|
25134
|
+
return target.closest(`.tree-caret`) !== null;
|
|
25135
|
+
}
|
|
25136
|
+
#handleImplicitClick(node, depth, event) {
|
|
25137
|
+
if (!this.#clickedOnCaret(node, event) && this.#canSelect(node)) {
|
|
24412
25138
|
const prev = new Set(this._selectedNodes);
|
|
24413
25139
|
this._selectedNodes.clear();
|
|
24414
25140
|
this._selectedNodes.add(node);
|
|
@@ -24453,7 +25179,7 @@ let TreeBaseElement = class TreeBaseElement extends i {
|
|
|
24453
25179
|
}
|
|
24454
25180
|
return;
|
|
24455
25181
|
}
|
|
24456
|
-
if (this.#canSelect(node)) {
|
|
25182
|
+
if (!this.#clickedOnCaret(node, event) && this.#canSelect(node)) {
|
|
24457
25183
|
const prev = new Set(this._selectedNodes);
|
|
24458
25184
|
this._selectedNodes.clear();
|
|
24459
25185
|
this._selectedNodes.add(node);
|
|
@@ -24848,8 +25574,8 @@ let TreeBaseElement = class TreeBaseElement extends i {
|
|
|
24848
25574
|
--tree-text: var(--surface-3-text);
|
|
24849
25575
|
--tree-muted-text: var(--surface-muted-text);
|
|
24850
25576
|
--tree-indent: 1ch;
|
|
24851
|
-
--tree-item-height:
|
|
24852
|
-
--tree-caret-size:
|
|
25577
|
+
--tree-item-height: 30px;
|
|
25578
|
+
--tree-caret-size: 30px;
|
|
24853
25579
|
--tree-radius: var(--radius-s);
|
|
24854
25580
|
|
|
24855
25581
|
position: relative;
|
|
@@ -24895,10 +25621,14 @@ let TreeBaseElement = class TreeBaseElement extends i {
|
|
|
24895
25621
|
display: inline-flex;
|
|
24896
25622
|
align-items: center;
|
|
24897
25623
|
justify-content: center;
|
|
24898
|
-
|
|
25624
|
+
/* Deliberately narrower than the icon: Lucide chevrons fill only ~half
|
|
25625
|
+
their viewBox, so letting the glyph overflow a slim box closes the
|
|
25626
|
+
visual gap to the label without shifting the indent. */
|
|
25627
|
+
width: calc(var(--tree-caret-size) * 0.5);
|
|
24899
25628
|
height: var(--tree-caret-size);
|
|
24900
25629
|
flex-shrink: 0;
|
|
24901
|
-
margin-right:
|
|
25630
|
+
margin-right: 1px;
|
|
25631
|
+
overflow: visible;
|
|
24902
25632
|
}
|
|
24903
25633
|
|
|
24904
25634
|
.caret-icon {
|
|
@@ -25095,10 +25825,14 @@ let TreeListElement = class TreeListElement extends TreeBaseElement {
|
|
|
25095
25825
|
display: inline-flex;
|
|
25096
25826
|
align-items: center;
|
|
25097
25827
|
justify-content: center;
|
|
25098
|
-
|
|
25828
|
+
/* Deliberately narrower than the icon: Lucide chevrons fill only ~half
|
|
25829
|
+
their viewBox, so letting the glyph overflow a slim box closes the
|
|
25830
|
+
visual gap to the label without shifting the indent. */
|
|
25831
|
+
width: calc(var(--tree-caret-size) * 0.5);
|
|
25099
25832
|
height: var(--tree-caret-size);
|
|
25100
25833
|
flex-shrink: 0;
|
|
25101
|
-
margin-right:
|
|
25834
|
+
margin-right: 1px;
|
|
25835
|
+
overflow: visible;
|
|
25102
25836
|
}
|
|
25103
25837
|
|
|
25104
25838
|
.caret-icon {
|
|
@@ -25116,7 +25850,7 @@ let TreeListElement = class TreeListElement extends TreeBaseElement {
|
|
|
25116
25850
|
flex-shrink: 0;
|
|
25117
25851
|
width: var(--icon-size, 1em);
|
|
25118
25852
|
height: var(--icon-size, 1em);
|
|
25119
|
-
margin-right: var(--icon-spacing,
|
|
25853
|
+
margin-right: var(--icon-spacing, 0px);
|
|
25120
25854
|
}
|
|
25121
25855
|
|
|
25122
25856
|
.item:not(.has-icon-at-depth) .tree-icon {
|
|
@@ -25344,6 +26078,7 @@ let VerticalListElement = class VerticalListElement extends i {
|
|
|
25344
26078
|
this.selectionMode = `single`;
|
|
25345
26079
|
this.interactionMode = `standard`;
|
|
25346
26080
|
this.itemWrap = `stop`;
|
|
26081
|
+
this.itemsDraggable = false;
|
|
25347
26082
|
this.#customWrappers = /* @__PURE__ */ new Map();
|
|
25348
26083
|
this.#wrappedElements = /* @__PURE__ */ new Set();
|
|
25349
26084
|
this.#animatedItems = /* @__PURE__ */ new WeakSet();
|
|
@@ -25374,7 +26109,41 @@ let VerticalListElement = class VerticalListElement extends i {
|
|
|
25374
26109
|
},
|
|
25375
26110
|
onStateChange: () => this._syncItemStates(),
|
|
25376
26111
|
itemWrap: this.itemWrap,
|
|
25377
|
-
hoverDisabled: () => this.#dragSelect.isDragging
|
|
26112
|
+
hoverDisabled: () => this.#dragSelect.isDragging || this.#nativeDrag.isDragging
|
|
26113
|
+
});
|
|
26114
|
+
this.#nativeDragging = false;
|
|
26115
|
+
this.#postDragSuppressTimer = 0;
|
|
26116
|
+
this.#nativeDrag = new ListNativeDragController(this, {
|
|
26117
|
+
source: `vertical-list`,
|
|
26118
|
+
isEnabled: () => this.itemsDraggable && this.selectionMode !== `none` && this._getVisibleItems().length > 0,
|
|
26119
|
+
resolveEventToKey: (target) => {
|
|
26120
|
+
if (!(target instanceof Element)) return void 0;
|
|
26121
|
+
const item = target.closest?.(ITEM_SELECTOR);
|
|
26122
|
+
if (!item || !this.contains(item) || this.#wrappedElements.has(item)) return void 0;
|
|
26123
|
+
return keyForElement(item);
|
|
26124
|
+
},
|
|
26125
|
+
prepareSelection: (originKey) => this.#prepareNativeDrag(originKey),
|
|
26126
|
+
getMetrics: () => ({}),
|
|
26127
|
+
getRenderer: () => this.dragPreviewRenderer,
|
|
26128
|
+
dispatch: (detail) => this._dispatchCancelable(`list-native-drag-start`, detail),
|
|
26129
|
+
onActiveChange: (active, originKey) => {
|
|
26130
|
+
this.#nativeDragging = active;
|
|
26131
|
+
this.toggleAttribute(`data-native-dragging`, active);
|
|
26132
|
+
for (const el of this._getVisibleItems()) el.toggleAttribute(`data-drag-origin`, active && originKey !== void 0 && keyForElement(el) === originKey);
|
|
26133
|
+
if (active) {
|
|
26134
|
+
const count = this.selection.selected.size;
|
|
26135
|
+
this.setAttribute(`aria-label`, count <= 1 ? `Dragging 1 item` : `Dragging ${count} items`);
|
|
26136
|
+
} else this.removeAttribute(`aria-label`);
|
|
26137
|
+
this.requestUpdate();
|
|
26138
|
+
},
|
|
26139
|
+
onEnd: () => {
|
|
26140
|
+
this.#nativeDragging = false;
|
|
26141
|
+
this.toggleAttribute(`data-native-dragging`, false);
|
|
26142
|
+
this.removeAttribute(`aria-label`);
|
|
26143
|
+
for (const el of this._getVisibleItems()) el.removeAttribute(`data-drag-origin`);
|
|
26144
|
+
this.#startPostDragSuppressTimer();
|
|
26145
|
+
},
|
|
26146
|
+
syncLightDomDraggable: () => this._syncNativeDraggable()
|
|
25378
26147
|
});
|
|
25379
26148
|
this.#dragSelect = new ListDragSelectController(this, {
|
|
25380
26149
|
getSurface: () => this.renderRoot.querySelector(`.container`),
|
|
@@ -25456,7 +26225,7 @@ let VerticalListElement = class VerticalListElement extends i {
|
|
|
25456
26225
|
}
|
|
25457
26226
|
};
|
|
25458
26227
|
this._onClick = (e) => {
|
|
25459
|
-
if (this.#dragSelect.isDragging) return;
|
|
26228
|
+
if (this.#dragSelect.isDragging || this.#nativeDrag.isDragging || this.#postDragSuppressTimer !== 0) return;
|
|
25460
26229
|
const item = this._findListItem(e.composedPath());
|
|
25461
26230
|
if (!item) return;
|
|
25462
26231
|
this._dispatch(`list-item-click`, { item });
|
|
@@ -25473,6 +26242,44 @@ let VerticalListElement = class VerticalListElement extends i {
|
|
|
25473
26242
|
#itemObserver;
|
|
25474
26243
|
/** Items that have already played (or been skipped for) their enter animation. */
|
|
25475
26244
|
#animatedItems;
|
|
26245
|
+
#nativeDragging;
|
|
26246
|
+
#postDragSuppressTimer;
|
|
26247
|
+
#nativeDrag;
|
|
26248
|
+
#prepareNativeDrag(originKey) {
|
|
26249
|
+
const visible = this._getVisibleItems();
|
|
26250
|
+
const originEl = visible.find((el) => keyForElement(el) === originKey);
|
|
26251
|
+
if (!originEl || !this._isCheckable(originEl)) return void 0;
|
|
26252
|
+
if (!this.selection.selected.has(originEl)) this.selection.replace(originEl);
|
|
26253
|
+
const selected = [];
|
|
26254
|
+
visible.forEach((el, index) => {
|
|
26255
|
+
if (!this.selection.selected.has(el)) return;
|
|
26256
|
+
selected.push({
|
|
26257
|
+
key: keyForElement(el) ?? originKey,
|
|
26258
|
+
index,
|
|
26259
|
+
item: el,
|
|
26260
|
+
element: el
|
|
26261
|
+
});
|
|
26262
|
+
});
|
|
26263
|
+
const origin = selected.find((entry) => entry.key === originKey);
|
|
26264
|
+
if (!origin) return void 0;
|
|
26265
|
+
return {
|
|
26266
|
+
origin,
|
|
26267
|
+
selected
|
|
26268
|
+
};
|
|
26269
|
+
}
|
|
26270
|
+
_syncNativeDraggable() {
|
|
26271
|
+
if (!this.isConnected) return;
|
|
26272
|
+
for (const el of this.querySelectorAll(ITEM_SELECTOR)) {
|
|
26273
|
+
if (this.#wrappedElements.has(el)) continue;
|
|
26274
|
+
if (el instanceof HTMLElement) el.draggable = this.itemsDraggable && this._isCheckable(el);
|
|
26275
|
+
}
|
|
26276
|
+
}
|
|
26277
|
+
#startPostDragSuppressTimer() {
|
|
26278
|
+
if (this.#postDragSuppressTimer) clearTimeout(this.#postDragSuppressTimer);
|
|
26279
|
+
this.#postDragSuppressTimer = window.setTimeout(() => {
|
|
26280
|
+
this.#postDragSuppressTimer = 0;
|
|
26281
|
+
}, 0);
|
|
26282
|
+
}
|
|
25476
26283
|
/** Live drag-select preview rect (surface-relative); the covered items carry `data-marquee`. */
|
|
25477
26284
|
#marqueeRect;
|
|
25478
26285
|
#dragSelect;
|
|
@@ -25540,6 +26347,10 @@ let VerticalListElement = class VerticalListElement extends i {
|
|
|
25540
26347
|
this.#unregisterSearchCommands?.();
|
|
25541
26348
|
this.#unregisterSearchCommands = void 0;
|
|
25542
26349
|
this.#searchRegistry = void 0;
|
|
26350
|
+
if (this.#postDragSuppressTimer) {
|
|
26351
|
+
clearTimeout(this.#postDragSuppressTimer);
|
|
26352
|
+
this.#postDragSuppressTimer = 0;
|
|
26353
|
+
}
|
|
25543
26354
|
}
|
|
25544
26355
|
/**
|
|
25545
26356
|
* Animate in items appended to the light DOM (however they got there —
|
|
@@ -25579,6 +26390,10 @@ let VerticalListElement = class VerticalListElement extends i {
|
|
|
25579
26390
|
}
|
|
25580
26391
|
this._syncItemStates();
|
|
25581
26392
|
} else if (changed.has(`checkboxRenderer`) && this.interactionMode === `checked`) this._syncCheckboxes();
|
|
26393
|
+
if (changed.has(`itemsDraggable`) || changed.has(`interactionMode`)) {
|
|
26394
|
+
this._syncNativeDraggable();
|
|
26395
|
+
this.#nativeDrag.refreshDraggable();
|
|
26396
|
+
}
|
|
25582
26397
|
}
|
|
25583
26398
|
/** The most recently selected item, or `undefined` if nothing is selected. */
|
|
25584
26399
|
get selectedItem() {
|
|
@@ -25848,6 +26663,14 @@ let VerticalListElement = class VerticalListElement extends i {
|
|
|
25848
26663
|
composed: true
|
|
25849
26664
|
}));
|
|
25850
26665
|
}
|
|
26666
|
+
_dispatchCancelable(name, detail) {
|
|
26667
|
+
return this.dispatchEvent(new CustomEvent(name, {
|
|
26668
|
+
detail,
|
|
26669
|
+
bubbles: true,
|
|
26670
|
+
composed: true,
|
|
26671
|
+
cancelable: true
|
|
26672
|
+
}));
|
|
26673
|
+
}
|
|
25851
26674
|
_activateItem(item) {
|
|
25852
26675
|
if (this.interactionMode !== `manual`) this.selection.replace(item);
|
|
25853
26676
|
this._dispatch(`list-activate`, { item });
|
|
@@ -25983,6 +26806,10 @@ let VerticalListElement = class VerticalListElement extends i {
|
|
|
25983
26806
|
color: var(--item-text-selected);
|
|
25984
26807
|
}
|
|
25985
26808
|
|
|
26809
|
+
::slotted([data-drag-origin]) {
|
|
26810
|
+
opacity: 0.6;
|
|
26811
|
+
}
|
|
26812
|
+
|
|
25986
26813
|
/* checked mode: checkbox (injected into li) communicates selection — suppress bg highlight */
|
|
25987
26814
|
:host([interaction-mode="checked"]) ::slotted([data-selected]) {
|
|
25988
26815
|
background: transparent;
|
|
@@ -26029,6 +26856,12 @@ __decorate([property({
|
|
|
26029
26856
|
attribute: `search-modes`,
|
|
26030
26857
|
reflect: true
|
|
26031
26858
|
})], VerticalListElement.prototype, "searchModes", void 0);
|
|
26859
|
+
__decorate([property({
|
|
26860
|
+
type: Boolean,
|
|
26861
|
+
attribute: `items-draggable`,
|
|
26862
|
+
reflect: true
|
|
26863
|
+
})], VerticalListElement.prototype, "itemsDraggable", void 0);
|
|
26864
|
+
__decorate([property({ attribute: false })], VerticalListElement.prototype, "dragPreviewRenderer", void 0);
|
|
26032
26865
|
VerticalListElement = __decorate([safeCustomElement(`ixfx-vertical-list`)], VerticalListElement);
|
|
26033
26866
|
//#endregion
|
|
26034
26867
|
//#region src/grouped-item-lister/vertical-list-adapter.ts
|
|
@@ -42560,6 +43393,6 @@ function init() {
|
|
|
42560
43393
|
console.log(`Init`);
|
|
42561
43394
|
}
|
|
42562
43395
|
//#endregion
|
|
42563
|
-
export { AcTextElement, AcTokenElement, BottomDrawerElement, ButtonElement, Checkbox, ColourPicker, ColourPickerPopup, CrumbNavigationElement, CrumbPathController, CrumbPathElement, DataController, DataDisplayComponent, DataGridElement, DataTableElement, DetailListElement, DockHostElement, DockPanelElement, EditableLabel, EditableNumber, FormElement, FormGroupElement, FormPartElement, GridListElement, GroupedItemListerElement, ICON_CARET_RIGHT, ICON_CHECK, ICON_CHEVRON_DOWN, ICON_CLOSE, IncrSearchTreeController as IncrSearchMillerController, IncrSearchTreeController, IxfxHexEditorElement, IxfxIconElement, IxfxTimelineElement, KeyedElementIndex, LIST_ITEM_MOTION_MS, LIST_SEARCH_COMMAND_IDS, LIST_SEARCH_MODES, LabelledRadialInput, LabelledRangeInput, LabelledSliderInput, LedElement, ListDragSelectController, ListSearchController, ListSelectionController, menu_exports as Menu, MillerBaseElement, MillerListElement, MillerTreeController, NarrowedTextElement, NotificationManager, NotificationPillElement, PanTextElement, PanelElement, PanelGroupElement, PlotDataSeries, PlotHistogram, PlotMultiAxis, PlotSingleAxis, PlotXyAxis, PolarPad, RadialInputElement, RadioGroup, RangeElement, RangeInput, RangeMultiElement, RatingElement, SelectHorizElement, SliderInputElement, SlidingNumberElement, SnackbarElement, SnapContainer, SplitButton, SplitLayoutElement, SplitPanelElement, SwipeElement, TabController, TabListElement, TabListItemElement, TabPanelElement, TabPanelsElement, TextShimmerElement, TickledController, TimelineController, TimelineTrackTabElement, TitlebarElement, ToolbarElement, ToolbarGroupElement, TooltipElement, TransitoryLabelElement, TreeBaseElement, TreeController, TreeDataModel, TreeKeyboardNavController, TreeListElement, TwoSplitLayoutElement, VerticalListElement, XyPad, addPanelToStack, animateListItemIn, animateListItemOut, applyAgeModification, applyHighlights, applySnapshot, attachTimelineInteractions, bottomDrawerCommandId, buildHighlightTargets, buildModel, clearHighlights, collectContainerNames, collectDataResult, collectPanelIds, collectStackPaths, computeColour, computeLeafGeoms, createAcCompletionProvider, createDataListSearchAdapter, createElementIncrSearch, createElementListSearchAdapter, createEmptyLayout, createEmptyStack, createFuzzySearch, createIncrSearch, createPillRenderer, createSplit, createStack, createTreeListAdapter, createTreeListSearchAdapter, createVerticalListAdapter, distribute, extractStack, findNode, findParentOf, findStackOf, findStackPathByName, getActiveDragPanelId, getIcon, getIconEntry, getIconFont, getLeafNeighbours, hasIcon, iconBus, init, insertBeside, isDragging, isMultiMode, isSplit, isStack, keyForElement, listItemFadeKeyframes, listSearchStyles, monitorIndeterminate, moveLeafNodeToEdge, moveLeafStep, normalise, normalize, panelGapIndex, parseColourScaleAttr, parseLayout, pointerOverAnyHost, prefersReducedMotion, readBaseColour, registerFontIcon, registerIcon, registerListSearchCommands, removePanelFromStack, resolveCssVars, resolveGrid, resolveLeafPath, resolveTracks, serializeLayout, setActive, setIconFont, svgToDataUri, swapLeaves, tickledItemStyles, tickledStyles, timelineStyles, toSnapshot, walk, wrapRoot };
|
|
43396
|
+
export { AcTextElement, AcTokenElement, BottomDrawerElement, ButtonElement, Checkbox, ColourPicker, ColourPickerPopup, CrumbNavigationElement, CrumbPathController, CrumbPathElement, DataController, DataDisplayComponent, DataGridElement, DataTableElement, DetailListElement, DockHostElement, DockPanelElement, EditableLabel, EditableNumber, FormElement, FormGroupElement, FormPartElement, GridListElement, GroupedItemListerElement, ICON_CARET_RIGHT, ICON_CHECK, ICON_CHEVRON_DOWN, ICON_CLOSE, IncrSearchTreeController as IncrSearchMillerController, IncrSearchTreeController, IxfxHexEditorElement, IxfxIconElement, IxfxTimelineElement, KeyedElementIndex, LIST_ITEM_MOTION_MS, LIST_SEARCH_COMMAND_IDS, LIST_SEARCH_MODES, LabelledRadialInput, LabelledRangeInput, LabelledSliderInput, LedElement, ListDragSelectController, ListNativeDragController, ListSearchController, ListSelectionController, menu_exports as Menu, MillerBaseElement, MillerListElement, MillerTreeController, NarrowedTextElement, NotificationManager, NotificationPillElement, PanTextElement, PanelElement, PanelGroupElement, PlotDataSeries, PlotHistogram, PlotMultiAxis, PlotSingleAxis, PlotXyAxis, PolarPad, RadialInputElement, RadioGroup, RangeElement, RangeInput, RangeMultiElement, RatingElement, SelectHorizElement, SliderInputElement, SlidingNumberElement, SnackbarElement, SnapContainer, SplitButton, SplitLayoutElement, SplitPanelElement, SwipeElement, TabController, TabListElement, TabListItemElement, TabPanelElement, TabPanelsElement, TextShimmerElement, TickledController, TimelineController, TimelineTrackTabElement, TitlebarElement, ToolbarElement, ToolbarGroupElement, TooltipElement, TransitoryLabelElement, TreeBaseElement, TreeController, TreeDataModel, TreeKeyboardNavController, TreeListElement, TwoSplitLayoutElement, VerticalListElement, XyPad, addPanelToStack, animateListItemIn, animateListItemOut, applyAgeModification, applyHighlights, applySnapshot, attachTimelineInteractions, bottomDrawerCommandId, buildHighlightTargets, buildModel, captionForEntry, clearHighlights, collectContainerNames, collectDataResult, collectPanelIds, collectStackPaths, computeColour, computeLeafGeoms, createAcCompletionProvider, createDataListSearchAdapter, createDefaultListDragPreview, createElementIncrSearch, createElementListSearchAdapter, createEmptyLayout, createEmptyStack, createFuzzySearch, createIncrSearch, createPillRenderer, createSplit, createStack, createTreeListAdapter, createTreeListSearchAdapter, createVerticalListAdapter, distribute, extractStack, findNode, findParentOf, findStackOf, findStackPathByName, getActiveDragPanelId, getIcon, getIconEntry, getIconFont, getLeafNeighbours, hasIcon, iconBus, init, insertBeside, isDragging, isMultiMode, isSplit, isStack, keyForElement, listItemFadeKeyframes, listSearchStyles, monitorIndeterminate, moveLeafNodeToEdge, moveLeafStep, normalise, normalize, panelGapIndex, parseColourScaleAttr, parseLayout, pointerOverAnyHost, prefersReducedMotion, readBaseColour, registerFontIcon, registerIcon, registerListSearchCommands, removePanelFromStack, resolveCssVars, resolveGrid, resolveLeafPath, resolveTracks, serializeLayout, setActive, setIconFont, startListItemOutAnimation, svgToDataUri, swapLeaves, tickledItemStyles, tickledStyles, timelineStyles, toSnapshot, walk, wrapRoot };
|
|
42564
43397
|
|
|
42565
43398
|
//# sourceMappingURL=index.js.map
|