@ixfx/components 0.13.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/bundle/index.d.ts +214 -73
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +347 -13
  4. package/bundle/index.js.map +1 -1
  5. package/dist/{button-BYuf72aR.d.ts → button-CTL45aBl.d.ts} +2 -2
  6. package/dist/{button-BYuf72aR.d.ts.map → button-CTL45aBl.d.ts.map} +1 -1
  7. package/dist/button.d.ts +1 -1
  8. package/dist/crumbs.d.ts +2 -2
  9. package/dist/{data-grid-BJ6XXvRc.d.ts → data-grid-Ck1Qx2H1.d.ts} +4 -4
  10. package/dist/{data-grid-BJ6XXvRc.d.ts.map → data-grid-Ck1Qx2H1.d.ts.map} +1 -1
  11. package/dist/data-grid.d.ts +2 -2
  12. package/dist/{detail-list-B0waVNeS.d.ts → detail-list-C1xzr1z7.d.ts} +4 -4
  13. package/dist/{detail-list-B0waVNeS.d.ts.map → detail-list-C1xzr1z7.d.ts.map} +1 -1
  14. package/dist/detail-list.d.ts +3 -3
  15. package/dist/editable-label-rzXkjf1H.d.ts.map +1 -1
  16. package/dist/editable-label.js +2 -2
  17. package/dist/editable-label.js.map +1 -1
  18. package/dist/{flat-list-eYItri8-.d.ts → flat-list-DEDG6epz.d.ts} +60 -5
  19. package/dist/flat-list-DEDG6epz.d.ts.map +1 -0
  20. package/dist/flat-list.d.ts +2 -2
  21. package/dist/flat-list.js +144 -9
  22. package/dist/flat-list.js.map +1 -1
  23. package/dist/{grid-list-_gI9ckcT.d.ts → grid-list-pefLORIr.d.ts} +4 -4
  24. package/dist/{grid-list-_gI9ckcT.d.ts.map → grid-list-pefLORIr.d.ts.map} +1 -1
  25. package/dist/grid-list.d.ts +2 -2
  26. package/dist/incr-search.d.ts +1 -1
  27. package/dist/{index-BvxHQUME.d.ts → index-CxZ61DO1.d.ts} +3 -3
  28. package/dist/{index-BvxHQUME.d.ts.map → index-CxZ61DO1.d.ts.map} +1 -1
  29. package/dist/{index-CW2QL33o.d.ts → index-Dq30pOnn.d.ts} +2 -2
  30. package/dist/{index-CW2QL33o.d.ts.map → index-Dq30pOnn.d.ts.map} +1 -1
  31. package/dist/index.d.ts +13 -13
  32. package/dist/{list-native-drag-controller-CllsHLxw.d.ts → list-native-drag-controller-ChIi3eK5.d.ts} +2 -2
  33. package/dist/{list-native-drag-controller-CllsHLxw.d.ts.map → list-native-drag-controller-ChIi3eK5.d.ts.map} +1 -1
  34. package/dist/menu.d.ts +1 -1
  35. package/dist/miller.d.ts +3 -3
  36. package/dist/{tree-component-DukLqesg.d.ts → tree-component-Cj8V3uar.d.ts} +2 -2
  37. package/dist/{tree-component-DukLqesg.d.ts.map → tree-component-Cj8V3uar.d.ts.map} +1 -1
  38. package/dist/tree.d.ts +4 -4
  39. package/dist/{types-D-kYF16b.d.ts → types-DQ7KOUIj.d.ts} +6 -1
  40. package/dist/types-DQ7KOUIj.d.ts.map +1 -0
  41. package/dist/{vertical-list-DheZSEmB.d.ts → vertical-list-CqBc-t8w.d.ts} +86 -4
  42. package/dist/vertical-list-CqBc-t8w.d.ts.map +1 -0
  43. package/dist/vertical-list.d.ts +3 -3
  44. package/dist/vertical-list.js +202 -2
  45. package/dist/vertical-list.js.map +1 -1
  46. package/docs-user/flat-list.md +32 -2
  47. package/docs-user/index.json +2 -2
  48. package/docs-user/vertical-list.md +59 -3
  49. package/package.json +1 -1
  50. package/dist/flat-list-eYItri8-.d.ts.map +0 -1
  51. package/dist/types-D-kYF16b.d.ts.map +0 -1
  52. package/dist/vertical-list-DheZSEmB.d.ts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-DQ7KOUIj.d.ts","names":[],"sources":["../src/common/types.ts"],"mappings":";;KAQY;;EAEV;;EAEA;;EAEA;;EAEA;;EAEA;;;;;;EAMA;;;;;;EAMA;;;;;;;;EAQA;;;;;EAKA;;EAEA;;EAEA;;;;;;;EAOA;;;KAIU;EACV,MAAM;;;;;;;EAON,WAAW;;;;;;;KAQD,uBAAuB;EAAgB,MAAM;EAAU;GAAiB;;;;;;KAOxE,uBAAuB,MAAM,UAAU;;;;;;;KAQvC;;;;;;;;;KAUA;;;;;;;;;KAUA"}
