@genexus/genexus-ide-ui 0.0.23 → 0.0.25

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 (61) hide show
  1. package/dist/cjs/ch-action-group_2.cjs.entry.js +211 -0
  2. package/dist/cjs/ch-dropdown-item.cjs.entry.js +36 -5
  3. package/dist/cjs/ch-dropdown.cjs.entry.js +50 -52
  4. package/dist/cjs/ch-test-action-group.cjs.entry.js +79 -0
  5. package/dist/cjs/ch-test-dropdown.cjs.entry.js +54 -0
  6. package/dist/cjs/ch-window_2.cjs.entry.js +25 -6
  7. package/dist/cjs/genexus-ide-ui.cjs.js +1 -1
  8. package/dist/cjs/gx-ide-team-dev-commit.cjs.entry.js +13 -13
  9. package/dist/cjs/loader.cjs.js +1 -1
  10. package/dist/collection/collection-manifest.json +4 -0
  11. package/dist/collection/components/team-dev-commit/gx-ide-assets/team-dev-commit/langs/team-dev-commit.lang.en.json +1 -1
  12. package/dist/collection/components/team-dev-commit/team-dev-commit.js +34 -15
  13. package/dist/components/action-group-item.js +54 -0
  14. package/dist/components/action-group.js +214 -0
  15. package/dist/components/ch-action-group-item.js +6 -0
  16. package/dist/components/ch-action-group.js +6 -0
  17. package/dist/components/ch-dropdown-item-separator.js +1 -28
  18. package/dist/components/ch-dropdown-item.js +1 -53
  19. package/dist/components/ch-dropdown.js +1 -284
  20. package/dist/components/ch-test-action-group.js +137 -0
  21. package/dist/components/ch-test-dropdown.js +104 -0
  22. package/dist/components/ch-window2.js +25 -6
  23. package/dist/components/dropdown-item-separator.js +30 -0
  24. package/dist/components/dropdown-item.js +109 -0
  25. package/dist/components/dropdown.js +294 -0
  26. package/dist/components/gx-ide-team-dev-commit.js +14 -13
  27. package/dist/components/index.js +4 -0
  28. package/dist/esm/ch-action-group_2.entry.js +206 -0
  29. package/dist/esm/ch-dropdown-item.entry.js +36 -5
  30. package/dist/esm/ch-dropdown.entry.js +50 -52
  31. package/dist/esm/ch-test-action-group.entry.js +75 -0
  32. package/dist/esm/ch-test-dropdown.entry.js +50 -0
  33. package/dist/esm/ch-window_2.entry.js +25 -6
  34. package/dist/esm/genexus-ide-ui.js +1 -1
  35. package/dist/esm/gx-ide-team-dev-commit.entry.js +13 -13
  36. package/dist/esm/loader.js +1 -1
  37. package/dist/genexus-ide-ui/genexus-ide-ui.esm.js +1 -1
  38. package/dist/genexus-ide-ui/gx-ide-assets/team-dev-commit/langs/team-dev-commit.lang.en.json +1 -1
  39. package/dist/genexus-ide-ui/p-097a3eeb.entry.js +1 -0
  40. package/dist/genexus-ide-ui/p-4bbe1c18.entry.js +1 -0
  41. package/dist/genexus-ide-ui/p-5c64c57f.entry.js +1 -0
  42. package/dist/genexus-ide-ui/p-5ff04ebe.entry.js +1 -0
  43. package/dist/genexus-ide-ui/p-9c82381c.entry.js +1 -0
  44. package/dist/genexus-ide-ui/p-dbebb1a0.entry.js +1 -0
  45. package/dist/genexus-ide-ui/p-f8561da6.entry.js +1 -0
  46. package/dist/node_modules/@genexus/chameleon-controls-library/dist/collection/components/action-group/action-group.css +48 -0
  47. package/dist/node_modules/@genexus/chameleon-controls-library/dist/collection/components/action-group-item/action-group-item.css +4 -0
  48. package/dist/node_modules/@genexus/chameleon-controls-library/dist/collection/components/dropdown/dropdown.css +32 -88
  49. package/dist/node_modules/@genexus/chameleon-controls-library/dist/collection/components/dropdown-item/dropdown-item.css +9 -22
  50. package/dist/node_modules/@genexus/chameleon-controls-library/dist/collection/components/test/test-action-group/test-action-group.css +52 -0
  51. package/dist/node_modules/@genexus/chameleon-controls-library/dist/collection/components/test/test-dropdown/test-dropdown.css +36 -0
  52. package/dist/node_modules/@genexus/chameleon-controls-library/dist/collection/components/window/ch-window.css +3 -1
  53. package/dist/types/common/types.d.ts +1 -0
  54. package/dist/types/components/team-dev-commit/team-dev-commit.d.ts +13 -6
  55. package/dist/types/components/team-dev-update/team-dev-update.d.ts +1 -1
  56. package/dist/types/components.d.ts +9 -1
  57. package/package.json +3 -3
  58. package/dist/genexus-ide-ui/p-04f094d1.entry.js +0 -1
  59. package/dist/genexus-ide-ui/p-192f1342.entry.js +0 -1
  60. package/dist/genexus-ide-ui/p-66072dce.entry.js +0 -1
  61. package/dist/genexus-ide-ui/p-c10d5f34.entry.js +0 -1
