@genexus/genexus-ide-ui 0.0.29 → 0.0.31

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 (82) hide show
  1. package/dist/cjs/ch-action-group_2.cjs.entry.js +2 -9
  2. package/dist/cjs/ch-checkbox.cjs.entry.js +1 -1
  3. package/dist/cjs/ch-dropdown-item.cjs.entry.js +8 -8
  4. package/dist/cjs/ch-dropdown.cjs.entry.js +11 -10
  5. package/dist/cjs/ch-suggest_4.cjs.entry.js +1 -0
  6. package/dist/cjs/ch-test-action-group.cjs.entry.js +2 -2
  7. package/dist/cjs/ch-test-tree-x.cjs.entry.js +150 -80
  8. package/dist/cjs/ch-tree-x_3.cjs.entry.js +211 -132
  9. package/dist/cjs/ch-window_2.cjs.entry.js +28 -12
  10. package/dist/cjs/genexus-ide-ui.cjs.js +1 -1
  11. package/dist/cjs/gx-ide-team-dev-commit.cjs.entry.js +3 -3
  12. package/dist/cjs/gxg-combo-box_6.cjs.entry.js +10 -4
  13. package/dist/cjs/gxg-date-picker.cjs.entry.js +4 -4
  14. package/dist/cjs/loader.cjs.js +1 -1
  15. package/dist/collection/components/team-dev-commit/gx-ide-assets/team-dev-commit/langs/team-dev-commit.lang.en.json +1 -1
  16. package/dist/collection/components/team-dev-commit/team-dev-commit.css +3 -0
  17. package/dist/collection/components/team-dev-commit/team-dev-commit.js +2 -2
  18. package/dist/components/action-group-item.js +1 -9
  19. package/dist/components/action-group.js +1 -1
  20. package/dist/components/ch-suggest2.js +1 -0
  21. package/dist/components/ch-test-action-group.js +2 -2
  22. package/dist/components/ch-test-tree-x.js +157 -83
  23. package/dist/components/ch-window2.js +31 -13
  24. package/dist/components/checkbox.js +1 -1
  25. package/dist/components/combo-box-item.js +2 -2
  26. package/dist/components/combo-box.js +8 -2
  27. package/dist/components/dropdown-item.js +8 -8
  28. package/dist/components/dropdown.js +11 -10
  29. package/dist/components/gx-ide-team-dev-commit.js +3 -3
  30. package/dist/components/gxg-date-picker.js +4 -4
  31. package/dist/components/tree-x-list-item.js +31 -17
  32. package/dist/components/tree-x-list.js +9 -4
  33. package/dist/components/tree-x.js +182 -117
  34. package/dist/esm/ch-action-group_2.entry.js +2 -9
  35. package/dist/esm/ch-checkbox.entry.js +1 -1
  36. package/dist/esm/ch-dropdown-item.entry.js +8 -8
  37. package/dist/esm/ch-dropdown.entry.js +11 -10
  38. package/dist/esm/ch-suggest_4.entry.js +1 -0
  39. package/dist/esm/ch-test-action-group.entry.js +2 -2
  40. package/dist/esm/ch-test-tree-x.entry.js +150 -80
  41. package/dist/esm/ch-tree-x_3.entry.js +211 -132
  42. package/dist/esm/ch-window_2.entry.js +28 -12
  43. package/dist/esm/genexus-ide-ui.js +1 -1
  44. package/dist/esm/gx-ide-team-dev-commit.entry.js +3 -3
  45. package/dist/esm/gxg-combo-box_6.entry.js +10 -4
  46. package/dist/esm/gxg-date-picker.entry.js +4 -4
  47. package/dist/esm/loader.js +1 -1
  48. package/dist/genexus-ide-ui/genexus-ide-ui.css +1 -1
  49. package/dist/genexus-ide-ui/genexus-ide-ui.esm.js +1 -1
  50. package/dist/genexus-ide-ui/gx-ide-assets/team-dev-commit/langs/team-dev-commit.lang.en.json +1 -1
  51. package/dist/genexus-ide-ui/p-1fe05a05.entry.js +1 -0
  52. package/dist/genexus-ide-ui/p-24f47ee2.entry.js +1 -0
  53. package/dist/genexus-ide-ui/{p-54bab171.entry.js → p-28d0afda.entry.js} +1 -1
  54. package/dist/genexus-ide-ui/{p-6050cdba.entry.js → p-48412811.entry.js} +1 -1
  55. package/dist/genexus-ide-ui/p-714bd8ea.entry.js +1 -0
  56. package/dist/genexus-ide-ui/p-8c2ab053.entry.js +1 -0
  57. package/dist/genexus-ide-ui/p-976e8118.entry.js +1 -0
  58. package/dist/genexus-ide-ui/p-a5463fc9.entry.js +1 -0
  59. package/dist/genexus-ide-ui/p-b54f448c.entry.js +1 -0
  60. package/dist/genexus-ide-ui/p-bb1809cb.entry.js +1 -0
  61. package/dist/genexus-ide-ui/p-cf41f154.entry.js +1 -0
  62. package/dist/genexus-ide-ui/p-e8a21ed7.entry.js +1 -0
  63. package/dist/node_modules/@genexus/chameleon-controls-library/dist/collection/components/action-group-item/action-group-item.css +0 -1
  64. package/dist/node_modules/@genexus/chameleon-controls-library/dist/collection/components/checkbox/checkbox.css +5 -3
  65. package/dist/node_modules/@genexus/chameleon-controls-library/dist/collection/components/dropdown/dropdown.css +15 -33
  66. package/dist/node_modules/@genexus/chameleon-controls-library/dist/collection/components/dropdown-item/dropdown-item.css +0 -4
  67. package/dist/node_modules/@genexus/chameleon-controls-library/dist/collection/components/test/test-tree-x.css +0 -10
  68. package/dist/node_modules/@genexus/chameleon-controls-library/dist/collection/components/tree-x/tree-x.css +20 -3
  69. package/dist/node_modules/@genexus/chameleon-controls-library/dist/collection/components/tree-x-list-item/tree-x-list-item.css +25 -8
  70. package/dist/node_modules/@genexus/chameleon-controls-library/dist/collection/components/window/ch-window.css +51 -2
  71. package/dist/node_modules/@genexus/gemini/dist/collection/components/combo-box-item/combo-box-item.css +1 -1
  72. package/package.json +3 -3
  73. package/dist/genexus-ide-ui/p-097a3eeb.entry.js +0 -1
  74. package/dist/genexus-ide-ui/p-3d9a4ede.entry.js +0 -1
  75. package/dist/genexus-ide-ui/p-4bbe1c18.entry.js +0 -1
  76. package/dist/genexus-ide-ui/p-5c64c57f.entry.js +0 -1
  77. package/dist/genexus-ide-ui/p-5ff04ebe.entry.js +0 -1
  78. package/dist/genexus-ide-ui/p-757f8567.entry.js +0 -1
  79. package/dist/genexus-ide-ui/p-8d46f8d8.entry.js +0 -1
  80. package/dist/genexus-ide-ui/p-a0e85c2a.entry.js +0 -1
  81. package/dist/genexus-ide-ui/p-e4cac203.entry.js +0 -1
  82. package/dist/genexus-ide-ui/p-f8561da6.entry.js +0 -1