@@ -1,9 +1,46 @@
1
- import { F as ListDragPreviewSourceResolver, P as ListDragPreviewRenderer, R as ListNativeDragStartEvent } from "./tree-component-DukLqesg.js";
1
+ import { F as ListDragPreviewSourceResolver, P as ListDragPreviewRenderer, R as ListNativeDragStartEvent } from "./tree-component-Cj8V3uar.js";
2
2
  import { n as ListViewportChangeEvent } from "./list-viewport-types-BRZsLcvp.js";
3
- import { S as ListSearchController } from "./index-BvxHQUME.js";
3
+ import { S as ListSearchController } from "./index-CxZ61DO1.js";
4
4
  import { i as ListInteractionMode, l as ListSelectionMode, r as ListElementEventMap } from "./list-selection-types-PjKdhF-a.js";
5
+ import "./editable-label-rzXkjf1H.js";
5
6
  import { LitElement, PropertyValues } from "lit";
6
7
  import { CommandId, CommandRegistry } from "@clinth/ui-commands";
8
+ //#region src/vertical-list/types.d.ts
9
+ /**
10
+ * `list-drag-over` / `list-drop`. `key` and `item` are `undefined` when the
11
+ * drag is over empty list space rather than a row.
12
+ */
13
+ type ListDropDetail = {
14
+ readonly key: string | undefined;
15
+ readonly item: Element | undefined;
16
+ readonly dataTransfer: DataTransfer;
17
+ };
18
+ type ListDragLeaveDetail = {
19
+ readonly key: string | undefined;
20
+ };
21
+ type ListContextMenuDetail = {
22
+ readonly key: string | undefined;
23
+ readonly item: Element;
24
+ /** Viewport coordinates to open the menu at. */
25
+ readonly x: number;
26
+ readonly y: number;
27
+ /** The selection at the time of the request — a row that was not selected has been selected first. */
28
+ readonly selectedKeys: ReadonlySet<string>;
29
+ };
30
+ type ListEditCommitDetail = {
31
+ readonly key: string | undefined;
32
+ readonly value: string;
33
+ };
34
+ type ListEditCancelDetail = {
35
+ readonly key: string | undefined;
36
+ };
37
+ type ListDragOverEvent = CustomEvent<ListDropDetail>;
38
+ type ListDropEvent = CustomEvent<ListDropDetail>;
39
+ type ListDragLeaveEvent = CustomEvent<ListDragLeaveDetail>;
40
+ type ListContextMenuEvent = CustomEvent<ListContextMenuDetail>;
41
+ type ListEditCommitEvent = CustomEvent<ListEditCommitDetail>;
42
+ type ListEditCancelEvent = CustomEvent<ListEditCancelDetail>;
43
+ //#endregion
7
44
  //#region src/vertical-list/vertical-list.d.ts