@@ -1,17 +1,45 @@
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}@media (prefers-color-scheme: light){.action:focus,.action:hover{background-color:#ccc}.action:active{background-color:#e9e9e9}}@media (prefers-color-scheme: dark){.action:focus,.action:hover{background-color:#3e3e40}.action:active{background-color:#575965}}:host{display:flex;width:100%;height:100%}.action{display:flex;align-items:center;column-gap:8px;width:100%;height:100%;cursor:pointer;padding-block:8px;padding-inline:16px;font-size:0.875em;text-align:start;transition-property:background-color, border-color, box-shadow, color, filter, opacity;transition-duration:250ms}.left-img,.right-img{display:block;width:24px;height:24px;min-width:24px}.content{width:100%}";
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}";
4
4
 
5
+ const DROPDOWN_ITEM = "ch-dropdown-item";
5
6
  const ChDropDownItem = class {
6
7
  constructor(hostRef) {
7
8
  registerInstance(this, hostRef);
8
9
  this.actionClick = createEvent(this, "actionClick", 7);
9
10
  this.focusChange = createEvent(this, "focusChange", 7);
11
+ this.hasItems = false;
12
+ /**
13
+ * Determine which actions on the expandable button display the dropdown
14
+ * section.
15
+ * Only works if the control has subitems.
16
+ */
17
+ this.expandBehavior = "ClickOrHover";
18
+ /**
19
+ * `true` to force the control to make its own containing block.
20
+ */
21
+ this.forceContainingBlock = true;
22
+ /**
23
+ * Determine if the dropdown section should be opened when the expandable
24
+ * button of the control is focused.
25
+ * Only works if the control has subitems.
26
+ */
27
+ this.openOnFocus = false;
28
+ /**
29
+ * Specifies the position of the dropdown section that is placed relative to
30
+ * the expandable button.
31
+ */
32
+ this.position = "Center_OutsideEnd";
10
33
  this.dropDownItemContent = () => [
11
- !!this.leftImgSrc && (h("img", { "aria-hidden": "true", class: "left-img", part: "dropdown-item__left-img", alt: "", src: this.leftImgSrc, loading: "lazy" })),
12
- h("span", { class: "content", part: "dropdown-item__content" }, h("slot", null)),
13
- !!this.rightImgSrc && (h("img", { "aria-hidden": "true", class: "right-img", part: "dropdown-item__right-img", alt: "", src: this.rightImgSrc, loading: "lazy" }))
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" }))
14
37
  ];
38
+ this.checkItems = () => {
39
+ this.hasItems = !!this.element.querySelector(`:scope>${DROPDOWN_ITEM}`);
40
+ };
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 })));
15
43
  this.handleActionClick = () => {
16
44
  this.actionClick.emit(this.element.id);
17
45
  };
@@ -25,8 +53,11 @@ const ChDropDownItem = class {
25
53
  async handleFocusElement() {
26
54
  this.mainElement.focus();
27
55
  }
56
+ componentWillLoad() {
57
+ this.checkItems();
58
+ }
28
59
  render() {
29
- return (h(Host, { role: "listitem" }, this.href ? (h("a", { class: "action", part: "dropdown-item__target", href: this.href, onClick: this.handleActionClick, onFocus: this.handleFocus, ref: el => (this.mainElement = el) }, this.dropDownItemContent())) : (h("button", { class: "action", part: "dropdown-item__button", type: "button", onClick: this.handleActionClick, onFocus: this.handleFocus, ref: el => (this.mainElement = el) }, this.dropDownItemContent()))));
60
+ return (h(Host, { role: "listitem" }, this.hasItems ? this.itemsRender() : this.noItemsRender()));
30
61
  }
31
62
  get element() { return getElement(this); }
32
63
  };