@@ -1,24 +1,42 @@
1
1
  import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
2
2
  import { m as mouseEventModifierKey } from './helpers.js';
3
3
 
4
- const treeXCss = "ch-tree-x{display:flex}ch-tree-x.ch-tree-x-dragging-item :not(.ch-tree-x-list-item--accept-drop){pointer-events:none}ch-tree-x.ch-tree-x-dragging-item .ch-tree-x-list-item--accept-drop{pointer-events:all}ch-tree-x.ch-tree-x-waiting-drop-processing{cursor:wait}ch-tree-x.ch-tree-x-waiting-drop-processing>ch-tree-x-list{pointer-events:none}.ch-tree-x-drag-info{--rtl-offset:16px;position:fixed;left:0;top:0;transform:translate(calc(var(--ch-tree-x-dragging-item-x) + var(--rtl-offset)), calc(var(--ch-tree-x-dragging-item-y) + 8px));pointer-events:none;z-index:1}html[dir=rtl] .ch-tree-x-drag-info{--rtl-offset:-100%}";
4
+ const scrollToEdge = (event, container, scrollSpeed, scrollThreshold) => {
5
+ const mousePositionY = event.clientY - container.getBoundingClientRect().top;
6
+ const containerHeight = container.clientHeight;
7
+ const mouseAtTheTop = mousePositionY <= scrollThreshold;
8
+ const mouseAtTheBottom = mousePositionY > containerHeight - scrollThreshold;
9
+ if (mouseAtTheTop || mouseAtTheBottom) {
10
+ const scrollAmount = mouseAtTheTop
11
+ ? mousePositionY - scrollThreshold
12
+ : mousePositionY - (containerHeight - scrollThreshold);
13
+ // Adjust container scroll position
14
+ container.scrollTop += scrollAmount / scrollSpeed;
15
+ }
16
+ };
17
+
18
+ const treeXCss = "ch-tree-x{display:flex;position:relative;overflow:auto}ch-tree-x>ch-tree-x-list{position:absolute;inset:0;min-width:max-content}ch-tree-x.ch-tree-x-dragging-item ch-tree-x-list-item{pointer-events:var(--ch-tree-x-pointer-events, all)}ch-tree-x.ch-tree-x-dragging-item .ch-tree-x-list-item--deny-drop,ch-tree-x.ch-tree-x-dragging-item ch-tree-x-list{pointer-events:none}ch-tree-x.ch-tree-x--dragging-selected-items ch-tree-x-list-item[selected]{--ch-tree-x-pointer-events:none}ch-tree-x.ch-tree-x-waiting-drop-processing{cursor:wait}ch-tree-x.ch-tree-x-waiting-drop-processing>ch-tree-x-list{pointer-events:none}.ch-tree-x-drag-info{--rtl-offset:16px;position:fixed;left:0;top:0;transform:translate(calc(var(--ch-tree-x-dragging-item-x) + var(--rtl-offset)), calc(var(--ch-tree-x-dragging-item-y) + 8px));pointer-events:none;z-index:1;animation:ch-tree-x-drag-info-fade-in 10ms}@keyframes ch-tree-x-drag-info-fade-in{0%,100%{opacity:0}}html[dir=rtl] .ch-tree-x-drag-info{--rtl-offset:-100%}";
5
19
 
6
20
  const TREE_ITEM_TAG_NAME = "ch-tree-x-list-item";
7
21
  const TREE_LIST_TAG_NAME = "ch-tree-x-list";
8
22
  // Selectors
9
23
  const TREE_LIST_AND_ITEM_SELECTOR = TREE_LIST_TAG_NAME + "," + TREE_ITEM_TAG_NAME;
10
24
  // const CHECKED_ITEMS = `${TREE_ITEM_TAG_NAME}[checked]`;
25
+ const TEXT_FORMAT = "text/plain";
11
26
  const ARROW_DOWN_KEY = "ArrowDown";
12
27
  const ARROW_UP_KEY = "ArrowUp";
13
28
  const EDIT_KEY = "F2";
14
29
  const isExecutedInTree = (event, el) => event.composedPath().includes(el);
15
30
  const treeItemIsInEditMode = () => document.activeElement.editing;
31
+ const getDroppableZoneKey = (newContainerId, draggedItems) => `"newContainerId":"${newContainerId}","metadata":"${JSON.stringify(draggedItems)}"`;
16
32
  const POSITION_X_DRAG_CUSTOM_VAR = "--ch-tree-x-dragging-item-x";
17
33
  const POSITION_Y_DRAG_CUSTOM_VAR = "--ch-tree-x-dragging-item-y";
18
34
  const ChTreeX = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
19
35
  constructor() {
20
36
  super();
21
37
  this.__registerHost();
38
+ this.droppableZoneEnter = createEvent(this, "droppableZoneEnter", 7);
39
+ this.expandedItemChange = createEvent(this, "expandedItemChange", 7);
22
40
  this.selectedItemsChange = createEvent(this, "selectedItemsChange", 7);
23
41
  this.itemsDropped = createEvent(this, "itemsDropped", 7);
24
42
  // @todo TODO: Check if key codes works in Safari
@@ -47,13 +65,18 @@ const ChTreeX = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
47
65
  document.activeElement.editing = true;
48
66
  }