8
45
  interface CustomCheckboxOptions {
9
46
  renderer: (checked: boolean) => unknown;
@@ -138,6 +175,27 @@ declare class VerticalListElement extends LitElement {
138
175
  * `ixfx-grid-list`'s `itemSize`.
139
176
  */
140
177
  itemHeight: number;
178
+ /**
179
+ * Make rows (and the empty space around them) drop targets for native
180
+ * drags — including OS drags carrying files. The list fires `list-drag-over`
181
+ * (cancelable: `preventDefault()` accepts the drop), `list-drop` and
182
+ * `list-drag-leave`, and highlights the row under the drag with
183
+ * `data-drop-target` (`--list-drop-target-bg`, `--list-drop-target-outline`).
184
+ */
185
+ itemsDroppable: boolean;
186
+ /**
187
+ * Opt in to in-place rename (`beginEdit`). Called with the typed text and
188
+ * the row's key when the user commits; return `false` to reject it (the
189
+ * edit then ends as a cancel). Without it `beginEdit` does nothing and rows
190
+ * stay plain text.
191
+ */
192
+ editValidator: ((value: string, key: string | undefined) => boolean) | undefined;
193
+ /**
194
+ * Refuse a drop before any event fires or any highlight shows. `item` is the
195
+ * row under the drag, or `undefined` over empty space. Only used while
196
+ * `itemsDroppable` is set.
197
+ */
198
+ canDrop: ((item: Element | undefined, dataTransfer: DataTransfer) => boolean) | undefined;
141
199
  private readonly selection;
142
200
  private tickled;
143
201
  private _syncNativeDraggable;
@@ -261,6 +319,24 @@ declare class VerticalListElement extends LitElement {
261
319
  private _onClick;
262
320
  private _onDblClick;
263
321
  private _activateItem;
322
+ private _onDragOver;
323
+ private _onDragLeave;
324
+ private _onDrop;
325
+ private _onContextMenu;
326
+ /** The key of the row being edited, if any. */
327
+ get editingKey(): string | undefined;
328
+ /**
329
+ * Edit a row's label in place with an `ixfx-editable-label`. The editor
330
+ * replaces the row's `[data-edit-label]` element (else the whole row) and
331
+ * the original content returns when editing ends. Fires `list-edit-commit`
332
+ * `{ key, value }` when the text changed, otherwise `list-edit-cancel`
333
+ * `{ key }` (Escape, an unchanged value, or one the label rejects). The list
334
+ * never rewrites the label itself — update your data in response.
335
+ *
336
+ * Returns false when `editValidator` is not set, or the row is unknown or
337
+ * not currently rendered.
338
+ */
339
+ beginEdit(key: string): boolean;
264
340
  static styles: import("lit").CSSResult[];
265
341
  render(): import("lit").TemplateResult<1>;
266
342
  }
@@ -273,7 +349,13 @@ declare global {
273
349
  interface VerticalListElementEventMap extends ListElementEventMap {
274
350
  'vertical-list-viewport-change': ListViewportChangeEvent;
275
351
  'list-native-drag-start': ListNativeDragStartEvent<Element>;
352
+ 'list-drag-over': ListDragOverEvent;
353
+ 'list-drop': ListDropEvent;
354
+ 'list-drag-leave': ListDragLeaveEvent;
355
+ 'list-context-menu': ListContextMenuEvent;
356
+ 'list-edit-commit': ListEditCommitEvent;
357
+ 'list-edit-cancel': ListEditCancelEvent;
276
358
  }
277
359
  //#endregion
278
- export { VerticalListElementEventMap as i, CustomCheckboxOptions as n, VerticalListElement as r, AddItemOptions as t };
279
- //# sourceMappingURL=vertical-list-DheZSEmB.d.ts.map
360
+ export { ListContextMenuDetail as a, ListDragLeaveEvent as c, ListDropEvent as d, ListEditCancelDetail as f, ListEditCommitEvent as h, VerticalListElementEventMap as i, ListDragOverEvent as l, ListEditCommitDetail as m, CustomCheckboxOptions as n, ListContextMenuEvent as o, ListEditCancelEvent as p, VerticalListElement as r, ListDragLeaveDetail as s, AddItemOptions as t, ListDropDetail as u };
361
+ //# sourceMappingURL=vertical-list-CqBc-t8w.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vertical-list-CqBc-t8w.d.ts","names":[],"sources":["../src/vertical-list/types.ts","../src/vertical-list/vertical-list.ts"],"mappings":";;;;;;;;;;;;KAuBY;WACD;WACA,MAAM;WACN,cAAc;;KAGb;WACD;;KAGC;WACD;WACA,MAAM;;WAEN;WACA;;WAEA,cAAc;;KAGb;WACD;WACA;;KAGC;WACD;;KAGC,oBAAoB,YAAY;KAChC,gBAAgB,YAAY;KAC5B,qBAAqB,YAAY;KACjC,uBAAuB,YAAY;KACnC,sBAAsB,YAAY;KAClC,sBAAsB,YAAY;;;UC+B7B;EACf,WAAW;EACX;EACA;;UAGe;;;;;;EAMf;;cAkCW,4BAA4B;;EAEvC,eAAe;EAGf,iBAAiB;EAGjB,mBAAmB,IAAI;;;;;;EAQvB;;;;;;;;;;;;;;;;;;;EAqBA,oBAAoB,gCAAgC;;;;;;EAQpD;;;;;;EAQA;;;;;EAOA,qBAAqB,wBAAwB;EAG7C,mBAAmB,8BAA8B;;;;;;;;;;;EAajD;;;;;EAOA;;;;;;;;;EAWA,aAAa,eAAe;;;;;;;EAS5B,QAAQ,eAAe;;;;;EAOvB,aAAa,eAAe;;;;;EAO5B,aAAa,eAAe;;;;;;EAQ5B,SAAS,eAAe;;;;;;;;;;;;;;;;;;EAoBxB;;;;;;EAQA;;;;;;;;EAUA;;;;;;;EASA,iBAAiB,eAAe;;;;;;EAQhC,WAAW,MAAM,qBAAqB,cAAc;mBAyCnC;UAeT;UA6EA;;WA6EC,QAAM,qBAAA;;MAYX,YAAY;EA2BP;EA0BA;;;;;;YAkCU;EAwDV,QAAQ,SAAS;;MAgFtB,gBAAgB;;MAKhB,iBAAiB,YAAY;EAIjC,QAAQ,MAAM,kBAAkB,UAAU;;;;;;;EA4B1C,WAAW,MAAM,UAAU;;EA2B3B,YAAY,OAAO,SAAS,WAAW;EAIvC;;;;;;EAmBA,SAAS,gBAAgB;;;;;;EAwBzB,SAAS,WAAW,WAAW,OAAO;EAItC,OAAO,MAAM;EAIb,WAAW,OAAO,SAAS;EAI3B,SAAS,MAAM;EAIf;EAIA;;MAQI,gBAAgB;;MAKhB;;EAMJ,WAAW,MAAM;;EAKjB,gBAAgB,MAAM;;EAKtB,mBAAmB,MAAM;;;;;;EASzB,SAAS;;EAgCT,aAAa,cAAc;;;;;;;;EAW3B;;;;;;;EAuBA;EAsBE,eAAe,0CAA0C,UAAU;;;;;EA2CrE,YAAY,MAAM;;;;;;;;;;;EAclB,WAAW,aAAa;UAmiBhB;UAgBA;UAOA;UAiBA;;;;;;;UA4GA;;;;;UAuBA;UAcA;UAYA;UAQA;UAWA;UAMA;UAIA;UAmEA;UAYA;UAQA;UAaA;UA2BA;UAOA;UAwCA;;MAuCJ;;;;;;;;;;;;EAmBJ,UAAU;SAiEM,sBAAM;EAuLb,wBAAM;;QAeT;YACI;IACR,sBAAsB;;YAGd,4BAA4B;;UAGvB,oCAAoC;EACnD,iCAAiC;EACjC,0BAA0B,yBAAyB;EACnD,kBAAkB;EAClB,aAAa;EACb,mBAAmB;EACnB,qBAAqB;EACrB,oBAAoB;EACpB,oBAAoB"}
@@ -1,5 +1,5 @@
1
- import { I as ListDragSource, L as ListNativeDragStartDetail, M as ListDragPreview, N as ListDragPreviewContext, P as ListDragPreviewRenderer, R as ListNativeDragStartEvent, j as ListDragEntry } from "./tree-component-DukLqesg.js";
1
+ import { I as ListDragSource, L as ListNativeDragStartDetail, M as ListDragPreview, N as ListDragPreviewContext, P as ListDragPreviewRenderer, R as ListNativeDragStartEvent, j as ListDragEntry } from "./tree-component-Cj8V3uar.js";
2
2
  import { n as ListViewportChangeEvent, t as ListViewportChangeDetail } from "./list-viewport-types-BRZsLcvp.js";
3
3
  import { a as ListItemClickDetail, c as ListSelectEvent, d as ListTickleEvent, i as ListInteractionMode, l as ListSelectionMode, n as ListActivateEvent, o as ListItemClickEvent, r as ListElementEventMap, s as ListSelectDetail, t as ListActivateDetail, u as ListTickleDetail } from "./list-selection-types-PjKdhF-a.js";
4
- import { i as VerticalListElementEventMap, n as CustomCheckboxOptions, r as VerticalListElement, t as AddItemOptions } from "./vertical-list-DheZSEmB.js";
5
- export { AddItemOptions, CustomCheckboxOptions, type ListActivateDetail, type ListActivateEvent, type ListDragEntry, type ListDragPreview, type ListDragPreviewContext, type ListDragPreviewRenderer, type ListDragSource, type ListElementEventMap, type ListInteractionMode, type ListItemClickDetail, type ListItemClickEvent, type ListNativeDragStartDetail, type ListNativeDragStartEvent, type ListSelectDetail, type ListSelectEvent, type ListSelectionMode, type ListTickleDetail, type ListTickleEvent, type ListViewportChangeDetail, type ListViewportChangeEvent, VerticalListElement, VerticalListElementEventMap };
4
+ import { a as ListContextMenuDetail, c as ListDragLeaveEvent, d as ListDropEvent, f as ListEditCancelDetail, h as ListEditCommitEvent, i as VerticalListElementEventMap, l as ListDragOverEvent, m as ListEditCommitDetail, n as CustomCheckboxOptions, o as ListContextMenuEvent, p as ListEditCancelEvent, r as VerticalListElement, s as ListDragLeaveDetail, t as AddItemOptions, u as ListDropDetail } from "./vertical-list-CqBc-t8w.js";
5
+ export { AddItemOptions, CustomCheckboxOptions, type ListActivateDetail, type ListActivateEvent, type ListContextMenuDetail, type ListContextMenuEvent, type ListDragEntry, type ListDragLeaveDetail, type ListDragLeaveEvent, type ListDragOverEvent, type ListDragPreview, type ListDragPreviewContext, type ListDragPreviewRenderer, type ListDragSource, type ListDropDetail, type ListDropEvent, type ListEditCancelDetail, type ListEditCancelEvent, type ListEditCommitDetail, type ListEditCommitEvent, type ListElementEventMap, type ListInteractionMode, type ListItemClickDetail, type ListItemClickEvent, type ListNativeDragStartDetail, type ListNativeDragStartEvent, type ListSelectDetail, type ListSelectEvent, type ListSelectionMode, type ListTickleDetail, type ListTickleEvent, type ListViewportChangeDetail, type ListViewportChangeEvent, VerticalListElement, VerticalListElementEventMap };
@@ -7,6 +7,7 @@ import { r as ListDragSelectController, t as ListSelectionController } from "./l
7
7
  import { n as animateListItemIn, r as animateListItemOut } from "./list-item-animation-BUoEKi5s.js";
8
8
  import { t as scrollFadeStyles } from "./scroll-fade-BrNUIYnm.js";
9
9
  import { n as appearanceColor, t as appearanceAbsent } from "./item-appearance-BjcMyauw.js";
10
+ import "./editable-label.js";
10
11
  import { LitElement, css, html, render } from "lit";
11
12
  import { property } from "lit/decorators.js";
12
13
  import { createCommandRegistry } from "@clinth/ui-commands";
@@ -43,6 +44,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
43
44
  this.keyProperty = ``;
44
45
  this.virtualize = false;
45
46
  this.itemHeight = 0;
47
+ this.itemsDroppable = false;
46
48
  this.#customWrappers = /* @__PURE__ */ new Map();
47
49
  this.#wrappedElements = /* @__PURE__ */ new Set();
48
50
  this.#itemData = /* @__PURE__ */ new WeakMap();
@@ -162,7 +164,16 @@ let VerticalListElement = class VerticalListElement extends LitElement {
162
164
  this.tickled.handlePointerLeave(e);
163
165
  };
164
166
  this._onKeyDown = (e) => {
165
- if (this.search.isOpen) return;
167
+ if (this.search.isOpen || this.#isEditEvent(e)) return;
168
+ if (e.key === `ContextMenu` || e.shiftKey && e.key === `F10`) {
169
+ const id = this.tickled.tickledId;
170
+ if (id) {
171
+ e.preventDefault();
172
+ const rect = id.getBoundingClientRect();
173
+ this.#requestContextMenu(id, rect.left, rect.bottom);
174
+ }
175
+ return;
176
+ }
166
177
  if ((e.ctrlKey || e.metaKey) && e.key === `a`) {
167
178
  if (this.selection.canSelectAll()) {
168
179
  e.preventDefault();
@@ -216,6 +227,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
216
227
  }
217
228
  };
218
229
  this._onClick = (e) => {
230
+ if (this.#isEditEvent(e)) return;
219
231
  if (this.#dragSelect.isDragging || this.#nativeDrag.isDragging || this.#postDragSuppressTimer !== 0) return;
220
232
  const item = this._findListItem(e.composedPath());
221
233
  if (!item) return;
@@ -223,9 +235,60 @@ let VerticalListElement = class VerticalListElement extends LitElement {
223
235
  this.selection.handleClick(item, e);
224
236
  };
225
237
  this._onDblClick = (e) => {
238
+ if (this.#isEditEvent(e)) return;
226
239
  const item = this._findListItem(e.composedPath());
227
240
  if (item) this._activateItem(item);
228
241
  };
242
+ this._onDragOver = (e) => {
243
+ const dt = e.dataTransfer;
244
+ if (!this.itemsDroppable || !dt || this.#isEditEvent(e)) return;
245
+ const item = this._findListItem(e.composedPath());
246
+ if (this.canDrop && !this.canDrop(item, dt)) {
247
+ this.#clearDropTarget();
248
+ return;
249
+ }
250
+ if (this.#dragOver && this.#dragOver.item !== item) this.#clearDropTarget();
251
+ this.#dragOver = { item };
252
+ if (!!this._dispatchCancelable(`list-drag-over`, {
253
+ key: item ? keyForElement(item) : void 0,
254
+ item,
255
+ dataTransfer: dt
256
+ })) {
257
+ this.#highlightDropTarget(void 0, false);
258
+ return;
259
+ }
260
+ e.preventDefault();
261
+ if (dt.dropEffect === `none`) dt.dropEffect = `copy`;
262
+ this.#highlightDropTarget(item, true);
263
+ };
264
+ this._onDragLeave = (e) => {
265
+ const next = e.relatedTarget;
266
+ if (next instanceof Node && this.contains(next)) return;
267
+ this.#clearDropTarget();
268
+ };
269
+ this._onDrop = (e) => {
270
+ const dt = e.dataTransfer;
271
+ if (!this.itemsDroppable || !dt || this.#isEditEvent(e)) return;
272
+ const item = this._findListItem(e.composedPath());
273
+ if (this.canDrop && !this.canDrop(item, dt)) {
274
+ this.#clearDropTarget();
275
+ return;
276
+ }
277
+ e.preventDefault();
278
+ this.#dragOver = void 0;
279
+ this.#highlightDropTarget(void 0, false);
280
+ this._dispatch(`list-drop`, {
281
+ key: item ? keyForElement(item) : void 0,
282
+ item,
283
+ dataTransfer: dt
284
+ });
285
+ };
286
+ this._onContextMenu = (e) => {
287
+ if (this.#isEditEvent(e)) return;
288
+ const item = this._findListItem(e.composedPath());
289
+ if (!item) return;
290
+ if (!this.#requestContextMenu(item, e.clientX, e.clientY)) e.preventDefault();
291
+ };
229
292
  }
230
293
  #customWrappers;
231
294
  #wrappedElements;
@@ -352,6 +415,10 @@ let VerticalListElement = class VerticalListElement extends LitElement {
352
415
  this.addEventListener(`keydown`, this._onKeyDown);
353
416
  this.addEventListener(`click`, this._onClick);
354
417
  this.addEventListener(`dblclick`, this._onDblClick);
418
+ this.addEventListener(`dragover`, this._onDragOver);
419
+ this.addEventListener(`dragleave`, this._onDragLeave);
420
+ this.addEventListener(`drop`, this._onDrop);
421
+ this.addEventListener(`contextmenu`, this._onContextMenu);
355
422
  for (const el of this.querySelectorAll(ITEM_SELECTOR)) this.#animatedItems.add(el);
356
423
  this.#itemObserver ??= new MutationObserver((records) => this.#onItemsMutated(records));
357
424
  this.#itemObserver.observe(this, { childList: true });
@@ -366,6 +433,12 @@ let VerticalListElement = class VerticalListElement extends LitElement {
366
433
  this.removeEventListener(`keydown`, this._onKeyDown);
367
434
  this.removeEventListener(`click`, this._onClick);
368
435
  this.removeEventListener(`dblclick`, this._onDblClick);
436
+ this.removeEventListener(`dragover`, this._onDragOver);
437
+ this.removeEventListener(`dragleave`, this._onDragLeave);
438
+ this.removeEventListener(`drop`, this._onDrop);
439
+ this.removeEventListener(`contextmenu`, this._onContextMenu);
440
+ this.#clearDropTarget();
441
+ this.#edit = void 0;
369
442
  this.#itemObserver?.disconnect();
370
443
  this.#resizeObserver?.disconnect();
371
444
  this.#resizeObserver = void 0;
@@ -1052,7 +1125,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
1052
1125
  }
1053
1126
  /** Per-attach state the attached sweep can't cover (it only sees the window). */
1054
1127
  #applyRowState(el) {
1055
- if (el instanceof HTMLElement) el.draggable = this.itemsDraggable && this._isCheckable(el);
1128
+ if (el instanceof HTMLElement) el.draggable = this.itemsDraggable && this._isCheckable(el) && !el.hasAttribute(`data-editing`);
1056
1129
  el.removeAttribute(`data-marquee`);
1057
1130
  el.removeAttribute(`data-drag-origin`);
1058
1131
  }
@@ -1262,6 +1335,114 @@ let VerticalListElement = class VerticalListElement extends LitElement {
1262
1335
  if (this.interactionMode !== `manual`) this.selection.replace(item);
1263
1336
  this._dispatch(`list-activate`, { item });
1264
1337
  }
1338
+ /** The row (or `undefined` for empty space) the last `list-drag-over` was fired for. */
1339
+ #dragOver;
1340
+ /** Tell the consumer the drag left its last target and drop the highlight. */
1341
+ #clearDropTarget() {
1342
+ const last = this.#dragOver;
1343
+ this.#dragOver = void 0;
1344
+ this.#highlightDropTarget(void 0, false);
1345
+ if (last) this._dispatch(`list-drag-leave`, { key: last.item ? keyForElement(last.item) : void 0 });
1346
+ }
1347
+ /** Mark one row (or, for empty space, the host) as the drop target. */
1348
+ #highlightDropTarget(item, active) {
1349
+ for (const el of this.querySelectorAll(`[data-drop-target]`)) el.removeAttribute(`data-drop-target`);
1350
+ this.toggleAttribute(`data-drop-target`, active && item === void 0);
1351
+ if (active && item) item.setAttribute(`data-drop-target`, ``);
1352
+ }
1353
+ /**
1354
+ * Select the row if it is not already, then fire `list-context-menu`.
1355
+ * Returns false when a listener cancelled it (the native menu is then suppressed).
1356
+ */
1357
+ #requestContextMenu(item, x, y) {
1358
+ if (!this.selection.selected.has(item) && this.interactionMode !== `manual` && this._isCheckable(item)) this.selection.replace(item);
1359
+ return this._dispatchCancelable(`list-context-menu`, {
1360
+ key: keyForElement(item),
1361
+ item,
1362
+ x,
1363
+ y,
1364
+ selectedKeys: this.selection.selectedKeys
1365
+ });
1366
+ }
1367
+ #edit;
1368
+ /** The key of the row being edited, if any. */
1369
+ get editingKey() {
1370
+ return this.#edit?.key;
1371
+ }
1372
+ #isEditEvent(e) {
1373
+ return this.#edit !== void 0 && e.composedPath().includes(this.#edit.label);
1374
+ }
1375
+ /**
1376
+ * Edit a row's label in place with an `ixfx-editable-label`. The editor
1377
+ * replaces the row's `[data-edit-label]` element (else the whole row) and
1378
+ * the original content returns when editing ends. Fires `list-edit-commit`
1379
+ * `{ key, value }` when the text changed, otherwise `list-edit-cancel`
1380
+ * `{ key }` (Escape, an unchanged value, or one the label rejects). The list
1381
+ * never rewrites the label itself — update your data in response.
1382
+ *
1383
+ * Returns false when `editValidator` is not set, or the row is unknown or
1384
+ * not currently rendered.
1385
+ */
1386
+ beginEdit(key) {
1387
+ this.#finishEdit();
1388
+ const validate = this.editValidator;
1389
+ if (!validate) return false;
1390
+ const row = this.#itemForKey(key);
1391
+ if (!(row instanceof HTMLElement) || row.parentNode !== this) return false;
1392
+ const container = row.querySelector(`[data-edit-label]`) ?? row;
1393
+ const value = container.getAttribute(`data-edit-value`) ?? container.textContent?.trim() ?? ``;
1394
+ const label = document.createElement(`ixfx-editable-label`);
1395
+ label.mode = `label`;
1396
+ label.value = value;
1397
+ label.validator = (text) => validate(text, key);
1398
+ label.style.cssText = `flex:1;min-width:0;--label-align:left;--label-padding:0 var(--space-xs,3px)`;
1399
+ const edit = {
1400
+ key,
1401
+ row,
1402
+ container,
1403
+ saved: [...container.childNodes],
1404
+ label,
1405
+ committed: void 0,
1406
+ refocus: false
1407
+ };
1408
+ this.#edit = edit;
1409
+ label.addEventListener(`change`, (e) => {
1410
+ e.stopPropagation();
1411
+ edit.committed = e.detail.value;
1412
+ });
1413
+ label.addEventListener(`input`, (e) => e.stopPropagation());
1414
+ label.addEventListener(`keydown`, (e) => {
1415
+ edit.refocus = e.key === `Enter` || e.key === `Escape`;
1416
+ });
1417
+ for (const type of [`pointerdown`, `dragstart`]) label.addEventListener(type, (e) => e.stopPropagation());
1418
+ label.addEventListener(`focusout`, () => this.#finishEdit());
1419
+ container.replaceChildren(label);
1420
+ row.setAttribute(`data-editing`, ``);
1421
+ row.draggable = false;
1422
+ row.scrollIntoView({
1423
+ block: `nearest`,
1424
+ inline: `nearest`
1425
+ });
1426
+ label.updateComplete.then(() => {
1427
+ if (this.#edit === edit) label.shadowRoot?.querySelector(`.content`)?.click();
1428
+ });
1429
+ return true;
1430
+ }
1431
+ /** Restore the row's content and report how the edit ended. */
1432
+ #finishEdit() {
1433
+ const edit = this.#edit;
1434
+ if (!edit) return;
1435
+ this.#edit = void 0;
1436
+ if (edit.container.isConnected) edit.container.replaceChildren(...edit.saved);
1437
+ edit.row.removeAttribute(`data-editing`);
1438
+ this.#applyRowState(edit.row);
1439
+ if (edit.refocus) this.focus();
1440
+ if (edit.committed === void 0) this._dispatch(`list-edit-cancel`, { key: edit.key });
1441
+ else this._dispatch(`list-edit-commit`, {
1442
+ key: edit.key,
1443
+ value: edit.committed
1444
+ });
1445
+ }
1265
1446
  static {
1266
1447
  this.styles = [
1267
1448
  themeFallbacks,
@@ -1422,6 +1603,18 @@ let VerticalListElement = class VerticalListElement extends LitElement {
1422
1603
  opacity: 0.6;
1423
1604
  }
1424
1605
 
1606
+ /* Native drop target: the row under a drag, or the whole list over empty space. */
1607
+ ::slotted([data-drop-target]) {
1608
+ background: var(--list-drop-target-bg, color-mix(in srgb, var(--accent) 25%, transparent));
1609
+ outline: 2px solid var(--list-drop-target-outline, var(--accent));
1610
+ outline-offset: -2px;
1611
+ }
1612
+
1613
+ :host([data-drop-target]) {
1614
+ outline: 2px solid var(--list-drop-target-outline, var(--accent));
1615
+ outline-offset: -2px;
1616
+ }
1617
+
1425
1618
  /* checked mode: checkbox (injected into li) communicates selection — suppress bg highlight */
1426
1619
  :host([interaction-mode="checked"]) ::slotted([data-selected]) {
1427
1620
  background: transparent;
@@ -1494,6 +1687,13 @@ __decorate([property({
1494
1687
  type: Number,
1495
1688
  attribute: `item-height`
1496
1689
  })], VerticalListElement.prototype, "itemHeight", void 0);
1690
+ __decorate([property({
1691
+ type: Boolean,
1692
+ attribute: `items-droppable`,
1693
+ reflect: true
1694
+ })], VerticalListElement.prototype, "itemsDroppable", void 0);
1695
+ __decorate([property({ attribute: false })], VerticalListElement.prototype, "editValidator", void 0);
1696
+ __decorate([property({ attribute: false })], VerticalListElement.prototype, "canDrop", void 0);
1497
1697
  VerticalListElement = __decorate([safeCustomElement(`ixfx-vertical-list`)], VerticalListElement);
1498
1698
  //#endregion
1499
1699
  export { VerticalListElement };