@@ -1,7 +1,14 @@
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}@media (prefers-color-scheme: light){.section{background-color:#fbfbfb;color:#000}}@media (prefers-color-scheme: dark){.section{background-color:#242426;color:#e9e9e9}}:host{--ch-dropdown-rtl-initial-X:1;--ch-dropdown-translateX:0;--ch-dropdown-translateY:0;display:flex;position:relative;width:100%;height:100%}.expandable-button{display:flex;position:relative;width:100%;height:100%;cursor:pointer;z-index:108}.expandable-button:focus-within{box-shadow:0px 0px 0 1px currentColor;transition:box-shadow 250ms}.dummy-separation{display:flex;position:absolute;z-index:107}.dummy-separation--vertical{width:100%;height:var(--separation-between-button-size)}.dummy-separation--top{inset-block-start:var(--separation-between-button)}.dummy-separation--bottom{inset-block-end:var(--separation-between-button)}.dummy-separation--horizontal{width:var(--separation-between-button-size);height:100%}.dummy-separation--left{inset-inline-start:var(--separation-between-button)}.dummy-separation--right{inset-inline-end:var(--separation-between-button)}.section{position:absolute;border-radius:5px;box-shadow:0 3px 4px #80808024, 0 3px 3px -2px #8080801f, 0 1px 8px #80808030;width:max-content;max-width:350px;z-index:107}.header+.list,.list+.footer{margin-block-start:8px}.list{display:flex;flex-direction:column;gap:4px}.position--top{inset-block-start:var(--separation-between-button);transform:translate(var(--ch-dropdown-translateX), -100%)}.position--right{inset-inline-end:var(--separation-between-button);transform:translate(calc(100% * var(--ch-dropdown-rtl-initial-X)), var(--ch-dropdown-translateY))}.position--bottom{inset-block-end:var(--separation-between-button);transform:translate(var(--ch-dropdown-translateX), 100%)}.position--left{inset-inline-start:var(--separation-between-button);transform:translate(calc(-100% * var(--ch-dropdown-rtl-initial-X)), var(--ch-dropdown-translateY))}.align--left{inset-inline-start:0}.align--center{inset-inline-start:50%;--ch-dropdown-translateX:calc(-50% * var(--ch-dropdown-rtl-initial-X))}.align--right{inset-inline-end:0}.valign--top{inset-block-start:0}.valign--middle{inset-block-start:50%;--ch-dropdown-translateY:calc(-50% * var(--ch-dropdown-rtl-initial-X))}.valign--bottom{inset-block-end:0}";
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}";
4
4
 
5
+ const mapDropdownAlignToChWindowAlign = {
6
+ OutsideStart: "outside-start",
7
+ InsideStart: "inside-start",
8
+ Center: "center",
9
+ InsideEnd: "inside-end",
10
+ OutsideEnd: "outside-end"
11
+ };
5
12
  const EXPANDABLE_BUTTON_ID = "expandable-button";
6
13
  const SECTION_ID = "section";
7
14
  const DROPDOWN_ITEM_TAG_NAME = "ch-dropdown-item";
@@ -46,11 +53,6 @@ const ChDropDown = class {
46
53
  this.showFooter = false;
47
54
  this.expanded = false;
48
55
  this.expandedWithHover = false;
49
- /**
50
- * Specifies the horizontal alignment the dropdown section has when using
51
- * `position === "Top"` or `position === "Bottom"`.
52
- */
53
- this.align = "Center";
54
56
  /**
55
57
  * This attribute lets you specify the label for the expandable button.
56
58
  * Important for accessibility.
@@ -60,7 +62,12 @@ const ChDropDown = class {
60
62
  * Determine which actions on the expandable button display the dropdown
61
63
  * section.
62
64
  */
63
- this.expandBehavior = "Click or Hover";
65
+ this.expandBehavior = "ClickOrHover";
66
+ /**
67
+ * This attribute lets you specify if the control is nested in another
68
+ * dropdown. Useful to manage keyboard interaction.
69
+ */
70
+ this.nestedDropdown = false;
64
71
  /**
65
72
  * Determine if the dropdown section should be opened when the expandable
66
73
  * button of the control is focused.
@@ -70,17 +77,7 @@ const ChDropDown = class {
70
77
  * Specifies the position of the dropdown section that is placed relative to
71
78
  * the expandable button.
72
79
  */
73
- this.position = "Bottom";
74
- /**
75
- * Specifies the separation (in pixels) between the expandable button and the
76
- * dropdown section of the control.
77
- */
78
- this.dropdownSeparation = 12;
79
- /**
80
- * Specifies the vertical alignment the dropdown section has when using
81
- * `position === "Right"` or `position === "Left"`.
82
- */
83
- this.valign = "Middle";
80
+ this.position = "Center_OutsideEnd";
84
81
  this.closeDropdown = () => {
85
82
  this.closeDropdownWithHover();
86
83
  this.expanded = false;
@@ -94,7 +91,7 @@ const ChDropDown = class {
94
91
  }
95
92
  };
96
93
  this.closeDropdownWhenClickingOutside = (event) => {
97
- if (event.composedPath().find(el => el === this.element) === undefined) {
94
+ if (event.composedPath().find(el => el === this.el) === undefined) {
98
95
  this.closeDropdown();
99
96
  }
100
97
  };
@@ -112,15 +109,14 @@ const ChDropDown = class {
112
109
  if (event.code !== TAB_KEY) {
113
110
  return;
114
111
  }
115
- const nextFocusedElement = event.target;
116
- const isChildElement = nextFocusedElement.closest("ch-dropdown") === this.element;
112
+ const isChildElement = event.composedPath().includes(this.el);
117
113
  if (isChildElement) {
118
114
  return;
119
115
  }
120
116
  this.closeDropdown();
121
117
  };
122
118
  this.handleMouseLeave = () => {
123
- const focusedElementIsInsideDropDown = document.activeElement.closest("ch-dropdown") === this.element;
119
+ const focusedElementIsInsideDropDown = document.activeElement.closest("ch-dropdown") === this.el;
124
120
  if (focusedElementIsInsideDropDown) {
125
121
  this.expanded = true;
126
122
  }
@@ -136,11 +132,13 @@ const ChDropDown = class {
136
132
  this.expandedChange.emit(true);
137
133
  }
138
134
  };
139
- this.handleButtonClick = () => {
135
+ this.handleButtonClick = (event) => {
136
+ event.stopPropagation();
140
137
  this.expandedChange.emit(!this.expanded);
141
138
  this.expanded = !this.expanded;
142
139
  };
143
- this.handleButtonFocus = () => {
140
+ this.handleButtonFocus = (event) => {
141
+ event.stopPropagation();
144
142
  if (this.expanded) {
145
143
  return;
146
144
  }
@@ -159,9 +157,11 @@ const ChDropDown = class {
159
157
  capture: true
160
158
  });
161
159
  // Keyboard events
162
- document.body.addEventListener("keydown", this.handleKeyDownEvents, {
163
- capture: true
164
- });
160
+ if (!this.nestedDropdown) {
161
+ document.body.addEventListener("keydown", this.handleKeyDownEvents, {
162
+ capture: true
163
+ });
164
+ }
165
165
  document.body.addEventListener("keyup", this.handleKeyUpEvents, {
166
166
  capture: true
167
167
  });
@@ -172,9 +172,11 @@ const ChDropDown = class {
172
172
  capture: true
173
173
  });
174
174
  // Keyboard events
175
- document.body.removeEventListener("keydown", this.handleKeyDownEvents, {
176
- capture: true
177
- });
175
+ if (!this.nestedDropdown) {
176
+ document.body.removeEventListener("keydown", this.handleKeyDownEvents, {
177
+ capture: true
178
+ });
179
+ }
178
180
  document.body.removeEventListener("keyup", this.handleKeyUpEvents, {
179
181
  capture: true
180
182
  });
@@ -189,7 +191,7 @@ const ChDropDown = class {
189
191
  this.currentFocusedItem = event.target;
190
192
  }
191
193
  focusFirstDropDownItem() {
192
- this.currentFocusedItem = this.element.querySelector(DROPDOWN_ITEM_SELECTOR);
194
+ this.currentFocusedItem = this.el.querySelector(DROPDOWN_ITEM_SELECTOR);
193
195
  if (this.currentFocusedItem) {
194
196
  this.currentFocusedItem.handleFocusElement();
195
197
  }
@@ -218,40 +220,36 @@ const ChDropDown = class {
218
220
  * works if `openOnFocus = "false"`
219
221
  */
220
222
  returnFocusToButton() {
221
- if (!this.openOnFocus) {
223
+ if (!this.openOnFocus && !this.nestedDropdown) {
222
224
  this.expandableButton.focus();
223
225
  }
224
226
  }
225
227
  componentWillLoad() {
226
- this.showHeader = !!this.element.querySelector(':scope > [slot="header"]');
227
- this.showFooter = !!this.element.querySelector(':scope > [slot="footer"]');
228
+ this.showHeader = !!this.el.querySelector(':scope > [slot="header"]');
229
+ this.showFooter = !!this.el.querySelector(':scope > [slot="footer"]');
228
230
  }
229
231
  render() {
230
- const hasVerticalPosition = this.position === "Bottom" || this.position === "Top";
232
+ const aligns = this.position.split("_");
233
+ const alignX = aligns[0];
234
+ const alignY = aligns[1];
235
+ const hasVerticalPosition = alignY === "OutsideStart" || alignY === "OutsideEnd";
236
+ const xAlignMapping = mapDropdownAlignToChWindowAlign[alignX];
237
+ const yAlignMapping = mapDropdownAlignToChWindowAlign[alignY];
231
238
  const isExpanded = this.expanded || this.expandedWithHover;
232
- return (h(Host, { onMouseLeave: this.expandBehavior === "Click or Hover"
239
+ return (h(Host, { onMouseLeave: this.expandBehavior === "ClickOrHover"
233
240
  ? this.handleMouseLeave
234
- : undefined, style: {
235
- "--separation-between-button": `-${this.dropdownSeparation}px`,
236
- "--separation-between-button-size": `${this.dropdownSeparation}px`
237
- } }, 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: "dropdown__expandable-button", type: "button", onClick: this.handleButtonClick, onFocus: this.openOnFocus ? this.handleButtonFocus : undefined, onMouseEnter: this.expandBehavior === "Click or Hover"
241
+ : 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"
238
242
  ? this.handleMouseEnter
239
- : undefined, ref: el => (this.expandableButton = el) }, h("slot", { name: "action" })), this.expandBehavior === "Click or Hover" && this.expandedWithHover && (
243
+ : undefined, ref: el => (this.expandableButton = el) }, h("slot", { name: "action" })), this.expandBehavior === "ClickOrHover" && (
240
244
  // Necessary since the separation between the button and the section
241
245
  // triggers the onMouseLeave event
242
246
  h("div", { "aria-hidden": "true", class: {
243
- "dummy-separation": true,
244
- [`dummy-separation--${this.position.toLowerCase()}`]: true,
245
- "dummy-separation--vertical": hasVerticalPosition,
246
- "dummy-separation--horizontal": !hasVerticalPosition
247
- }, part: "dropdown__separation" })), h("section", { id: SECTION_ID, "aria-labelledby": EXPANDABLE_BUTTON_ID, class: {
248
- section: true,
249
- [`position--${this.position.toLowerCase()}`]: true,
250
- [`align--${this.align.toLowerCase()}`]: hasVerticalPosition,
251
- [`valign--${this.valign.toLowerCase()}`]: !hasVerticalPosition
252
- }, part: "dropdown__section", hidden: !isExpanded }, this.showHeader && (h("header", { class: "header", part: "dropdown__header" }, h("slot", { name: "header" }))), h("div", { role: "list", class: "list", part: "dropdown__list" }, h("slot", { name: "items" })), this.showFooter && (h("footer", { class: "footer", part: "dropdown__footer" }, h("slot", { name: "footer" }))))));
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" }))));
253
251
  }
254
- get element() { return getElement(this); }
252
+ get el() { return getElement(this); }
255
253
  static get watchers() { return {
256
254
  "expanded": ["handleExpandedChange"]
257
255
  }; }
@@ -0,0 +1,75 @@
1
+ import { r as registerInstance, h, H as Host } from './index-0da01575.js';
2
+
3
+ const testActionGroupCss = "ch-test-action-group{display:flex;border:2px dashed #00000080;resize:both;overflow:auto;width:500px}.action-group{padding:20px;margin:20px;background-color:#ffffff;border:1px solid}.action-group::part(actions){gap:12px}.action-group::part(more-actions-button){border-radius:50%;width:fit-content;height:fit-content;color:#313aa1;align-self:center;margin-inline-end:8px}.dropdown-item::part(action){--separation:8px;background-color:#f3d0c3;border-radius:4px;padding-inline:16px;padding-block:8px}.dropdown-item::part(action):focus-within{outline:1px solid}.dropdown-item::part(action):hover{background-color:#d3b1a4}.action-group::part(more-actions-list),.dropdown-item::part(list){row-gap:8px;margin-block:8px}.action-group::part(more-actions-section),.dropdown-item::part(section){background-color:#edeaff;padding:8px;box-shadow:0 4px 8px 1px #22222220}";
4
+
5
+ const ChTestActionGroup = class {
6
+ constructor(hostRef) {
7
+ registerInstance(this, hostRef);
8
+ this.displayedItemsCount = -1;
9
+ /**
10
+ * This attribute lets you specify the label for the expandable button.
11
+ * Important for accessibility.
12
+ */
13
+ this.buttonLabel = "Show options";
14
+ /**
15
+ * Determine which actions on the expandable button display the dropdown
16
+ * section.
17
+ */
18
+ this.expandBehavior = "ClickOrHover";
19
+ /**
20
+ * This attribute determines how items behave when the content of the ActionGroup overflows horizontal. This property is needed
21
+ * to make the control responsive to changes in the Width of the container of ActionGroup.
22
+ *
23
+ * | Value | Details |
24
+ * | --------------------- | ------------------------------------------------------------------------------------------------ |
25
+ * | `Add Scroll` | The items of the ActionGroup that overflow horizontally are shown by means of a scroll. |
26
+ * | `Multiline` | The ActionGroup items that overflow horizontally are shown in a second line of the control. |
27
+ * | `Responsive Collapse` | The Action Group items, when they start to overflow the control, are placed in the More Actions. |
28
+ */
29
+ this.itemsOverflowBehavior = "ResponsiveCollapse";
30
+ /**
31
+ * Determine if the dropdown section should be opened when the expandable
32
+ * button of the control is focused.
33
+ */
34
+ this.openOnFocus = false;
35
+ /**
36
+ * Specifies the position of the dropdown section that is placed relative to
37
+ * the more actions button.
38
+ */
39
+ this.moreActionsDropdownPosition = "InsideStart_OutsideEnd";
40
+ /**
41
+ * Specifies the separation (in pixels) between the expandable button and the
42
+ * dropdown section of the control.
43
+ */
44
+ this.separation = 0;
45
+ // /**
46
+ // * Fired when the visibility of the dropdown section is changed
47
+ // */
48
+ // @Event() expandedChange: EventEmitter<boolean>;
49
+ this.renderItem = (item) => (h("ch-dropdown-item", { slot: "items", id: item.id, class: item.class, expandBehavior: this.expandBehavior, href: item.target, leftImgSrc: item.leftIcon, openOnFocus: this.openOnFocus, position: item.position || "OutsideEnd_InsideStart", rightImgSrc: item.rightIcon }, item.title, item.items != null && item.items.map(this.renderItem)));
50
+ this.firstLevelRenderItem = (item, index) => (h("ch-dropdown-item", { id: item.id, class: item.class, expandBehavior: this.expandBehavior, forceContainingBlock: false, href: item.target, leftImgSrc: item.leftIcon, openOnFocus: this.openOnFocus, position: item.position || "Center_OutsideEnd", rightImgSrc: item.rightIcon }, item.title, this.itemsOverflowBehavior === "ResponsiveCollapse" &&
51
+ (this.displayedItemsCount === -1 || index < this.displayedItemsCount) &&
52
+ item.items != null &&
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)));
55
+ this.handleDisplayedItemsCountChange = (event) => {
56
+ this.displayedItemsCount = event.detail;
57
+ };
58
+ }
59
+ render() {
60
+ return (h(Host, null, h("ch-action-group", { buttonLabel: this.buttonLabel, class: "action-group", expandBehavior: this.expandBehavior, itemsOverflowBehavior: this.itemsOverflowBehavior, openOnFocus: this.openOnFocus, moreActionsDropdownPosition: this.moreActionsDropdownPosition,
61
+ // style={{
62
+ // "--separation": `${this.separation}px`
63
+ // }}
64
+ onDisplayedItemsCountChange: this.handleDisplayedItemsCountChange }, this.itemsModel != null &&
65
+ this.itemsModel.map((item, index) => (h("ch-action-group-item", { slot: "items" }, this.firstLevelRenderItem(item, index)))), this.itemsOverflowBehavior === "ResponsiveCollapse" &&
66
+ this.itemsModel != null &&
67
+ this.itemsModel
68
+ .filter((_, index) => this.displayedItemsCount !== -1 &&
69
+ index >= this.displayedItemsCount)
70
+ .map(item => (h("ch-action-group-item", { slot: "more-items", avoidFloating: true }, this.firstLevelRenderCollapsedItem(item)))))));
71
+ }
72
+ };
73
+ ChTestActionGroup.style = testActionGroupCss;
74
+
75
+ export { ChTestActionGroup as ch_test_action_group };
@@ -0,0 +1,50 @@
1
+ import { r as registerInstance, h, H as Host } from './index-0da01575.js';
2
+
3
+ const testDropdownCss = ".dropdown::part(expandable-button){background-color:aliceblue;border:1px solid;border-radius:4px;padding-block:4px;padding-inline:16px}.dropdown::part(expandable-button):focus{box-shadow:0 0 0 1px black}.dropdown-item::part(action){--separation:8px;background-color:#f3d0c3;border-radius:4px;padding-inline:16px;padding-block:8px}.dropdown-item::part(action):focus-within{outline:1px solid}.dropdown-item::part(action):hover{background-color:#d3b1a4}.dropdown::part(section),.dropdown-item::part(section){background-color:#edeaff;padding:8px;box-shadow:0 4px 8px 1px #22222220}.dropdown::part(list),.dropdown-item::part(list){row-gap:8px;margin-block:8px}";
4
+
5
+ const ChTestDropdownX = class {
6
+ constructor(hostRef) {
7
+ registerInstance(this, hostRef);
8
+ /**
9
+ * This attribute lets you specify the label for the expandable button.
10
+ * Important for accessibility.
11
+ */
12
+ this.buttonLabel = "Show options";
13
+ /**
14
+ * Determine which actions on the expandable button display the dropdown
15
+ * section.
16
+ */
17
+ this.expandBehavior = "ClickOrHover";
18
+ /**
19
+ * Determine if the dropdown section should be opened when the expandable
20
+ * button of the control is focused.
21
+ */
22
+ this.openOnFocus = false;
23
+ /**
24
+ * Specifies the position of the dropdown section that is placed relative to
25
+ * the expandable button.
26
+ */
27
+ this.position = "Center_OutsideEnd";
28
+ /**
29
+ * Specifies the separation (in pixels) between the expandable button and the
30
+ * dropdown section of the control.
31
+ */
32
+ this.separation = 0;
33
+ // /**
34
+ // * Fired when the visibility of the dropdown section is changed
35
+ // */
36
+ // @Event() expandedChange: EventEmitter<boolean>;
37
+ this.renderItem = (item) => [
38
+ h("ch-dropdown-item", { slot: "items", id: item.id, class: item.class, expandBehavior: this.expandBehavior, href: item.target, leftImgSrc: item.leftIcon, openOnFocus: this.openOnFocus, position: "OutsideEnd_InsideStart", rightImgSrc: item.rightIcon }, item.title, item.items != null && item.items.map(this.renderItem)),
39
+ item.showSeparator && (h("ch-dropdown-item-separator", { class: item.separatorClass }))
40
+ ];
41
+ }
42
+ render() {
43
+ return (h(Host, null, h("ch-dropdown", { buttonLabel: this.buttonLabel, class: "dropdown", expandBehavior: this.expandBehavior, openOnFocus: this.openOnFocus, position: this.position, style: {
44
+ "--separation": `${this.separation}px`
45
+ } }, h("span", { slot: "action" }, "User info"), h("div", { slot: "header" }, h("h1", null, "John Doe"), h("span", null, "johndoe@example.com")), this.itemsModel != null && this.itemsModel.map(this.renderItem), h("div", { slot: "footer" }, "Footer"))));
46
+ }
47
+ };
48
+ ChTestDropdownX.style = testDropdownCss;
49
+
50
+ export { ChTestDropdownX as ch_test_dropdown };
@@ -1,14 +1,16 @@
1
1
  import { r as registerInstance, c as createEvent, h, H as Host, g as getElement } from './index-0da01575.js';
2
2
  import { C as CH_GLOBAL_STYLESHEET } from './ch-global-stylesheet-f8bbf095.js';
3
3
 
4
- const chWindowCss = ":host{--ch-window-offset-x:0px;--ch-window-offset-y:0px}:host(:not([hidden])){display:contents}:host(:is(:not([modal]),[modal=\"false\"])) .mask{pointer-events:none}.window{pointer-events:all}.mask{display:flex;position:fixed;inset:0;inset-inline-start:calc( var(--ch-window-inset-inline-start) + var(--ch-window-offset-x) );inset-block-start:calc( var(--ch-window-inset-block-start) + var(--ch-window-offset-y) );z-index:var(--ch-window-mask-z-index, 1000)}:host(:is([x-align=\"outside-start\"],[x-align=\"inside-start\"])) .mask{justify-content:flex-start}:host([x-align=center]) .mask{justify-content:center}:host(:is([x-align=\"outside-end\"],[x-align=\"inside-end\"])) .mask{justify-content:flex-end}:host(:is([y-align=\"outside-start\"],[y-align=\"inside-start\"])) .mask{align-items:flex-start}:host([y-align=center]) .mask{align-items:center}:host(:is([y-align=\"outside-end\"],[y-align=\"inside-end\"])) .mask{align-items:flex-end}.window{display:flex;flex-direction:column;transform:translate(var(--ch-window-x-outside, 0px), var(--ch-window-y-outside, 0px)) translate(var(--ch-window-x-drag, 0px), var(--ch-window-y-drag, 0px))}:host([x-align=outside-start]) .window{--ch-window-x-outside:-100%}:host([x-align=outside-end]) .window{--ch-window-x-outside:100%}:host([y-align=outside-start]) .window{--ch-window-y-outside:-100%}:host([y-align=outside-end]) .window{--ch-window-y-outside:100%}";
4
+ const chWindowCss = ":host{--ch-window-offset-x:0px;--ch-window-offset-y:0px;--ch-window-x-outside:0px;--ch-window-y-outside:0px}:host(:not([hidden])){display:contents}:host(:is(:not([modal]),[modal=\"false\"])) .mask{pointer-events:none}.window{pointer-events:all}.mask{display:flex;position:fixed;inset:0;inset-inline-start:calc( var(--ch-window-inset-inline-start) + var(--ch-window-offset-x) );inset-block-start:calc( var(--ch-window-inset-block-start) + var(--ch-window-offset-y) );z-index:var(--ch-window-mask-z-index, 1000)}:host(:is([x-align=\"outside-start\"],[x-align=\"inside-start\"])) .mask{justify-content:flex-start}:host([x-align=center]) .mask{justify-content:center}:host(:is([x-align=\"outside-end\"],[x-align=\"inside-end\"])) .mask{justify-content:flex-end}:host(:is([y-align=\"outside-start\"],[y-align=\"inside-start\"])) .mask{align-items:flex-start}:host([y-align=center]) .mask{align-items:center}:host(:is([y-align=\"outside-end\"],[y-align=\"inside-end\"])) .mask{align-items:flex-end}.window{display:flex;flex-direction:column;transform:translate(var(--ch-window-x-outside), var(--ch-window-y-outside)) translate(var(--ch-window-x-drag, 0px), var(--ch-window-y-drag, 0px))}:host([x-align=outside-start]) .window{--ch-window-x-outside:-100%}:host([x-align=outside-end]) .window{--ch-window-x-outside:100%}:host([y-align=outside-start]) .window{--ch-window-y-outside:-100%}:host([y-align=outside-end]) .window{--ch-window-y-outside:100%}";
5
5
 
6
+ const CONTAINING_BLOCK_RESET_CUSTOM_VAR = "--ch-window-relative-position";
6
7
  const ChWindow = class {
7
8
  constructor(hostRef) {
8
9
  registerInstance(this, hostRef);
9
10
  this.windowOpened = createEvent(this, "windowOpened", 7);
10
11
  this.windowClosed = createEvent(this, "windowClosed", 7);
11
12
  this.isContainerCssOverride = false;
13
+ this.relativeWindow = false;
12
14
  this.validCssAligns = [
13
15
  "outside-start",
14
16
  "inside-start",
@@ -56,17 +58,25 @@ const ChWindow = class {
56
58
  this.updatePosition = () => {
57
59
  if (!this.isContainerCssOverride && this.container && this.mask) {
58
60
  const rect = this.container.getBoundingClientRect();
61
+ this.mask.style.width = `${rect.width}px`;
62
+ this.mask.style.height = `${rect.height}px`;
63
+ // Nested windows are positioned relative to its initial containing block,
64
+ // so there is no need to align them relative to the document
65
+ if (this.relativeWindow) {
66
+ return;
67
+ }
59
68
  // TODO: RTL positioning bug
60
69
  this.mask.style.setProperty("--ch-window-inset-inline-start", `${rect.left}px`);
61
70
  this.mask.style.setProperty("--ch-window-inset-block-start", `${rect.top}px`);
62
- this.mask.style.width = `${rect.width}px`;
63
- this.mask.style.height = `${rect.height}px`;
64
71
  }
65
72
  else if (this.isContainerCssOverride || !this.container) {
66
- this.mask.style.removeProperty("--ch-window-inset-inline-start");
67
- this.mask.style.removeProperty("--ch-window-inset-block-start");
68
73
  this.mask.style.removeProperty("width");
69
74
  this.mask.style.removeProperty("height");
75
+ if (this.relativeWindow) {
76
+ return;
77
+ }
78
+ this.mask.style.removeProperty("--ch-window-inset-inline-start");
79
+ this.mask.style.removeProperty("--ch-window-inset-block-start");
70
80
  }
71
81
  };
72
82
  this.windowResizeHandler = () => {
@@ -88,6 +98,7 @@ const ChWindow = class {
88
98
  };
89
99
  }
90
100
  containerHandler(value, oldValue) {
101
+ this.checkRelativePosition();
91
102
  this.containerResizeObserverHandler(value, oldValue);
92
103
  this.updatePosition();
93
104
  }
@@ -98,6 +109,7 @@ const ChWindow = class {
98
109
  this.windowClosed.emit();
99
110
  }
100
111
  else {
112
+ this.checkRelativePosition();
101
113
  this.updatePosition();
102
114
  this.watchCSSAlign();
103
115
  this.addListeners();
@@ -125,6 +137,10 @@ const ChWindow = class {
125
137
  windowCloseClickedHandler() {
126
138
  this.hidden = true;
127
139
  }
140
+ checkRelativePosition() {
141
+ const computed = getComputedStyle(this.el);
142
+ this.relativeWindow = !!computed.getPropertyValue(CONTAINING_BLOCK_RESET_CUSTOM_VAR);
143
+ }
128
144
  resetDrag() {
129
145
  this.dragStartX = undefined;
130
146
  this.dragStartY = undefined;
@@ -200,7 +216,10 @@ const ChWindow = class {
200
216
  this.el.shadowRoot.adoptedStyleSheets.push(CH_GLOBAL_STYLESHEET);
201
217
  }
202
218
  render() {
203
- return (h(Host, null, h("div", { class: "mask", part: "mask", ref: el => (this.mask = el), onClick: this.maskClickHandler }, h("section", { class: "window", part: "window", ref: el => (this.window = el) }, this.showHeader && (h("header", { part: "header", ref: el => (this.header = el) }, h("slot", { name: "header" }, h("span", { part: "caption" }, this.caption), h("ch-window-close", { part: "close", title: this.closeTooltip }, this.closeText)))), h("div", { part: "main" }, h("slot", null)), this.showFooter && (h("footer", { part: "footer" }, h("slot", { name: "footer" })))))));
219
+ return (h(Host, null, h("div", { class: "mask", part: "mask", style: this.relativeWindow && {
220
+ "--ch-window-inset-inline-start": "0px",
221
+ "--ch-window-inset-block-start": "0px"
222
+ }, ref: el => (this.mask = el), onClick: this.maskClickHandler }, h("section", { class: "window", part: "window", ref: el => (this.window = el) }, this.showHeader && (h("header", { part: "header", ref: el => (this.header = el) }, h("slot", { name: "header" }, h("span", { part: "caption" }, this.caption), h("ch-window-close", { part: "close", title: this.closeTooltip }, this.closeText)))), h("div", { part: "main" }, h("slot", null)), this.showFooter && (h("footer", { part: "footer" }, h("slot", { name: "footer" })))))));
204
223
  }
205
224
  get el() { return getElement(this); }
206
225
  static get watchers() { return {