49
67
  };
68
+ this.draggingSelectedItems = false;
50
69
  this.needForRAF = true; // To prevent redundant RAF (request animation frame) calls
51
- this.lastPageX = 0;
52
- this.lastPageY = 0;
53
70
  this.selectedItemsInfo = new Map();
71
+ /**
72
+ * Cache to avoid duplicate requests when checking the droppable zone in the
73
+ * same drag event.
74
+ */
75
+ this.validDroppableZoneCache = new Map();
54
76
  this.draggedIds = [];
55
77
  this.draggedParentIds = [];
56
- this.draggingItem = false;
78
+ this.draggingInTheDocument = false;
79
+ this.draggingInTree = false;
57
80
  /**
58
81
  * Level in the tree at which the control is placed.
59
82
  */
@@ -67,54 +90,41 @@ const ChTreeX = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
67
90
  * over in a subtree to open it when dragging.
68
91
  */
69
92
  this.openSubTreeCountdown = 750;
93
+ /**
94
+ * `true` to scroll in the tree when dragging an item near the edges of the
95
+ * tree.
96
+ */
97
+ this.scrollToEdgeOnDrag = true;
70
98
  /**
71
99
  * `true` to display the relation between tree items and tree lists using
72
100
  * lines.
73
101
  */
74
- this.showLines = false;
102
+ this.showLines = "none";
75
103
  /**
76
104
  * This property lets you specify if the tree is waiting to process the drop
77
105
  * of items.
78
106
  */
79
107
  this.waitDropProcessing = false;
80
- this.trackItemDragEnter = (event) => {
81
- event.stopPropagation();
82
- const currentTarget = event.target;
83
- // Don't mark droppable zones if they are the dragged items or their direct parents
84
- if (!this.validDroppableZone(currentTarget.id)) {
85
- return;
86
- }
87
- // Check if it is a valid item
88
- if (currentTarget.tagName.toLowerCase() !== TREE_ITEM_TAG_NAME) {
89
- return;
90
- }
91
- const treeItem = currentTarget;
92
- treeItem.dragState = "enter";
93
- this.openSubTreeAfterCountdown(treeItem);
94
- };
95
- this.validDroppableZone = (draggedItemId) => !this.draggedIds.includes(draggedItemId) &&
96
- !this.draggedParentIds.includes(draggedItemId);
97
- this.trackItemDragLeave = (event) => {
98
- const currentTarget = event.target;
99
- if (currentTarget.tagName.toLowerCase() !== TREE_ITEM_TAG_NAME) {
100
- return;
101
- }
102
- const treeItem = currentTarget;
103
- treeItem.dragState = "none";
104
- this.cancelSubTreeOpening(treeItem);
105
- };
106
108
  this.trackItemDrag = (event) => {
107
109
  event.preventDefault();
108
- this.lastPageX = event.pageX;
109
- this.lastPageY = event.pageY;
110
+ this.lastDragEvent = event;
110
111
  if (!this.needForRAF) {
111
112
  return;
112
113
  }
113
114
  this.needForRAF = false; // No need to call RAF up until next frame
114
115
  requestAnimationFrame(() => {
115
116
  this.needForRAF = true; // RAF now consumes the movement instruction so a new one can come
116
- this.el.style.setProperty(POSITION_X_DRAG_CUSTOM_VAR, `${this.lastPageX}px`);
117
- this.el.style.setProperty(POSITION_Y_DRAG_CUSTOM_VAR, `${this.lastPageY}px`);
117
+ this.el.style.setProperty(POSITION_X_DRAG_CUSTOM_VAR, `${this.lastDragEvent.pageX}px`);
118
+ this.el.style.setProperty(POSITION_Y_DRAG_CUSTOM_VAR, `${this.lastDragEvent.pageY}px`);
119
+ });
120
+ };
121
+ this.fixScrollPositionOnDrag = () => {
122
+ if (!this.draggingInTree || !this.lastDragEvent) {
123
+ return;
124
+ }
125
+ requestAnimationFrame(() => {
126
+ scrollToEdge(this.lastDragEvent, this.el, 10, 30);
127
+ requestAnimationFrame(this.fixScrollPositionOnDrag);
118
128
  });
119
129
  };
120
130
  this.handleKeyDownEvents = (event) => {
@@ -149,37 +159,26 @@ const ChTreeX = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
149
159
  itemRef.scrollIntoView();
150
160
  });
151
161
  }
152
- // /**
153
- // * This method is used to toggle a tree item by the tree item id/ids.
154
- // *
155
- // * @param treeItemIds An array id the tree items to be toggled.
156
- // * @param expand A boolean indicating that the tree item should be expanded or collapsed. (optional)
157
- // * @returns The modified items after the method was called.
158
- // */
159
- // @Method()
160
- // async toggleItems(
161
- // treeItemIds: string[],
162
- // expand?: boolean
163
- // ): Promise<ExpandedTreeItemInfo[]> {
164
- // if (!treeItemIds) {
165
- // return [];
166
- // }
167
- // const allTreeItems = Array.from(
168
- // this.el.querySelectorAll(TREE_ITEM_TAG_NAME)
169
- // );
170
- // const modifiedTreeItems: ExpandedTreeItemInfo[] = [];
171
- // treeItemIds.forEach(treeItemId => {
172
- // const treeItem = allTreeItems.find(item => treeItemId === item.id);
173
- // if (treeItem) {
174
- // treeItem.expanded = expand ?? !treeItem.expanded;
175
- // modifiedTreeItems.push({
176
- // id: treeItem.id,
177
- // expanded: treeItem.expanded
178
- // });
179
- // }
180
- // });
181
- // return modifiedTreeItems;
182
- // }
162
+ /**
163
+ * Update the information about the valid droppable zones.
164
+ * @param requestTimestamp Time where the request to the server was made. Useful to avoid having old information.
165
+ * @param newContainerId ID of the container where the drag is trying to be made.
166
+ * @param draggedItems Information about the dragged items.
167
+ * @param validDrop Current state of the droppable zone.
168
+ */
169
+ async updateValidDroppableZone(requestTimestamp, newContainerId, draggedItems, validDrop) {
170
+ var _a;
171
+ if (!this.draggingInTheDocument ||
172
+ requestTimestamp <= this.dragStartTimestamp) {
173
+ return;
174
+ }
175
+ const droppableZoneKey = getDroppableZoneKey(newContainerId, draggedItems);
176
+ this.validDroppableZoneCache.set(droppableZoneKey, validDrop ? "valid" : "invalid");
177
+ const shouldUpdateDragEnterInCurrentContainer = ((_a = this.lastOpenSubTreeItem) === null || _a === void 0 ? void 0 : _a.id) === newContainerId;
178
+ if (shouldUpdateDragEnterInCurrentContainer) {
179
+ this.lastOpenSubTreeItem.dragState = "enter";
180
+ }
181
+ }
183
182
  // /**
