@ixfx/components 0.8.3 → 0.8.5
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 +78 -9
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +241 -47
- package/bundle/index.js.map +1 -1
- 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 +1 -1
- package/dist/{data-grid-D-z7bx5-.d.ts → data-grid-DCt0oack.d.ts} +2 -2
- package/dist/{data-grid-D-z7bx5-.d.ts.map → data-grid-DCt0oack.d.ts.map} +1 -1
- package/dist/data-grid.d.ts +1 -1
- package/dist/{detail-list-_ZJHYEBr.d.ts → detail-list-CqRzhFnv.d.ts} +2 -2
- package/dist/{detail-list-_ZJHYEBr.d.ts.map → detail-list-CqRzhFnv.d.ts.map} +1 -1
- package/dist/detail-list.d.ts +1 -1
- package/dist/{grid-list-BXfY3XXX.js → grid-list-j5C7qtlG.js} +148 -29
- package/dist/grid-list-j5C7qtlG.js.map +1 -0
- package/dist/grid-list-x550wJ0X.d.ts.map +1 -1
- 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/{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-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 +92 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +95 -20
- 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/{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/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/{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/docs-user/dock.md +27 -5
- package/docs-user/grid-list.md +5 -3
- package/docs-user/index.json +2 -2
- package/package.json +1 -1
- package/dist/grid-list-BXfY3XXX.js.map +0 -1
- package/dist/icon-CDGprSdE.d.ts.map +0 -1
package/bundle/index.js
CHANGED
|
@@ -19008,6 +19008,16 @@ let DockHostElement = class DockHostElement extends i {
|
|
|
19008
19008
|
if (rules.deny.has(kind)) return false;
|
|
19009
19009
|
return rules.allow === null || rules.allow.has(kind);
|
|
19010
19010
|
}
|
|
19011
|
+
/**
|
|
19012
|
+
* Whether an edge drop may split a new sibling leaf beside `stack`. Unnamed
|
|
19013
|
+
* leaves and leaves with no policy always allow it; a named leaf whose
|
|
19014
|
+
* policy sets `allowEdgeSplit: false` does not (strict named-area
|
|
19015
|
+
* containment).
|
|
19016
|
+
*/
|
|
19017
|
+
_leafAllowsEdgeSplit(stack) {
|
|
19018
|
+
if (stack.name === void 0) return true;
|
|
19019
|
+
return this._leafContentRules.get(stack.name)?.allowEdgeSplit ?? true;
|
|
19020
|
+
}
|
|
19011
19021
|
/** First stack (tree order) whose rules admit `kind`, else the first stack. */
|
|
19012
19022
|
_firstStackAllowing(kind) {
|
|
19013
19023
|
for (const path of collectStackPaths(this._model)) {
|
|
@@ -19072,6 +19082,9 @@ let DockHostElement = class DockHostElement extends i {
|
|
|
19072
19082
|
else if (op === `tabs` && !this._stackAllowsKindAt(namedPath, kind)) {
|
|
19073
19083
|
console.warn(`[ixfx-dock-host] addPanel: container "${target.container}" does not admit kind "${kind}"`);
|
|
19074
19084
|
return false;
|
|
19085
|
+
} else if (op !== `tabs` && !this._stackAllowsEdgeSplitAt(namedPath)) {
|
|
19086
|
+
console.warn(`[ixfx-dock-host] addPanel: container "${target.container}" forbids edge splits (allowEdgeSplit: false)`);
|
|
19087
|
+
return false;
|
|
19075
19088
|
} else stackPath = namedPath;
|
|
19076
19089
|
} else if (target?.stack) {
|
|
19077
19090
|
const found = findStackOf(this._model, target.stack);
|
|
@@ -19079,6 +19092,9 @@ let DockHostElement = class DockHostElement extends i {
|
|
|
19079
19092
|
else if (op === `tabs` && !this._stackAllowsKindAt(found, kind)) {
|
|
19080
19093
|
console.warn(`[ixfx-dock-host] addPanel: target stack does not admit kind "${kind}"`);
|
|
19081
19094
|
return false;
|
|
19095
|
+
} else if (op !== `tabs` && !this._stackAllowsEdgeSplitAt(found)) {
|
|
19096
|
+
console.warn(`[ixfx-dock-host] addPanel: target stack forbids edge splits (allowEdgeSplit: false)`);
|
|
19097
|
+
return false;
|
|
19082
19098
|
} else stackPath = found;
|
|
19083
19099
|
}
|
|
19084
19100
|
if (stackPath !== null && op !== `tabs`) {
|
|
@@ -19120,6 +19136,11 @@ let DockHostElement = class DockHostElement extends i {
|
|
|
19120
19136
|
const stack = findNode(this._model, stackPath);
|
|
19121
19137
|
return stack !== null && isStack(stack) && this._stackAllowsKind(stack, kind);
|
|
19122
19138
|
}
|
|
19139
|
+
/** Whether the stack at `stackPath` permits an edge split beside it. */
|
|
19140
|
+
_stackAllowsEdgeSplitAt(stackPath) {
|
|
19141
|
+
const stack = findNode(this._model, stackPath);
|
|
19142
|
+
return stack === null || !isStack(stack) || this._leafAllowsEdgeSplit(stack);
|
|
19143
|
+
}
|
|
19123
19144
|
removePanel(panelId) {
|
|
19124
19145
|
if (!collectPanelIds(this._model).includes(panelId)) return false;
|
|
19125
19146
|
this._returnAllToolbars();
|
|
@@ -19181,11 +19202,26 @@ let DockHostElement = class DockHostElement extends i {
|
|
|
19181
19202
|
getContainerElements(name) {
|
|
19182
19203
|
return this.getContainerPanels(name).map((id) => this._findPanelEl(id)).filter((el) => el !== void 0);
|
|
19183
19204
|
}
|
|
19205
|
+
_defaultLeafRule() {
|
|
19206
|
+
return {
|
|
19207
|
+
allow: null,
|
|
19208
|
+
deny: /* @__PURE__ */ new Set(),
|
|
19209
|
+
allowEdgeSplit: true
|
|
19210
|
+
};
|
|
19211
|
+
}
|
|
19212
|
+
/** A rule entry that constrains nothing — safe to drop from the map. */
|
|
19213
|
+
_isEmptyLeafRule(entry) {
|
|
19214
|
+
return entry.allow === null && entry.deny.size === 0 && entry.allowEdgeSplit;
|
|
19215
|
+
}
|
|
19216
|
+
_warnUnknownContainer(method, key) {
|
|
19217
|
+
if (findStackPathByName(this._model, key) === null) console.warn(`[ixfx-dock-host] ${method}: no container named "${key}" yet; rule stored`);
|
|
19218
|
+
}
|
|
19184
19219
|
/**
|
|
19185
19220
|
* Restrict a named container to only the given panel kinds — e.g.
|
|
19186
19221
|
* `setLeafExclusiveContents('editor', ['document'])`. `tabs` drops,
|
|
19187
|
-
* `addPanel`, and re-homing into the leaf then refuse other kinds
|
|
19188
|
-
* edge splits beside the leaf
|
|
19222
|
+
* `addPanel`, and re-homing into the leaf then refuse other kinds. Whether
|
|
19223
|
+
* edge splits beside the leaf are offered is governed separately by
|
|
19224
|
+
* {@link setLeafPlacementPolicy}'s `allowEdgeSplit` (default `true`).
|
|
19189
19225
|
* Pass `[]` to seal the leaf (nothing admitted). Warns when no stack
|
|
19190
19226
|
* currently carries `name`, but the rule is still stored and applies once
|
|
19191
19227
|
* one appears. Rules are host policy: kept across `loadLayout()`, never
|
|
@@ -19197,14 +19233,10 @@ let DockHostElement = class DockHostElement extends i {
|
|
|
19197
19233
|
console.warn(`[ixfx-dock-host] setLeafExclusiveContents: empty container name`);
|
|
19198
19234
|
return;
|
|
19199
19235
|
}
|
|
19200
|
-
const
|
|
19201
|
-
|
|
19202
|
-
allow: null,
|
|
19203
|
-
deny: /* @__PURE__ */ new Set()
|
|
19204
|
-
};
|
|
19205
|
-
entry.allow = allow;
|
|
19236
|
+
const entry = this._leafContentRules.get(key) ?? this._defaultLeafRule();
|
|
19237
|
+
entry.allow = new Set(kinds.map((k) => k.trim()).filter((k) => k.length > 0));
|
|
19206
19238
|
this._leafContentRules.set(key, entry);
|
|
19207
|
-
|
|
19239
|
+
this._warnUnknownContainer(`setLeafExclusiveContents`, key);
|
|
19208
19240
|
}
|
|
19209
19241
|
/**
|
|
19210
19242
|
* Forbid the given panel kinds in a named container — e.g.
|
|
@@ -19218,21 +19250,53 @@ let DockHostElement = class DockHostElement extends i {
|
|
|
19218
19250
|
console.warn(`[ixfx-dock-host] setLeafDenyContents: empty container name`);
|
|
19219
19251
|
return;
|
|
19220
19252
|
}
|
|
19221
|
-
const
|
|
19222
|
-
|
|
19223
|
-
|
|
19224
|
-
|
|
19225
|
-
|
|
19226
|
-
|
|
19227
|
-
|
|
19253
|
+
const entry = this._leafContentRules.get(key) ?? this._defaultLeafRule();
|
|
19254
|
+
entry.deny = new Set(kinds.map((k) => k.trim()).filter((k) => k.length > 0));
|
|
19255
|
+
if (this._isEmptyLeafRule(entry)) this._leafContentRules.delete(key);
|
|
19256
|
+
else this._leafContentRules.set(key, entry);
|
|
19257
|
+
this._warnUnknownContainer(`setLeafDenyContents`, key);
|
|
19258
|
+
}
|
|
19259
|
+
/**
|
|
19260
|
+
* Set (merge) the full placement policy for a named leaf: kind allow/deny
|
|
19261
|
+
* lists plus the `allowEdgeSplit` gate. Omitted fields are left unchanged
|
|
19262
|
+
* — pass `clearLeafPlacementPolicy(name)` to reset. `allowKinds` /
|
|
19263
|
+
* `denyKinds` are equivalent to {@link setLeafExclusiveContents} /
|
|
19264
|
+
* {@link setLeafDenyContents} and share the same storage.
|
|
19265
|
+
*
|
|
19266
|
+
* `allowEdgeSplit: false` enforces strict named-area containment: the edge
|
|
19267
|
+
* drop zones beside the leaf go inert for every placement route (pointer
|
|
19268
|
+
* preview and drop, `queryDropTarget` / `previewExternalDrop`,
|
|
19269
|
+
* `addPanel` with a split `op`), so a panel cannot escape the area by
|
|
19270
|
+
* splitting next to it. A permitted split still creates an *unnamed,
|
|
19271
|
+
* unconstrained* leaf — the policy is not propagated to it.
|
|
19272
|
+
*
|
|
19273
|
+
* Warns when no stack currently carries `name`; the policy is stored and
|
|
19274
|
+
* applies once one appears. Host policy: kept across `loadLayout()`, never
|
|
19275
|
+
* serialized.
|
|
19276
|
+
*/
|
|
19277
|
+
setLeafPlacementPolicy(name, policy) {
|
|
19278
|
+
const key = name.trim();
|
|
19279
|
+
if (!key) {
|
|
19280
|
+
console.warn(`[ixfx-dock-host] setLeafPlacementPolicy: empty container name`);
|
|
19281
|
+
return;
|
|
19282
|
+
}
|
|
19283
|
+
const entry = this._leafContentRules.get(key) ?? this._defaultLeafRule();
|
|
19284
|
+
if (policy.allowKinds !== void 0) entry.allow = new Set(policy.allowKinds.map((k) => k.trim()).filter((k) => k.length > 0));
|
|
19285
|
+
if (policy.denyKinds !== void 0) entry.deny = new Set(policy.denyKinds.map((k) => k.trim()).filter((k) => k.length > 0));
|
|
19286
|
+
if (policy.allowEdgeSplit !== void 0) entry.allowEdgeSplit = policy.allowEdgeSplit;
|
|
19287
|
+
if (this._isEmptyLeafRule(entry)) this._leafContentRules.delete(key);
|
|
19228
19288
|
else this._leafContentRules.set(key, entry);
|
|
19229
|
-
|
|
19289
|
+
this._warnUnknownContainer(`setLeafPlacementPolicy`, key);
|
|
19230
19290
|
}
|
|
19231
|
-
/** Remove every content rule for a named container. */
|
|
19291
|
+
/** Remove every content rule and reset the edge-split gate for a named container. */
|
|
19232
19292
|
clearLeafContentRestrictions(name) {
|
|
19233
19293
|
this._leafContentRules.delete(name.trim());
|
|
19234
19294
|
}
|
|
19235
|
-
/**
|
|
19295
|
+
/** Alias of {@link clearLeafContentRestrictions} — clears kind rules and the edge-split gate. */
|
|
19296
|
+
clearLeafPlacementPolicy(name) {
|
|
19297
|
+
this._leafContentRules.delete(name.trim());
|
|
19298
|
+
}
|
|
19299
|
+
/** Copy of a container's kind rules, or null when unrestricted. */
|
|
19236
19300
|
getLeafContentRestrictions(name) {
|
|
19237
19301
|
const rules = this._leafContentRules.get(name.trim());
|
|
19238
19302
|
if (rules === void 0) return null;
|
|
@@ -19241,6 +19305,16 @@ let DockHostElement = class DockHostElement extends i {
|
|
|
19241
19305
|
deny: [...rules.deny]
|
|
19242
19306
|
};
|
|
19243
19307
|
}
|
|
19308
|
+
/** Resolved placement policy for a container, or null when it has none. */
|
|
19309
|
+
getLeafPlacementPolicy(name) {
|
|
19310
|
+
const rules = this._leafContentRules.get(name.trim());
|
|
19311
|
+
if (rules === void 0) return null;
|
|
19312
|
+
return {
|
|
19313
|
+
allowKinds: rules.allow === null ? null : [...rules.allow],
|
|
19314
|
+
denyKinds: [...rules.deny],
|
|
19315
|
+
allowEdgeSplit: rules.allowEdgeSplit
|
|
19316
|
+
};
|
|
19317
|
+
}
|
|
19244
19318
|
/**
|
|
19245
19319
|
* Geometric neighbours of a leaf (`name` or numeric `path`) — what sits
|
|
19246
19320
|
* above / below / left / right of it on screen. Each entry is
|
|
@@ -19535,6 +19609,7 @@ let DockHostElement = class DockHostElement extends i {
|
|
|
19535
19609
|
if (zone.operation === `tabs` && stack !== null && isStack(stack)) {
|
|
19536
19610
|
if (!this._stackAllowsKind(stack, kind?.trim() ? kind.trim() : this._panelKind(panelId))) return false;
|
|
19537
19611
|
}
|
|
19612
|
+
if (zone.operation !== `tabs` && stack !== null && isStack(stack) && !this._leafAllowsEdgeSplit(stack)) return false;
|
|
19538
19613
|
if (this.canAccept && !this.canAccept(panelId, zone.operation)) return false;
|
|
19539
19614
|
return true;
|
|
19540
19615
|
}
|
|
@@ -21914,14 +21989,8 @@ let GridListElement = class GridListElement extends i {
|
|
|
21914
21989
|
}
|
|
21915
21990
|
},
|
|
21916
21991
|
shouldStart: (event) => {
|
|
21917
|
-
if (
|
|
21918
|
-
|
|
21919
|
-
if (!cell) return true;
|
|
21920
|
-
const key = cell.dataset.key;
|
|
21921
|
-
if (!key) return true;
|
|
21922
|
-
const index = this.#source.indexOfKey(key);
|
|
21923
|
-
if (index < 0) return true;
|
|
21924
|
-
return !this.#source.isSelectable(index);
|
|
21992
|
+
for (const node of event.composedPath()) if (node instanceof Element && node.classList.contains(`cell`)) return false;
|
|
21993
|
+
return true;
|
|
21925
21994
|
}
|
|
21926
21995
|
});
|
|
21927
21996
|
this.#selectedSnapshot = /* @__PURE__ */ new Set();
|
|
@@ -21936,26 +22005,17 @@ let GridListElement = class GridListElement extends i {
|
|
|
21936
22005
|
});
|
|
21937
22006
|
};
|
|
21938
22007
|
this.#onDragStart = (e, key) => {
|
|
22008
|
+
this.#doDragStart(key, () => e.preventDefault(), e);
|
|
22009
|
+
};
|
|
22010
|
+
this.#onSlottedDragStart = (e) => {
|
|
21939
22011
|
if (!this.itemsDraggable) return;
|
|
21940
|
-
|
|
21941
|
-
if (
|
|
21942
|
-
if (!
|
|
21943
|
-
const
|
|
21944
|
-
|
|
21945
|
-
|
|
21946
|
-
|
|
21947
|
-
item: this.#source.resolveKeyToData(key) ?? this.#source.resolveKeyToElement(key),
|
|
21948
|
-
selectedKeys
|
|
21949
|
-
};
|
|
21950
|
-
if (!this._dispatch(`grid-list-native-drag-start`, detail, true)) {
|
|
21951
|
-
e.preventDefault();
|
|
21952
|
-
return;
|
|
21953
|
-
}
|
|
21954
|
-
this.#nativeDragging = true;
|
|
21955
|
-
this.#dragOriginKey = key;
|
|
21956
|
-
this.toggleAttribute(`data-native-dragging`, true);
|
|
21957
|
-
const count = selectedKeys.length;
|
|
21958
|
-
this.setAttribute(`aria-label`, count === 1 ? `Dragging 1 item` : `Dragging ${count} items`);
|
|
22012
|
+
let cell = e.composedPath().find((n) => n instanceof Element && n.classList.contains(`cell`));
|
|
22013
|
+
if (!cell && e.target instanceof Element) cell = e.target.closest?.(`.cell`);
|
|
22014
|
+
if (!cell) return;
|
|
22015
|
+
const key = cell.dataset.key;
|
|
22016
|
+
if (!key) return;
|
|
22017
|
+
if (e instanceof DragEvent) this.#doDragStart(key, () => e.preventDefault(), e);
|
|
22018
|
+
else this.#doDragStart(key, () => {});
|
|
21959
22019
|
};
|
|
21960
22020
|
this.#onDragEnd = () => {
|
|
21961
22021
|
this.#clearNativeDragState();
|
|
@@ -22132,7 +22192,6 @@ let GridListElement = class GridListElement extends i {
|
|
|
22132
22192
|
align-items: center;
|
|
22133
22193
|
justify-content: center;
|
|
22134
22194
|
overflow: hidden;
|
|
22135
|
-
draggable: false;
|
|
22136
22195
|
}
|
|
22137
22196
|
.thumb ::slotted(*:empty)::after {
|
|
22138
22197
|
content: "Empty";
|
|
@@ -22611,6 +22670,7 @@ let GridListElement = class GridListElement extends i {
|
|
|
22611
22670
|
this.#measureViewport(false);
|
|
22612
22671
|
this.#syncItems();
|
|
22613
22672
|
this.requestUpdate();
|
|
22673
|
+
this.#initSlottedDragInterceptor();
|
|
22614
22674
|
}
|
|
22615
22675
|
/** (Re)construct {@link #source} for the current mode and re-apply the filters. */
|
|
22616
22676
|
#rebuildSource() {
|
|
@@ -22700,6 +22760,7 @@ let GridListElement = class GridListElement extends i {
|
|
|
22700
22760
|
this.selection.clearAnchor();
|
|
22701
22761
|
this.#syncAriaMultiselectable();
|
|
22702
22762
|
}
|
|
22763
|
+
if (changed.has(`itemsDraggable`)) this.#syncSlottedDraggable();
|
|
22703
22764
|
if (changed.has(`orientation`)) {
|
|
22704
22765
|
const vp = this.#viewportRef.value;
|
|
22705
22766
|
if (vp) {
|
|
@@ -23226,7 +23287,140 @@ let GridListElement = class GridListElement extends i {
|
|
|
23226
23287
|
this.selection.handleClick(key, e);
|
|
23227
23288
|
this.#emitItemEvent(`list-item-click`, key);
|
|
23228
23289
|
}
|
|
23290
|
+
#doDragStart(key, cancelled, dragEvent) {
|
|
23291
|
+
if (!this.itemsDraggable) return false;
|
|
23292
|
+
const index = this.#source.indexOfKey(key);
|
|
23293
|
+
if (index < 0 || !this.#source.isSelectable(index)) return false;
|
|
23294
|
+
if (!this.selection.selectedKeys.has(key)) this.selection.replace(key);
|
|
23295
|
+
const selectedKeys = this.#source.keys().filter((k) => !isSyntheticKey(k)).filter((k) => this.selection.selectedKeys.has(k));
|
|
23296
|
+
const detail = {
|
|
23297
|
+
key,
|
|
23298
|
+
index: this.#source.indexOfKey(key),
|
|
23299
|
+
item: this.#source.resolveKeyToData(key) ?? this.#source.resolveKeyToElement(key),
|
|
23300
|
+
selectedKeys
|
|
23301
|
+
};
|
|
23302
|
+
if (!this._dispatch(`grid-list-native-drag-start`, detail, true)) {
|
|
23303
|
+
cancelled();
|
|
23304
|
+
return false;
|
|
23305
|
+
}
|
|
23306
|
+
this.#nativeDragging = true;
|
|
23307
|
+
this.#dragOriginKey = key;
|
|
23308
|
+
this.toggleAttribute(`data-native-dragging`, true);
|
|
23309
|
+
const count = selectedKeys.length;
|
|
23310
|
+
this.setAttribute(`aria-label`, count === 1 ? `Dragging 1 item` : `Dragging ${count} items`);
|
|
23311
|
+
if (dragEvent && count > 1) this.#setMultiItemDragImage(dragEvent, selectedKeys);
|
|
23312
|
+
return true;
|
|
23313
|
+
}
|
|
23314
|
+
#setMultiItemDragImage(e, selectedKeys) {
|
|
23315
|
+
const preview = this.#createMultiItemPreview(selectedKeys);
|
|
23316
|
+
document.body.appendChild(preview);
|
|
23317
|
+
const rect = preview.getBoundingClientRect();
|
|
23318
|
+
e.dataTransfer?.setDragImage(preview, rect.width / 2, rect.height / 2);
|
|
23319
|
+
requestAnimationFrame(() => preview.remove());
|
|
23320
|
+
}
|
|
23321
|
+
#createMultiItemPreview(selectedKeys) {
|
|
23322
|
+
const preview = document.createElement(`div`);
|
|
23323
|
+
preview.style.cssText = `
|
|
23324
|
+
position: fixed;
|
|
23325
|
+
top: -9999px;
|
|
23326
|
+
left: -9999px;
|
|
23327
|
+
display: flex;
|
|
23328
|
+
flex-direction: column;
|
|
23329
|
+
gap: 4px;
|
|
23330
|
+
padding: 8px;
|
|
23331
|
+
background: var(--surface-4, #333);
|
|
23332
|
+
border: 1px solid var(--border, #555);
|
|
23333
|
+
border-radius: 8px;
|
|
23334
|
+
box-shadow: 0 4px 16px rgba(0,0,0,0.3);
|
|
23335
|
+
font-family: system-ui, sans-serif;
|
|
23336
|
+
font-size: 12px;
|
|
23337
|
+
color: var(--surface-text, #fff);
|
|
23338
|
+
max-width: 200px;
|
|
23339
|
+
z-index: 999999;
|
|
23340
|
+
`;
|
|
23341
|
+
const header = document.createElement(`div`);
|
|
23342
|
+
header.style.cssText = `
|
|
23343
|
+
font-weight: 600;
|
|
23344
|
+
padding-bottom: 4px;
|
|
23345
|
+
border-bottom: 1px solid var(--border, #555);
|
|
23346
|
+
margin-bottom: 4px;
|
|
23347
|
+
`;
|
|
23348
|
+
header.textContent = `${selectedKeys.length} items`;
|
|
23349
|
+
preview.appendChild(header);
|
|
23350
|
+
for (const key of selectedKeys.slice(0, 5)) {
|
|
23351
|
+
const row = this.#createPreviewRow(key);
|
|
23352
|
+
if (row) preview.appendChild(row);
|
|
23353
|
+
}
|
|
23354
|
+
if (selectedKeys.length > 5) {
|
|
23355
|
+
const more = document.createElement(`div`);
|
|
23356
|
+
more.style.cssText = `opacity: 0.6; text-align: center;`;
|
|
23357
|
+
more.textContent = `+${selectedKeys.length - 5} more`;
|
|
23358
|
+
preview.appendChild(more);
|
|
23359
|
+
}
|
|
23360
|
+
return preview;
|
|
23361
|
+
}
|
|
23362
|
+
#createPreviewRow(key) {
|
|
23363
|
+
const el = this.#source.resolveKeyToElement(key);
|
|
23364
|
+
if (!el) return null;
|
|
23365
|
+
const row = document.createElement(`div`);
|
|
23366
|
+
row.style.cssText = `
|
|
23367
|
+
display: flex;
|
|
23368
|
+
align-items: center;
|
|
23369
|
+
gap: 6px;
|
|
23370
|
+
`;
|
|
23371
|
+
const thumb = document.createElement(`div`);
|
|
23372
|
+
thumb.style.cssText = `
|
|
23373
|
+
width: 32px;
|
|
23374
|
+
height: 32px;
|
|
23375
|
+
border-radius: 4px;
|
|
23376
|
+
overflow: hidden;
|
|
23377
|
+
background: var(--surface-5, #444);
|
|
23378
|
+
flex-shrink: 0;
|
|
23379
|
+
display: flex;
|
|
23380
|
+
align-items: center;
|
|
23381
|
+
justify-content: center;
|
|
23382
|
+
`;
|
|
23383
|
+
const slottedImg = el.querySelector(`img`);
|
|
23384
|
+
const slottedSvg = el.querySelector(`svg`);
|
|
23385
|
+
const slottedPlaceholder = el.querySelector(`.placeholder`);
|
|
23386
|
+
if (slottedImg) {
|
|
23387
|
+
const img = slottedImg.cloneNode(true);
|
|
23388
|
+
img.style.cssText = `width: 100%; height: 100%; object-fit: cover;`;
|
|
23389
|
+
thumb.appendChild(img);
|
|
23390
|
+
} else if (slottedSvg) {
|
|
23391
|
+
const svg = slottedSvg.cloneNode(true);
|
|
23392
|
+
svg.style.cssText = `width: 70%; height: 70%; opacity: 0.8;`;
|
|
23393
|
+
thumb.appendChild(svg);
|
|
23394
|
+
} else if (slottedPlaceholder) thumb.textContent = slottedPlaceholder.textContent || `?`;
|
|
23395
|
+
const label = document.createElement(`span`);
|
|
23396
|
+
label.style.cssText = `
|
|
23397
|
+
flex: 1;
|
|
23398
|
+
overflow: hidden;
|
|
23399
|
+
text-overflow: ellipsis;
|
|
23400
|
+
white-space: nowrap;
|
|
23401
|
+
`;
|
|
23402
|
+
label.textContent = el.getAttribute(`data-label`) || key;
|
|
23403
|
+
row.appendChild(thumb);
|
|
23404
|
+
row.appendChild(label);
|
|
23405
|
+
return row;
|
|
23406
|
+
}
|
|
23229
23407
|
#onDragStart;
|
|
23408
|
+
#onSlottedDragStart;
|
|
23409
|
+
#initSlottedDragInterceptor() {
|
|
23410
|
+
this.renderRoot.addEventListener(`dragstart`, this.#onSlottedDragStart, { capture: true });
|
|
23411
|
+
const observer = new MutationObserver(() => this.#syncSlottedDraggable());
|
|
23412
|
+
observer.observe(this, {
|
|
23413
|
+
childList: true,
|
|
23414
|
+
subtree: true
|
|
23415
|
+
});
|
|
23416
|
+
this.#slottedDragObserver = observer;
|
|
23417
|
+
this.#syncSlottedDraggable();
|
|
23418
|
+
}
|
|
23419
|
+
#slottedDragObserver;
|
|
23420
|
+
#syncSlottedDraggable() {
|
|
23421
|
+
const draggable = this.itemsDraggable;
|
|
23422
|
+
for (const child of this.children) if (child instanceof HTMLElement) child.draggable = draggable;
|
|
23423
|
+
}
|
|
23230
23424
|
#onDragEnd;
|
|
23231
23425
|
#startPostDragSuppressTimer() {
|
|
23232
23426
|
if (this.#postDragSuppressTimer) clearTimeout(this.#postDragSuppressTimer);
|