184
183
  // * Returns an array of the selected tree items, providing the id, caption and
185
184
  // * selected status.
@@ -195,98 +194,160 @@ const ChTreeX = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
195
194
  // selected: item.selected
196
195
  // }));
197
196
  // }
197
+ // We can't use capture, because the dataTransfer info would not be defined
198
+ // Also, we cant use capture and setTimeout with 0 seconds, because the
199
+ // getData method can only be accessed during the dragstart and drop event
200
+ handleDragStart(event) {
201
+ // Reset the validity of the droppable zones with each new drag start
202
+ this.validDroppableZoneCache.clear();
203
+ this.draggingInTheDocument = true;
204
+ this.dragStartTimestamp = new Date().getTime();
205
+ this.draggedItems = JSON.parse(event.dataTransfer.getData(TEXT_FORMAT));
206
+ }
207
+ handleDragEnd() {
208
+ this.draggingInTheDocument = false;
209
+ }
210
+ handleDragEnter(event) {
211
+ this.cancelSubTreeOpening(null, true);
212
+ event.stopPropagation();
213
+ const containerTarget = event.target;
214
+ // Check if it is a valid item
215
+ if (containerTarget.tagName.toLowerCase() !== TREE_ITEM_TAG_NAME) {
216
+ return;
217
+ }
218
+ this.lastOpenSubTreeItem = containerTarget;
219
+ this.openSubTreeAfterCountdown(containerTarget);
220
+ if (this.validDroppableZone(event) === "valid") {
221
+ containerTarget.dragState = "enter";
222
+ }
223
+ }
224
+ handleDragLeave(event) {
225
+ const currentTarget = event.target;
226
+ if (currentTarget.tagName.toLowerCase() !== TREE_ITEM_TAG_NAME) {
227
+ return;
228
+ }
229
+ const treeItem = currentTarget;
230
+ treeItem.dragState = "none";
231
+ this.cancelSubTreeOpening(treeItem);
232
+ }
233
+ cancelSubTreeOpening(treeItem, forceClear = false) {
234
+ if (this.lastOpenSubTreeItem === treeItem || forceClear) {
235
+ clearTimeout(this.openSubTreeTimeout);
236
+ this.lastOpenSubTreeItem = null;
237
+ }
238
+ }
239
+ handleItemDrop(event) {
240
+ event.stopPropagation();
241
+ this.cancelSubTreeOpening(null, true);
242
+ const newContainer = event.target;
243
+ const draggedItems = JSON.parse(event.dataTransfer.getData(TEXT_FORMAT));
244
+ // The droppable zone must be checked, even if it was marked as not valid
245
+ // @todo Try to drop an item with high delays in droppable zone checking
246
+ if (this.validDroppableZone(event) !== "valid") {
247
+ return;
248
+ }
249
+ this.itemsDropped.emit({
250
+ newContainer: { id: newContainer.id, metadata: newContainer.metadata },
251
+ draggedItems: draggedItems,
252
+ dropInTheSameTree: this.draggingInTree
253
+ });
254
+ }
198
255
  handleItemDragStart(event) {
199
256
  document.body.addEventListener("dragover", this.trackItemDrag, {
200
257
  capture: true
201
258
  });
202
259
  this.currentDraggedItem = event.target;
203
260
  this.updateDragInfo(event.detail);
204
- this.el.addEventListener("dragenter", this.trackItemDragEnter, {
205
- capture: true,
206
- passive: true
207
- });
208
- this.el.addEventListener("dragleave", this.trackItemDragLeave, {
209
- capture: true,
210
- passive: true
211
- });
212
- // Wait until the custom var values are updated to avoid flickering
213
- setTimeout(() => {
214
- this.draggingItem = true;
215
- }, 10);
261
+ this.draggingInTree = true;
262
+ if (this.scrollToEdgeOnDrag) {
263
+ this.fixScrollPositionOnDrag();
264
+ }
216
265
  }
217
266
  handleItemDragEnd() {
218
- this.draggingItem = false;
267
+ this.draggingInTree = false;
219
268
  document.body.removeEventListener("dragover", this.trackItemDrag, {
220
269
  capture: true
221
270
  });
222
- this.el.removeEventListener("dragenter", this.trackItemDragEnter, {
223
- capture: true
224
- });
225
- this.el.removeEventListener("dragleave", this.trackItemDragLeave, {
226
- capture: true
227
- });
228
271
  // Reset not allowed droppable ids
229
272
  this.resetVariables();
230
273
  }
231
- handleItemDrop(event) {
232
- event.stopPropagation();
233
- this.cancelSubTreeOpening(null, true);
234
- const selectedItemEl = event.target;
235
- if (!this.validDroppableZone(selectedItemEl.id)) {
236
- return;
237
- }
238
- this.itemsDropped.emit(event.detail);
239
- }
240
274
  handleSelectedItemChange(event) {
241
275
  event.stopPropagation();
242
276
  const selectedItemInfo = event.detail;
243
277
  const selectedItemEl = event.target;
244
278
  this.handleItemSelection(selectedItemEl, selectedItemInfo);
245
279
  }
246
- openSubTreeAfterCountdown(treeItem) {
247
- this.cancelSubTreeOpening(treeItem);
248
- if (treeItem.leaf || treeItem.expanded) {
280
+ validDroppableZone(event) {
281
+ const containerTarget = event.target;
282
+ // When dragging in the same tree, don't mark droppable zones if they are
283
+ // the dragged items or their direct parents
284
+ if (this.draggingInTree &&
285
+ (this.draggedIds.includes(containerTarget.id) ||
286
+ this.draggedParentIds.includes(containerTarget.id))) {
287
+ return "invalid";
288
+ }
289
+ const cacheKey = getDroppableZoneKey(containerTarget.id, this.draggedItems);
290
+ const droppableZoneState = this.validDroppableZoneCache.get(cacheKey);
291
+ if (droppableZoneState != null) {
292
+ return droppableZoneState;
293
+ }
294
+ this.validDroppableZoneCache.set(cacheKey, "checking");
295
+ this.droppableZoneEnter.emit({
296
+ newContainer: {
297
+ id: containerTarget.id,
298
+ metadata: containerTarget.metadata
299
+ },
300
+ draggedItems: this.draggedItems
301
+ });
302
+ return "checking";
303
+ }
304
+ openSubTreeAfterCountdown(currentTarget) {
305
+ if (currentTarget.leaf || currentTarget.expanded) {
249
306
  return;
250
307
  }
251
- this.lastOpenSubTreeItem = treeItem;
252
308
  this.openSubTreeTimeout = setTimeout(() => {
253
- treeItem.expanded = true;
309
+ currentTarget.expanded = true;
310
+ this.expandedItemChange.emit({ id: currentTarget.id, expanded: true });
254
311
  }, this.openSubTreeCountdown);
255
312
  }
256
- cancelSubTreeOpening(treeItem, forceClear = false) {
257
- if (this.lastOpenSubTreeItem === treeItem || forceClear) {
258
- clearTimeout(this.openSubTreeTimeout);
259
- }
260
- }
261
313
  resetVariables() {
262
314
  this.draggedIds = [];
263
315
  this.draggedParentIds = [];
264
316
  }
265
317
  /**
266
- * Update the dataTransfer in the drag event to store the ids of the dragged
267
- * items. Also it updates the visual information of the dragged items.
318
+ * Update the dataTransfer in the drag event to store the ids and metadata of
319
+ * the dragged items. Also it updates the visual information of the dragged
320
+ * items.
268
321
  */
269
322
  updateDragInfo(dragInfo) {
270
323
  const draggedElement = dragInfo.elem;
271
324
  const isDraggingSelectedItems = this.selectedItemsInfo.has(draggedElement.id);
272
- let joinedDraggedIds;
325
+ this.draggingSelectedItems = isDraggingSelectedItems;
326
+ let dataTransferInfo = [];
273
327
  if (isDraggingSelectedItems) {
274
328
  const selectedItemKeys = [...this.selectedItemsInfo.keys()];
275
329
  const selectedItemCount = selectedItemKeys.length;
276
330
  this.draggedIds = selectedItemKeys;
277
- joinedDraggedIds = selectedItemKeys.join(",");
331
+ dataTransferInfo = [...this.selectedItemsInfo.values()].map(el => ({
332
+ id: el.id,
333
+ metadata: el.metadata
334
+ }));
278
335
  this.dragInfo =
279
336
  selectedItemCount === 1
280
337
  ? draggedElement.caption
281
338
  : selectedItemCount.toString();
282
339
  }
283
340
  else {
284
- joinedDraggedIds = draggedElement.id;
285
- this.draggedIds = [joinedDraggedIds];
341
+ dataTransferInfo = [
342
+ { id: draggedElement.id, metadata: draggedElement.metadata }
343
+ ];
344
+ this.draggedIds = [draggedElement.id];
286
345
  this.dragInfo = draggedElement.caption;
287
346
  }
288
347
  this.getDirectParentsOfDraggableItems(isDraggingSelectedItems);
289
- dragInfo.dataTransfer.setData("text/plain", joinedDraggedIds);
348
+ // Update drag event info
349
+ const data = JSON.stringify(dataTransferInfo);
350
+ dragInfo.dataTransfer.setData(TEXT_FORMAT, data);
290
351
  }
291
352
  getDirectParentsOfDraggableItems(draggingSelectedItems) {
292
353
  if (!draggingSelectedItems) {
@@ -343,9 +404,10 @@ const ChTreeX = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
343
404
  }
344
405
  render() {
345
406
  return (h(Host, { class: {
346
- "ch-tree-x-dragging-item": this.draggingItem,
407
+ "ch-tree-x-dragging-item": this.draggingInTheDocument,
408
+ "ch-tree-x--dragging-selected-items": this.draggingInTree && this.draggingSelectedItems,
347
409
  "ch-tree-x-waiting-drop-processing": this.waitDropProcessing
348
- } }, h("slot", null), this.draggingItem && (h("span", { "aria-hidden": "true", class: "ch-tree-x-drag-info" }, this.dragInfo))));
410
+ } }, h("slot", null), this.draggingInTree && (h("span", { "aria-hidden": "true", class: "ch-tree-x-drag-info" }, this.dragInfo))));
349
411
  }
350
412
  get el() { return this; }
351
413
  static get watchers() { return {
@@ -356,11 +418,14 @@ const ChTreeX = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
356
418
  "level": [2],
357
419
  "multiSelection": [4, "multi-selection"],
358
420
  "openSubTreeCountdown": [2, "open-sub-tree-countdown"],
359
- "showLines": [4, "show-lines"],
421
+ "scrollToEdgeOnDrag": [4, "scroll-to-edge-on-drag"],
422
+ "showLines": [1, "show-lines"],
360
423
  "waitDropProcessing": [4, "wait-drop-processing"],
361
- "draggingItem": [32],
362
- "scrollIntoVisible": [64]
363
- }, [[0, "itemDragStart", "handleItemDragStart"], [0, "itemDragEnd", "handleItemDragEnd"], [0, "itemDrop", "handleItemDrop"], [0, "selectedItemChange", "handleSelectedItemChange"]]]);
424
+ "draggingInTheDocument": [32],
425
+ "draggingInTree": [32],
426
+ "scrollIntoVisible": [64],
427
+ "updateValidDroppableZone": [64]
428
+ }, [[9, "dragstart", "handleDragStart"], [11, "dragend", "handleDragEnd"], [3, "dragenter", "handleDragEnter"], [3, "dragleave", "handleDragLeave"], [1, "drop", "handleItemDrop"], [0, "itemDragStart", "handleItemDragStart"], [0, "itemDragEnd", "handleItemDragEnd"], [0, "selectedItemChange", "handleSelectedItemChange"]]]);
364
429
  function defineCustomElement() {
365
430
  if (typeof customElements === "undefined") {
366
431
  return;
@@ -122,7 +122,7 @@ const ChActionGroup = class {
122
122
  }
123
123
  connectActionsContainerObserver() {
124
124
  this.actionsContainerWatcher = new ResizeObserver(this.updateDisplayedActionInFrame);
125
- this.actionsContainerWatcher.observe(this.el);
125
+ this.actionsContainerWatcher.observe(this.actionsContainer);
126
126
  }
127
127
  disconnectActionsObserver() {
128
128
  if (this.actionsWatcher) {
@@ -169,15 +169,11 @@ const ChActionGroup = class {
169
169
  };
170
170
  ChActionGroup.style = actionGroupCss;
171
171
 
172
- const actionGroupItemCss = "ch-action-group-item[floating]{position:absolute;visibility:hidden}";
172
+ const actionGroupItemCss = "ch-action-group-item[floating]{visibility:hidden}";
173
173
 
174
174
  const ChActionGroupItem = class {
175
175
  constructor(hostRef) {
176
176
  registerInstance(this, hostRef);
177
- /**
178
- * `true` to ignore the floating property value.
179
- */
180
- this.avoidFloating = false;
181
177
  /**
182
178
  * `true` if the control is floating. Useful to implement the
183
179
  * `"ResponsiveCollapse"` value for the `itemsOverflowBehavior` property of
@@ -186,9 +182,6 @@ const ChActionGroupItem = class {
186
182
  this.floating = false;
187
183
  }
188
184
  componentWillLoad() {
189
- if (this.avoidFloating) {
190
- return;
191
- }
192
185
  const parentAction = this.el.closest("ch-action-group");
193
186
  // Hide items at the start to improve CLS
194
187
  if (parentAction) {
@@ -1,7 +1,7 @@
1
1
  import { r as registerInstance, c as createEvent, h, H as Host, g as getElement } from './index-0da01575.js';
2
2
  import { D as DISABLED_CLASS } from './reserverd-names-2a2d0fb3.js';
3
3
 
4
- const checkboxCss = "*,::before,::after{box-sizing:border-box}:host{display:flex;align-items:center;align-self:stretch;outline:unset;touch-action:manipulation;user-select:none}:host(.ch-checkbox--actionable) :is(.input,.label){cursor:pointer}.container{position:relative;width:min(1em, 20px);height:min(1em, 20px);border:1px solid var(--option-border-color, #000);border-radius:18.75%}.container--checked{background-color:var(--option-checked-color, #ffffff00)}.container:focus-within{box-shadow:0 0 1px 1px #00000040}.input{display:flex;width:100%;height:100%;opacity:0;margin:0;padding:0}.option{position:absolute;inset:calc(50% - min(0.25em, 5px));width:min(0.5em, 10px);height:min(0.5em, 10px);background-color:#000;opacity:0;pointer-events:none}.option--checked{opacity:1;-webkit-mask:url(\"data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8' %3E%3Cpath fill='currentColor' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z' /%3E%3C/svg%3E\")}.option--indeterminate{opacity:1}.label{margin-inline-start:min(0.35em, 7px)}";
4
+ const checkboxCss = "*,::before,::after{box-sizing:border-box}:host{display:flex;align-items:center;align-self:stretch;outline:unset;touch-action:manipulation;user-select:none}:host(.ch-checkbox--actionable) :is(.input,.label){cursor:pointer}.container{position:relative;width:min(1em, 20px);height:min(1em, 20px);border:1px solid var(--option-border-color, #000);border-radius:18.75%}.container--checked{background-color:var(--option-checked-color, #ffffff00)}.container:focus-within{box-shadow:0 0 1px 1px #00000040}.input{display:flex;width:100%;height:100%;opacity:0;margin:0;padding:0}.option{position:absolute;left:50%;top:50%;transform:translate(-50%, -50%);width:50%;height:50%;background-color:#000;opacity:0;pointer-events:none}.option--checked{opacity:1;-webkit-mask:url(\"data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8' %3E%3Cpath fill='currentColor' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z' /%3E%3C/svg%3E\")}.option--indeterminate{opacity:1}.label{margin-inline-start:min(0.35em, 7px)}";
5
5
 
6
6
  const CHECKBOX_ID = "checkbox";
7
7
  const PARTS = (checked, indeterminate) => `${checked ? " checked" : ""}${indeterminate ? " indeterminate" : ""}`;
@@ -1,6 +1,6 @@
1
1
  import { r as registerInstance, c as createEvent, h, H as Host, g as getElement } from './index-0da01575.js';
2
2
 
3
- const dropdownItemCss = ":where(a,button){all:unset}*,::before,::after{box-sizing:border-box}:host{display:flex;width:100%;height:100%}:host([force-containing-block]){transform:translateX(0);--ch-window-relative-position:true}.action{display:flex;align-items:center;width:100%;height:100%;cursor:pointer;text-align:start}.left-img,.right-img{display:block;width:24px;height:24px;min-width:24px}.content{width:100%}.dummy-wrapper{display:contents}";
3
+ const dropdownItemCss = ":where(a,button){all:unset}*,::before,::after{box-sizing:border-box}:host{display:flex;width:100%;height:100%}:host([force-containing-block]){transform:translateX(0);--ch-window-relative-position:true}.action{display:flex;align-items:center;width:100%;height:100%;cursor:pointer;text-align:start}.left-img,.right-img{display:block;width:24px;height:24px;min-width:24px}.content{width:100%}";
4
4
 
5
5
  const DROPDOWN_ITEM = "ch-dropdown-item";
6
6
  const ChDropDownItem = class {
@@ -31,17 +31,17 @@ const ChDropDownItem = class {
31
31
  */
32
32
  this.position = "Center_OutsideEnd";
33
33
  this.dropDownItemContent = () => [
34
- !!this.leftImgSrc && (h("img", { "aria-hidden": "true", class: "left-img", part: "left-img", alt: "", src: this.leftImgSrc, loading: "lazy" })),
35
- h("span", { class: "content", part: "content" }, h("slot", null)),
36
- !!this.rightImgSrc && (h("img", { "aria-hidden": "true", class: "right-img", part: "right-img", alt: "", src: this.rightImgSrc, loading: "lazy" }))
34
+ !!this.leftImgSrc && (h("img", { slot: "action", "aria-hidden": "true", class: "left-img", part: "left-img", alt: "", src: this.leftImgSrc, loading: "lazy" })),
35
+ h("span", { slot: "action", class: "content", part: "content" }, h("slot", null)),
36
+ !!this.rightImgSrc && (h("img", { slot: "action", "aria-hidden": "true", class: "right-img", part: "right-img", alt: "", src: this.rightImgSrc, loading: "lazy" }))
37
37
  ];
38
38
  this.checkItems = () => {
39
- this.hasItems = !!this.element.querySelector(`:scope>${DROPDOWN_ITEM}`);
39
+ this.hasItems = !!this.el.querySelector(`:scope>${DROPDOWN_ITEM}`);
40
40
  };
41
41
  this.noItemsRender = () => this.href ? (h("a", { class: "action", part: "action target", href: this.href, onClick: this.handleActionClick, onFocus: this.handleFocus, ref: el => (this.mainElement = el) }, this.dropDownItemContent(), h("slot", { name: "items", onSlotchange: this.checkItems }))) : (h("button", { class: "action", part: "action button", type: "button", onClick: this.handleActionClick, onFocus: this.handleFocus, ref: el => (this.mainElement = el) }, this.dropDownItemContent(), h("slot", { name: "items", onSlotchange: this.checkItems })));
42
- this.itemsRender = () => (h("ch-dropdown", { class: "action", exportparts: "expandable-button:action,expandable-button:button,expandable-button:expandable-action,separation,list,section,mask,header,footer,window", expandBehavior: this.expandBehavior, nestedDropdown: true, openOnFocus: this.openOnFocus, position: this.position }, h("div", { class: "dummy-wrapper", slot: "action" }, this.dropDownItemContent()), h("slot", { name: "items", slot: "items", onSlotchange: this.checkItems })));
42
+ this.itemsRender = () => (h("ch-dropdown", { class: "action", exportparts: "expandable-button:action,expandable-button:button,expandable-button:expandable-action,separation,list,section,mask,header,footer,window", expandBehavior: this.expandBehavior, nestedDropdown: true, openOnFocus: this.openOnFocus, position: this.position }, this.dropDownItemContent(), h("slot", { name: "items", slot: "items", onSlotchange: this.checkItems })));
43
43
  this.handleActionClick = () => {
44
- this.actionClick.emit(this.element.id);
44
+ this.actionClick.emit(this.el.id);
45
45
  };
46
46
  this.handleFocus = () => {
47
47
  this.focusChange.emit();
@@ -59,7 +59,7 @@ const ChDropDownItem = class {
59
59
  render() {
60
60
  return (h(Host, { role: "listitem" }, this.hasItems ? this.itemsRender() : this.noItemsRender()));
61
61
  }
62
- get element() { return getElement(this); }
62
+ get el() { return getElement(this); }
63
63
  };
64
64
  ChDropDownItem.style = dropdownItemCss;
65
65
 
@@ -1,6 +1,6 @@
1
1
  import { r as registerInstance, c as createEvent, h, H as Host, g as getElement } from './index-0da01575.js';
2
2
 
3
- const dropdownCss = ":where(button){all:unset}*,::before,::after{box-sizing:border-box}:host{--separation:0px;--separation-x:var(--separation);--separation-y:var(--separation);display:flex;position:relative;width:100%;height:100%}.expandable-button{display:flex;align-items:center;justify-content:center;position:relative;width:100%;height:100%;cursor:pointer;z-index:108}.expandable-button:focus-within{transition:box-shadow 250ms}::slotted([slot=action]){pointer-events:none}.separation{display:flex;position:absolute;z-index:107}.separation--y{width:100%;height:var(--separation-y)}.separation--y-outside-start{inset-block-start:calc(var(--separation-y) * -1)}.separation--y-outside-start+ch-window{--ch-window-offset-y:calc(var(--separation-y) * -1)}.separation--y-outside-end{inset-block-end:calc(var(--separation-y) * -1)}.separation--y-outside-end+ch-window{--ch-window-offset-y:var(--separation-y)}.separation--x{width:var(--separation-x);height:100%}.separation--x-outside-start{inset-inline-start:calc(var(--separation-x) * -1)}.separation--x-outside-start+ch-window{--ch-window-offset-x:calc(var(--separation-x) * -1)}.separation--x-outside-end{inset-inline-end:calc(var(--separation-x) * -1)}.separation--x-outside-end+ch-window{--ch-window-offset-x:var(--separation-x)}.list{display:flex;flex-direction:column}";
3
+ const dropdownCss = ":where(button){all:unset}*,::before,::after{box-sizing:border-box}:host{--separation:0px;--separation-x:var(--separation);--separation-y:var(--separation);display:flex;position:relative;width:100%;height:100%}.expandable-button{display:flex;align-items:center;justify-content:center;position:relative;width:100%;height:100%;cursor:pointer;z-index:108}.expandable-button:focus-within{transition:box-shadow 250ms}::slotted([slot=action]){pointer-events:none}ch-window[y-align=outside-start]{--ch-window-separation:var(--separation-y);--ch-window-separation-y:calc(var(--separation-y) * -1)}ch-window[y-align=outside-end]{--ch-window-separation:var(--separation-y);--ch-window-separation-y:var(--separation-y)}ch-window[x-align=outside-start]{--ch-window-separation:var(--separation-x);--ch-window-separation-x:calc(var(--separation-x) * -1)}ch-window[x-align=outside-end]{--ch-window-separation:var(--separation-x);--ch-window-separation-x:var(--separation-x)}.list{display:flex;flex-direction:column}";
4
4
 
5
5
  const mapDropdownAlignToChWindowAlign = {
6
6
  OutsideStart: "outside-start",
@@ -51,6 +51,7 @@ const ChDropDown = class {
51
51
  };
52
52
  this.showHeader = false;
53
53
  this.showFooter = false;
54
+ this.firstExpanded = false;
54
55
  this.expanded = false;
55
56
  this.expandedWithHover = false;
56
57
  /**
@@ -232,22 +233,22 @@ const ChDropDown = class {
232
233
  const aligns = this.position.split("_");
233
234
  const alignX = aligns[0];
234
235
  const alignY = aligns[1];
235
- const hasVerticalPosition = alignY === "OutsideStart" || alignY === "OutsideEnd";
236
236
  const xAlignMapping = mapDropdownAlignToChWindowAlign[alignX];
237
237
  const yAlignMapping = mapDropdownAlignToChWindowAlign[alignY];
238
238
  const isExpanded = this.expanded || this.expandedWithHover;
239
+ this.firstExpanded || (this.firstExpanded = isExpanded);
239
240
  return (h(Host, { onMouseLeave: this.expandBehavior === "ClickOrHover"
240
241
  ? this.handleMouseLeave
241
242
  : undefined }, h("button", { id: EXPANDABLE_BUTTON_ID, "aria-controls": SECTION_ID, "aria-expanded": this.expanded.toString(), "aria-haspopup": "true", "aria-label": this.buttonLabel, class: "expandable-button", part: "expandable-button", type: "button", onClick: this.handleButtonClick, onFocus: this.openOnFocus ? this.handleButtonFocus : undefined, onMouseEnter: this.expandBehavior === "ClickOrHover"
242
243
  ? this.handleMouseEnter
243
- : undefined, ref: el => (this.expandableButton = el) }, h("slot", { name: "action" })), this.expandBehavior === "ClickOrHover" && (
244
- // Necessary since the separation between the button and the section
245
- // triggers the onMouseLeave event
246
- h("div", { "aria-hidden": "true", class: {
247
- separation: true,
248
- [`separation--y separation--y-${yAlignMapping}`]: hasVerticalPosition,
249
- [`separation--x separation--x-${xAlignMapping}`]: !hasVerticalPosition
250
- }, part: "separation" })), h("ch-window", { part: "window", exportparts: "window:section,mask,header,footer", container: this.el, closeOnEscape: true, hidden: !isExpanded, modal: false, showFooter: this.showFooter, showHeader: this.showHeader, xAlign: xAlignMapping, yAlign: yAlignMapping }, this.showHeader && h("slot", { name: "header", slot: "header" }), h("div", { role: "list", class: "list", part: "list" }, h("slot", { name: "items" })), this.showFooter && h("slot", { name: "footer", slot: "footer" }))));
244
+ : undefined, ref: el => (this.expandableButton = el) }, h("slot", { name: "action" })), h("ch-window", { part: "window", exportparts: "window:section,mask,header,footer,separation", container: this.expandableButton, closeOnEscape: true, hidden: !isExpanded, modal: false, showFooter: this.showFooter, showHeader: this.showHeader, showMain: false,
245
+ // Necessary since the separation between the button and the section
246
+ // triggers the onMouseLeave event
247
+ showSeparation: this.expandBehavior === "ClickOrHover", xAlign: xAlignMapping, yAlign: yAlignMapping }, this.firstExpanded && [
248
+ this.showHeader && h("slot", { name: "header", slot: "header" }),
249
+ h("div", { role: "list", class: "list", part: "list" }, h("slot", { name: "items" })),
250
+ this.showFooter && h("slot", { name: "footer", slot: "footer" })
251
+ ])));
251
252
  }
252
253
  get el() { return getElement(this); }
253
254
  static get watchers() { return {
@@ -125,6 +125,7 @@ const ChSuggest = class {
125
125
  */
126
126
  this.handleInput = (e) => {
127
127
  const inputValue = e.target.value;
128
+ this.caption = inputValue;
128
129
  if (this.timeoutReference) {
129
130
  clearTimeout(this.timeoutReference);
130
131
  }
@@ -51,7 +51,7 @@ const ChTestActionGroup = class {
51
51
  (this.displayedItemsCount === -1 || index < this.displayedItemsCount) &&
52
52
  item.items != null &&
53
53
  item.items.map(this.renderItem)));
54
- this.firstLevelRenderCollapsedItem = (item) => (h("ch-dropdown-item", { id: item.id, class: item.class, expandBehavior: this.expandBehavior, href: item.target, leftImgSrc: item.leftIcon, openOnFocus: this.openOnFocus, position: item.responsiveCollapsePosition || "OutsideEnd_InsideStart", rightImgSrc: item.rightIcon }, item.title, item.items != null && item.items.map(this.renderItem)));
54
+ this.firstLevelRenderCollapsedItem = (item) => (h("ch-dropdown-item", { slot: "more-items", id: item.id, class: item.class, expandBehavior: this.expandBehavior, href: item.target, leftImgSrc: item.leftIcon, openOnFocus: this.openOnFocus, position: item.responsiveCollapsePosition || "OutsideEnd_InsideStart", rightImgSrc: item.rightIcon }, item.title, item.items != null && item.items.map(this.renderItem)));
55
55
  this.handleDisplayedItemsCountChange = (event) => {
56
56
  this.displayedItemsCount = event.detail;
57
57
  };
@@ -67,7 +67,7 @@ const ChTestActionGroup = class {
67
67
  this.itemsModel
68
68
  .filter((_, index) => this.displayedItemsCount !== -1 &&
69
69
  index >= this.displayedItemsCount)
70
- .map(item => (h("ch-action-group-item", { slot: "more-items", avoidFloating: true }, this.firstLevelRenderCollapsedItem(item)))))));
70
+ .map(this.firstLevelRenderCollapsedItem))));
71
71
  }
72
72
  };
73
73
  ChTestActionGroup.style = testActionGroupCss;