@umbraco-ui/uui 2.0.0-alpha.1 → 2.0.0-rc.0

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 (96) hide show
  1. package/custom-elements.json +45 -8
  2. package/dist/components/avatar/avatar.element.js +1 -0
  3. package/dist/components/avatar/avatar.element.js.map +1 -1
  4. package/dist/components/boolean-input/boolean-input.element.js +7 -1
  5. package/dist/components/boolean-input/boolean-input.element.js.map +1 -1
  6. package/dist/components/button/button.element.d.ts +0 -1
  7. package/dist/components/button/button.element.js +64 -18
  8. package/dist/components/button/button.element.js.map +1 -1
  9. package/dist/components/card-block-type/card-block-type.element.js +13 -4
  10. package/dist/components/card-block-type/card-block-type.element.js.map +1 -1
  11. package/dist/components/card-content-node/card-content-node.element.js +2 -2
  12. package/dist/components/card-content-node/card-content-node.element.js.map +1 -1
  13. package/dist/components/card-media/card-media.element.js +10 -3
  14. package/dist/components/card-media/card-media.element.js.map +1 -1
  15. package/dist/components/card-user/card-user.element.js +2 -2
  16. package/dist/components/card-user/card-user.element.js.map +1 -1
  17. package/dist/components/checkbox/checkbox.element.js +3 -6
  18. package/dist/components/checkbox/checkbox.element.js.map +1 -1
  19. package/dist/components/color-slider/color-slider.element.js +13 -3
  20. package/dist/components/color-slider/color-slider.element.js.map +1 -1
  21. package/dist/components/color-swatch/color-swatch.element.js +33 -1
  22. package/dist/components/color-swatch/color-swatch.element.js.map +1 -1
  23. package/dist/components/combobox/combobox.element.d.ts +9 -0
  24. package/dist/components/combobox/combobox.element.js +127 -15
  25. package/dist/components/combobox/combobox.element.js.map +1 -1
  26. package/dist/components/combobox-list/combobox-list-option.element.d.ts +1 -0
  27. package/dist/components/combobox-list/combobox-list-option.element.js +49 -10
  28. package/dist/components/combobox-list/combobox-list-option.element.js.map +1 -1
  29. package/dist/components/combobox-list/combobox-list.element.d.ts +14 -0
  30. package/dist/components/combobox-list/combobox-list.element.js +74 -25
  31. package/dist/components/combobox-list/combobox-list.element.js.map +1 -1
  32. package/dist/components/file-dropzone/file-dropzone.element.d.ts +2 -8
  33. package/dist/components/file-dropzone/file-dropzone.element.js +14 -25
  34. package/dist/components/file-dropzone/file-dropzone.element.js.map +1 -1
  35. package/dist/components/icon-registry-essential/UUIIconRegistryEssential.js +1 -1
  36. package/dist/components/icon-registry-essential/icon-registry-essential.js +33 -0
  37. package/dist/components/icon-registry-essential/icon-registry-essential.js.map +1 -1
  38. package/dist/components/index.d.ts +81 -0
  39. package/dist/components/input/input.element.js +33 -3
  40. package/dist/components/input/input.element.js.map +1 -1
  41. package/dist/components/input-file/input-file.element.js +33 -1
  42. package/dist/components/input-file/input-file.element.js.map +1 -1
  43. package/dist/components/input-lock/input-lock.element.js +33 -4
  44. package/dist/components/input-lock/input-lock.element.js.map +1 -1
  45. package/dist/components/input-password/input-password.element.js +33 -3
  46. package/dist/components/input-password/input-password.element.js.map +1 -1
  47. package/dist/components/keyboard-shortcut/key.element.js +7 -1
  48. package/dist/components/keyboard-shortcut/key.element.js.map +1 -1
  49. package/dist/components/loader/loader.element.js +19 -2
  50. package/dist/components/loader/loader.element.js.map +1 -1
  51. package/dist/components/modal/modal-container.js +6 -2
  52. package/dist/components/modal/modal-container.js.map +1 -1
  53. package/dist/components/modal/modal-dialog.element.js +5 -5
  54. package/dist/components/modal/modal-dialog.element.js.map +1 -1
  55. package/dist/components/modal/modal-sidebar.element.js +14 -10
  56. package/dist/components/modal/modal-sidebar.element.js.map +1 -1
  57. package/dist/components/modal/modal-with-toasts-example.element.d.ts +22 -0
  58. package/dist/components/modal/modal.element.d.ts +3 -1
  59. package/dist/components/modal/modal.element.js +31 -12
  60. package/dist/components/modal/modal.element.js.map +1 -1
  61. package/dist/components/modal/modal.js +7 -1
  62. package/dist/components/modal/modal.js.map +1 -1
  63. package/dist/components/pagination/pagination.element.d.ts +2 -0
  64. package/dist/components/pagination/pagination.element.js +26 -20
  65. package/dist/components/pagination/pagination.element.js.map +1 -1
  66. package/dist/components/progress-bar/progress-bar.element.js +6 -5
  67. package/dist/components/progress-bar/progress-bar.element.js.map +1 -1
  68. package/dist/components/responsive-container/responsive-container.element.js +36 -14
  69. package/dist/components/responsive-container/responsive-container.element.js.map +1 -1
  70. package/dist/components/scroll-container/scroll-container.element.js +4 -4
  71. package/dist/components/scroll-container/scroll-container.element.js.map +1 -1
  72. package/dist/components/symbol-expand/symbol-expand.element.js +1 -1
  73. package/dist/components/symbol-expand/symbol-expand.element.js.map +1 -1
  74. package/dist/components/symbol-file-thumbnail/symbol-file-thumbnail.element.js +34 -1
  75. package/dist/components/symbol-file-thumbnail/symbol-file-thumbnail.element.js.map +1 -1
  76. package/dist/components/table/table-head.element.js +4 -0
  77. package/dist/components/table/table-head.element.js.map +1 -1
  78. package/dist/components/table/table.element.js +5 -1
  79. package/dist/components/table/table.element.js.map +1 -1
  80. package/dist/components/tag/tag.element.js +4 -3
  81. package/dist/components/tag/tag.element.js.map +1 -1
  82. package/dist/components/toast-notification/toast-notification.element.js +34 -2
  83. package/dist/components/toast-notification/toast-notification.element.js.map +1 -1
  84. package/dist/components/toggle/toggle.element.js +38 -3
  85. package/dist/components/toggle/toggle.element.js.map +1 -1
  86. package/dist/index.d.ts +1 -81
  87. package/dist/internal/mixins/LabelMixin.js +14 -1
  88. package/dist/internal/mixins/LabelMixin.js.map +1 -1
  89. package/dist/internal/mixins/SelectOnlyMixin.d.ts +1 -1
  90. package/dist/internal/mixins/SelectOnlyMixin.js.map +1 -1
  91. package/dist/package.json.js +1 -1
  92. package/dist/themes/dark.css +1 -1
  93. package/dist/themes/high-contrast.css +1 -1
  94. package/dist/themes/light.css +1 -1
  95. package/package.json +26 -26
  96. package/vscode.html-custom-data.json +33 -18
@@ -24,33 +24,53 @@ const _UUIComboboxListElement = class _UUIComboboxListElement extends LitElement
24
24
  super(...arguments);
25
25
  __privateAdd(this, _UUIComboboxListElement_instances);
26
26
  this.displayValue = "";
27
+ this.multiple = false;
27
28
  this._value = "";
28
29
  this._activeElementValue = null;
30
+ this._selectedValues = [];
31
+ this._selectedElements = [];
29
32
  this._onSlotChange = () => {
30
33
  __privateMethod(this, _UUIComboboxListElement_instances, updateActiveElement_fn).call(this);
34
+ for (const option of this._options) {
35
+ option.multiple = this.multiple;
36
+ }
31
37
  this._updateSelection();
32
38
  this.dispatchEvent(
33
39
  new UUIComboboxListEvent(UUIComboboxListEvent.INNER_SLOT_CHANGE)
34
40
  );
35
41
  };
36
42
  this._onSelected = (e) => {
37
- if (this._selectedElement) {
38
- this._selectedElement.selected = false;
39
- this._selectedElement.active = false;
40
- this._selectedElement = void 0;
43
+ const option = e.composedPath()[0];
44
+ if (this.multiple) {
45
+ option.deselectable = true;
46
+ this._selectedElements.push(option);
47
+ this._selectedValues = [...this._selectedValues, option.value || ""];
48
+ } else {
49
+ if (this._selectedElement) {
50
+ this._selectedElement.selected = false;
51
+ this._selectedElement.active = false;
52
+ this._selectedElement = void 0;
53
+ }
54
+ this._selectedElement = option;
55
+ this.value = option.value || "";
56
+ this.displayValue = option.displayValue || "";
41
57
  }
42
- this._selectedElement = e.composedPath()[0];
43
- this.value = this._selectedElement.value || "";
44
- this.displayValue = this._selectedElement.displayValue || "";
45
58
  this.dispatchEvent(new UUIComboboxListEvent(UUIComboboxListEvent.CHANGE));
46
59
  };
47
60
  this._onDeselected = (e) => {
48
61
  const el = e.composedPath()[0];
49
- if (this._selectedElement === el) {
50
- this.value = "";
51
- this.displayValue = "";
52
- this.dispatchEvent(new UUIComboboxListEvent(UUIComboboxListEvent.CHANGE));
62
+ if (this.multiple) {
63
+ this._selectedElements = this._selectedElements.filter((opt) => opt !== el);
64
+ this._selectedValues = this._selectedValues.filter(
65
+ (v) => v !== (el.value || "")
66
+ );
67
+ } else {
68
+ if (this._selectedElement === el) {
69
+ this.value = "";
70
+ this.displayValue = "";
71
+ }
53
72
  }
73
+ this.dispatchEvent(new UUIComboboxListEvent(UUIComboboxListEvent.CHANGE));
54
74
  };
55
75
  this._moveIndex = (distance) => {
56
76
  const newIndex = Math.min(
@@ -88,13 +108,6 @@ const _UUIComboboxListElement = class _UUIComboboxListElement extends LitElement
88
108
  this._getActiveElement?.click();
89
109
  break;
90
110
  }
91
- //Space key
92
- case "Space": {
93
- e.preventDefault();
94
- e.stopPropagation();
95
- this._getActiveElement?.click();
96
- break;
97
- }
98
111
  case "End": {
99
112
  e.preventDefault();
100
113
  this._goToIndex(this._options.length - 1);
@@ -125,6 +138,20 @@ const _UUIComboboxListElement = class _UUIComboboxListElement extends LitElement
125
138
  this._for.addEventListener("keydown", this._onKeyDown);
126
139
  }
127
140
  }
141
+ /**
142
+ * Array of selected option values. Only relevant when multiple is true.
143
+ * @type {string[]}
144
+ */
145
+ get selectedValues() {
146
+ return this._selectedValues;
147
+ }
148
+ /**
149
+ * Array of display values for selected options. Only relevant when multiple is true.
150
+ * @type {string[]}
151
+ */
152
+ get selectedDisplayValues() {
153
+ return this._selectedElements.map((el) => el.displayValue || el.value || "");
154
+ }
128
155
  connectedCallback() {
129
156
  super.connectedCallback();
130
157
  this._for ??= this;
@@ -138,16 +165,32 @@ const _UUIComboboxListElement = class _UUIComboboxListElement extends LitElement
138
165
  this.removeEventListener(UUISelectableEvent.DESELECTED, this._onDeselected);
139
166
  }
140
167
  _updateSelection() {
141
- this.displayValue = "";
142
- for (const option of this._options) {
143
- if (option.value === this._value) {
144
- this.displayValue = option.displayValue || "";
145
- option.selected = true;
146
- } else {
147
- option.selected = false;
168
+ if (this.multiple) {
169
+ for (const option of this._options) {
170
+ if (this._selectedValues.includes(option.value)) {
171
+ option.selected = true;
172
+ option.deselectable = true;
173
+ }
174
+ }
175
+ this._selectedElements = this._options.filter(
176
+ (opt) => this._selectedValues.includes(opt.value)
177
+ );
178
+ } else {
179
+ this.displayValue = "";
180
+ for (const option of this._options) {
181
+ if (option.value === this._value) {
182
+ this.displayValue = option.displayValue || "";
183
+ option.selected = true;
184
+ } else {
185
+ option.selected = false;
186
+ }
148
187
  }
149
188
  }
150
189
  }
190
+ resetSelection() {
191
+ this._selectedValues = [];
192
+ this._selectedElements = [];
193
+ }
151
194
  get _getActiveIndex() {
152
195
  if (this._activeElementValue === null) return -1;
153
196
  return this._options.findIndex(
@@ -206,6 +249,9 @@ __decorateClass([
206
249
  __decorateClass([
207
250
  property({ type: String })
208
251
  ], UUIComboboxListElement.prototype, "displayValue", 2);
252
+ __decorateClass([
253
+ property({ type: Boolean, reflect: true })
254
+ ], UUIComboboxListElement.prototype, "multiple", 2);
209
255
  __decorateClass([
210
256
  property({ attribute: false })
211
257
  ], UUIComboboxListElement.prototype, "for", 1);
@@ -227,6 +273,9 @@ __decorateClass([
227
273
  __decorateClass([
228
274
  state()
229
275
  ], UUIComboboxListElement.prototype, "_activeElementValue", 2);
276
+ __decorateClass([
277
+ state()
278
+ ], UUIComboboxListElement.prototype, "_selectedValues", 2);
230
279
  export {
231
280
  UUIComboboxListElement
232
281
  };
@@ -1 +1 @@
1
- {"version":3,"file":"combobox-list.element.js","sources":["../../../src/components/combobox-list/combobox-list.element.ts"],"sourcesContent":["import { css, html, LitElement } from 'lit';\nimport { property, queryAssignedElements, state } from 'lit/decorators.js';\nimport { UUISelectableEvent } from '../../internal/events/index.js';\nimport type { UUIComboboxListOptionElement } from './combobox-list-option.element.js';\nimport { UUIComboboxListEvent } from './UUIComboboxListEvent.js';\n\n/**\n * @element uui-combobox-list\n * @fires {UUIComboboxListEvent} change - fires when selection is changed\n * @slot - for uui-combobox-list-options\n * @description - A list that uses uui-combobox-list-options and handles keyboard navigation and selection.\n */\nexport class UUIComboboxListElement extends LitElement {\n /**\n * Value of selected option.\n * @type {FormDataEntryValue | FormData}\n * @attr\n * @default \"\"\n */\n @property()\n public get value() {\n return this._value;\n }\n public set value(newValue) {\n if (this._value === newValue) return;\n\n const oldValue = this._value;\n this._value = newValue;\n\n this._updateSelection();\n this.requestUpdate('value', oldValue);\n }\n\n /**\n * A readable value to display to show the selected value.\n * @type {string}\n * @attr\n * @default \"\"\n */\n @property({ type: String })\n public displayValue = '';\n\n private _for?: HTMLElement;\n /**\n * provide another element of which keyboard navigation\n * @type {HTMLElement}\n * @attr\n * @default this\n */\n @property({ attribute: false })\n public get for() {\n return this._for;\n }\n public set for(newValue: HTMLElement | undefined) {\n if (this._for) {\n this._for.removeEventListener('keydown', this._onKeyDown);\n }\n\n this._for = newValue;\n if (this._for) {\n this._for.addEventListener('keydown', this._onKeyDown);\n }\n }\n\n @queryAssignedElements({\n flatten: true,\n selector: 'uui-combobox-list-option:not([disabled])',\n })\n private readonly _options!: UUIComboboxListOptionElement[];\n\n @queryAssignedElements({\n flatten: true,\n selector: 'uui-combobox-list-option[active]',\n })\n private readonly _activeOptions!: UUIComboboxListOptionElement[];\n\n @state()\n private _value: FormDataEntryValue | FormData = '';\n\n @state()\n private _activeElementValue: string | null = null;\n\n private _selectedElement: UUIComboboxListOptionElement | undefined;\n\n connectedCallback(): void {\n super.connectedCallback();\n\n this._for ??= this;\n\n this.addEventListener(UUISelectableEvent.SELECTED, this._onSelected);\n this.addEventListener(UUISelectableEvent.DESELECTED, this._onDeselected);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n document.removeEventListener('keydown', this._onKeyDown);\n\n this.removeEventListener(UUISelectableEvent.SELECTED, this._onSelected);\n this.removeEventListener(UUISelectableEvent.DESELECTED, this._onDeselected);\n }\n\n private _updateSelection() {\n this.displayValue = '';\n\n // Ensure the right items are selected.\n for (const option of this._options) {\n if (option.value === this._value) {\n this.displayValue = option.displayValue || '';\n option.selected = true;\n } else {\n option.selected = false;\n }\n }\n }\n\n private readonly _onSlotChange = () => {\n // Get index from first active, remove active from the rest.\n this.#updateActiveElement();\n\n this._updateSelection();\n this.dispatchEvent(\n new UUIComboboxListEvent(UUIComboboxListEvent.INNER_SLOT_CHANGE),\n );\n };\n\n #updateActiveElement() {\n for (const option of this._activeOptions) {\n option.active = false;\n }\n\n const activeElement = this._getActiveElement;\n if (activeElement) {\n activeElement.active = true;\n } else {\n this._goToIndex(0);\n }\n }\n\n private readonly _onSelected = (e: Event) => {\n if (this._selectedElement) {\n this._selectedElement.selected = false;\n this._selectedElement.active = false;\n this._selectedElement = undefined;\n }\n this._selectedElement = e.composedPath()[0] as UUIComboboxListOptionElement;\n\n this.value = this._selectedElement.value || '';\n this.displayValue = this._selectedElement.displayValue || '';\n\n this.dispatchEvent(new UUIComboboxListEvent(UUIComboboxListEvent.CHANGE));\n };\n private readonly _onDeselected = (e: Event) => {\n const el = e.composedPath()[0] as UUIComboboxListOptionElement;\n if (this._selectedElement === el) {\n this.value = '';\n this.displayValue = '';\n this.dispatchEvent(new UUIComboboxListEvent(UUIComboboxListEvent.CHANGE));\n }\n };\n\n private get _getActiveIndex(): number {\n if (this._activeElementValue === null) return -1;\n\n return this._options.findIndex(\n element => element.value === this._activeElementValue,\n );\n }\n\n private get _getActiveElement() {\n if (this._activeElementValue === null) return null;\n\n return this._options.find(\n element => element.value === this._activeElementValue,\n );\n }\n\n private readonly _moveIndex = (distance: number) => {\n const newIndex = Math.min(\n Math.max(this._getActiveIndex + distance, 0),\n this._options.length - 1,\n );\n\n this._goToIndex(newIndex);\n };\n\n private _goToIndex(index: number) {\n if (this._options.length === 0) return;\n\n index = Math.min(Math.max(index, 0), this._options.length - 1); // Makes sure the index stays within array length\n const activeElement = this._options[index];\n this._activeElementValue = activeElement.value;\n this.#updateActiveElement();\n\n if (activeElement) {\n activeElement.scrollIntoView({\n behavior: 'auto',\n block: 'nearest',\n inline: 'nearest',\n });\n }\n }\n\n private readonly _onKeyDown = (e: KeyboardEvent) => {\n if (this._options.length <= 0) return;\n\n switch (e.code) {\n case 'ArrowUp':\n e.preventDefault();\n if (e.ctrlKey) {\n this._moveIndex(-10);\n } else {\n this._moveIndex(-1);\n }\n break;\n\n case 'ArrowDown':\n e.preventDefault();\n if (e.ctrlKey) {\n this._moveIndex(10);\n } else {\n this._moveIndex(1);\n }\n\n break;\n\n case 'Home': {\n e.preventDefault();\n this._goToIndex(0);\n break;\n }\n\n case 'Enter': {\n e.preventDefault();\n this._getActiveElement?.click();\n break;\n }\n\n //Space key\n case 'Space': {\n e.preventDefault();\n e.stopPropagation();\n this._getActiveElement?.click();\n break;\n }\n\n case 'End': {\n e.preventDefault();\n this._goToIndex(this._options.length - 1);\n break;\n }\n\n default:\n break;\n }\n };\n\n render() {\n return html` <slot @slotchange=${this._onSlotChange}></slot> `;\n }\n\n static override readonly styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n }\n `,\n ];\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"combobox-list.element.js","sources":["../../../src/components/combobox-list/combobox-list.element.ts"],"sourcesContent":["import { css, html, LitElement } from 'lit';\nimport { property, queryAssignedElements, state } from 'lit/decorators.js';\nimport { UUISelectableEvent } from '../../internal/events/index.js';\nimport type { UUIComboboxListOptionElement } from './combobox-list-option.element.js';\nimport { UUIComboboxListEvent } from './UUIComboboxListEvent.js';\n\n/**\n * @element uui-combobox-list\n * @fires {UUIComboboxListEvent} change - fires when selection is changed\n * @slot - for uui-combobox-list-options\n * @description - A list that uses uui-combobox-list-options and handles keyboard navigation and selection.\n */\nexport class UUIComboboxListElement extends LitElement {\n /**\n * Value of selected option.\n * @type {FormDataEntryValue | FormData}\n * @attr\n * @default \"\"\n */\n @property()\n public get value() {\n return this._value;\n }\n public set value(newValue) {\n if (this._value === newValue) return;\n\n const oldValue = this._value;\n this._value = newValue;\n\n this._updateSelection();\n this.requestUpdate('value', oldValue);\n }\n\n /**\n * A readable value to display to show the selected value.\n * @type {string}\n * @attr\n * @default \"\"\n */\n @property({ type: String })\n public displayValue = '';\n\n @property({ type: Boolean, reflect: true })\n multiple = false;\n\n private _for?: HTMLElement;\n /**\n * provide another element of which keyboard navigation\n * @type {HTMLElement}\n * @attr\n * @default this\n */\n @property({ attribute: false })\n public get for() {\n return this._for;\n }\n public set for(newValue: HTMLElement | undefined) {\n if (this._for) {\n this._for.removeEventListener('keydown', this._onKeyDown);\n }\n\n this._for = newValue;\n if (this._for) {\n this._for.addEventListener('keydown', this._onKeyDown);\n }\n }\n\n @queryAssignedElements({\n flatten: true,\n selector: 'uui-combobox-list-option:not([disabled])',\n })\n private readonly _options!: UUIComboboxListOptionElement[];\n\n @queryAssignedElements({\n flatten: true,\n selector: 'uui-combobox-list-option[active]',\n })\n private readonly _activeOptions!: UUIComboboxListOptionElement[];\n\n @state()\n private _value: FormDataEntryValue | FormData = '';\n\n @state()\n private _activeElementValue: string | null = null;\n\n private _selectedElement: UUIComboboxListOptionElement | undefined;\n\n @state()\n private _selectedValues: string[] = [];\n private _selectedElements: UUIComboboxListOptionElement[] = [];\n /**\n * Array of selected option values. Only relevant when multiple is true.\n * @type {string[]}\n */\n public get selectedValues(): string[] {\n return this._selectedValues;\n }\n\n /**\n * Array of display values for selected options. Only relevant when multiple is true.\n * @type {string[]}\n */\n public get selectedDisplayValues(): string[] {\n return this._selectedElements.map(el => el.displayValue || el.value || '');\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n\n this._for ??= this;\n\n this.addEventListener(UUISelectableEvent.SELECTED, this._onSelected);\n this.addEventListener(UUISelectableEvent.DESELECTED, this._onDeselected);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n document.removeEventListener('keydown', this._onKeyDown);\n\n this.removeEventListener(UUISelectableEvent.SELECTED, this._onSelected);\n this.removeEventListener(UUISelectableEvent.DESELECTED, this._onDeselected);\n }\n\n private _updateSelection() {\n if (this.multiple) {\n for (const option of this._options) {\n if (this._selectedValues.includes(option.value)) {\n option.selected = true;\n option.deselectable = true;\n }\n }\n this._selectedElements = this._options.filter(opt =>\n this._selectedValues.includes(opt.value),\n );\n } else {\n this.displayValue = '';\n for (const option of this._options) {\n if (option.value === this._value) {\n this.displayValue = option.displayValue || '';\n option.selected = true;\n } else {\n option.selected = false;\n }\n }\n }\n }\n\n private readonly _onSlotChange = () => {\n // Get index from first active, remove active from the rest.\n this.#updateActiveElement();\n\n for (const option of this._options) {\n option.multiple = this.multiple;\n }\n\n this._updateSelection();\n this.dispatchEvent(\n new UUIComboboxListEvent(UUIComboboxListEvent.INNER_SLOT_CHANGE),\n );\n };\n\n #updateActiveElement() {\n for (const option of this._activeOptions) {\n option.active = false;\n }\n\n const activeElement = this._getActiveElement;\n if (activeElement) {\n activeElement.active = true;\n } else {\n this._goToIndex(0);\n }\n }\n\n private readonly _onSelected = (e: Event) => {\n const option = e.composedPath()[0] as UUIComboboxListOptionElement;\n\n if (this.multiple) {\n // Allow this option to be toggled off on next click\n option.deselectable = true;\n // Add to array\n this._selectedElements.push(option);\n this._selectedValues = [...this._selectedValues, option.value || ''];\n } else {\n // Existing single-select logic\n if (this._selectedElement) {\n this._selectedElement.selected = false;\n this._selectedElement.active = false;\n this._selectedElement = undefined;\n }\n this._selectedElement = option;\n this.value = option.value || '';\n this.displayValue = option.displayValue || '';\n }\n\n this.dispatchEvent(new UUIComboboxListEvent(UUIComboboxListEvent.CHANGE));\n };\n\n private readonly _onDeselected = (e: Event) => {\n const el = e.composedPath()[0] as UUIComboboxListOptionElement;\n if (this.multiple) {\n // Remove from arrays\n this._selectedElements = this._selectedElements.filter(opt => opt !== el);\n this._selectedValues = this._selectedValues.filter(\n v => v !== (el.value || ''),\n );\n } else {\n // Existing single-select logic\n if (this._selectedElement === el) {\n this.value = '';\n this.displayValue = '';\n }\n }\n\n this.dispatchEvent(new UUIComboboxListEvent(UUIComboboxListEvent.CHANGE));\n };\n\n public resetSelection() {\n this._selectedValues = [];\n this._selectedElements = [];\n }\n\n private get _getActiveIndex(): number {\n if (this._activeElementValue === null) return -1;\n\n return this._options.findIndex(\n element => element.value === this._activeElementValue,\n );\n }\n\n private get _getActiveElement() {\n if (this._activeElementValue === null) return null;\n\n return this._options.find(\n element => element.value === this._activeElementValue,\n );\n }\n\n private readonly _moveIndex = (distance: number) => {\n const newIndex = Math.min(\n Math.max(this._getActiveIndex + distance, 0),\n this._options.length - 1,\n );\n\n this._goToIndex(newIndex);\n };\n\n private _goToIndex(index: number) {\n if (this._options.length === 0) return;\n\n index = Math.min(Math.max(index, 0), this._options.length - 1); // Makes sure the index stays within array length\n const activeElement = this._options[index];\n this._activeElementValue = activeElement.value;\n this.#updateActiveElement();\n\n if (activeElement) {\n activeElement.scrollIntoView({\n behavior: 'auto',\n block: 'nearest',\n inline: 'nearest',\n });\n }\n }\n\n private readonly _onKeyDown = (e: KeyboardEvent) => {\n if (this._options.length <= 0) return;\n\n switch (e.code) {\n case 'ArrowUp':\n e.preventDefault();\n if (e.ctrlKey) {\n this._moveIndex(-10);\n } else {\n this._moveIndex(-1);\n }\n break;\n\n case 'ArrowDown':\n e.preventDefault();\n if (e.ctrlKey) {\n this._moveIndex(10);\n } else {\n this._moveIndex(1);\n }\n\n break;\n\n case 'Home': {\n e.preventDefault();\n this._goToIndex(0);\n break;\n }\n\n case 'Enter': {\n e.preventDefault();\n this._getActiveElement?.click();\n break;\n }\n\n case 'End': {\n e.preventDefault();\n this._goToIndex(this._options.length - 1);\n break;\n }\n\n default:\n break;\n }\n };\n\n render() {\n return html` <slot @slotchange=${this._onSlotChange}></slot> `;\n }\n\n static override readonly styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n }\n `,\n ];\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAYO,MAAM,0BAAN,MAAM,gCAA+B,WAAW;AAAA,EAAhD,cAAA;AAAA,UAAA,GAAA,SAAA;AAAA;AA4BL,SAAO,eAAe;AAGtB,SAAA,WAAW;AAqCX,SAAQ,SAAwC;AAGhD,SAAQ,sBAAqC;AAK7C,SAAQ,kBAA4B,CAAA;AACpC,SAAQ,oBAAoD,CAAA;AA0D5D,SAAiB,gBAAgB,MAAM;AAErC,4BAAK,2DAAL;AAEA,iBAAW,UAAU,KAAK,UAAU;AAClC,eAAO,WAAW,KAAK;AAAA,MACzB;AAEA,WAAK,iBAAA;AACL,WAAK;AAAA,QACH,IAAI,qBAAqB,qBAAqB,iBAAiB;AAAA,MAAA;AAAA,IAEnE;AAeA,SAAiB,cAAc,CAAC,MAAa;AAC3C,YAAM,SAAS,EAAE,aAAA,EAAe,CAAC;AAEjC,UAAI,KAAK,UAAU;AAEjB,eAAO,eAAe;AAEtB,aAAK,kBAAkB,KAAK,MAAM;AAClC,aAAK,kBAAkB,CAAC,GAAG,KAAK,iBAAiB,OAAO,SAAS,EAAE;AAAA,MACrE,OAAO;AAEL,YAAI,KAAK,kBAAkB;AACzB,eAAK,iBAAiB,WAAW;AACjC,eAAK,iBAAiB,SAAS;AAC/B,eAAK,mBAAmB;AAAA,QAC1B;AACA,aAAK,mBAAmB;AACxB,aAAK,QAAQ,OAAO,SAAS;AAC7B,aAAK,eAAe,OAAO,gBAAgB;AAAA,MAC7C;AAEA,WAAK,cAAc,IAAI,qBAAqB,qBAAqB,MAAM,CAAC;AAAA,IAC1E;AAEA,SAAiB,gBAAgB,CAAC,MAAa;AAC7C,YAAM,KAAK,EAAE,aAAA,EAAe,CAAC;AAC7B,UAAI,KAAK,UAAU;AAEjB,aAAK,oBAAoB,KAAK,kBAAkB,OAAO,CAAA,QAAO,QAAQ,EAAE;AACxE,aAAK,kBAAkB,KAAK,gBAAgB;AAAA,UAC1C,CAAA,MAAK,OAAO,GAAG,SAAS;AAAA,QAAA;AAAA,MAE5B,OAAO;AAEL,YAAI,KAAK,qBAAqB,IAAI;AAChC,eAAK,QAAQ;AACb,eAAK,eAAe;AAAA,QACtB;AAAA,MACF;AAEA,WAAK,cAAc,IAAI,qBAAqB,qBAAqB,MAAM,CAAC;AAAA,IAC1E;AAuBA,SAAiB,aAAa,CAAC,aAAqB;AAClD,YAAM,WAAW,KAAK;AAAA,QACpB,KAAK,IAAI,KAAK,kBAAkB,UAAU,CAAC;AAAA,QAC3C,KAAK,SAAS,SAAS;AAAA,MAAA;AAGzB,WAAK,WAAW,QAAQ;AAAA,IAC1B;AAmBA,SAAiB,aAAa,CAAC,MAAqB;AAClD,UAAI,KAAK,SAAS,UAAU,EAAG;AAE/B,cAAQ,EAAE,MAAA;AAAA,QACR,KAAK;AACH,YAAE,eAAA;AACF,cAAI,EAAE,SAAS;AACb,iBAAK,WAAW,GAAG;AAAA,UACrB,OAAO;AACL,iBAAK,WAAW,EAAE;AAAA,UACpB;AACA;AAAA,QAEF,KAAK;AACH,YAAE,eAAA;AACF,cAAI,EAAE,SAAS;AACb,iBAAK,WAAW,EAAE;AAAA,UACpB,OAAO;AACL,iBAAK,WAAW,CAAC;AAAA,UACnB;AAEA;AAAA,QAEF,KAAK,QAAQ;AACX,YAAE,eAAA;AACF,eAAK,WAAW,CAAC;AACjB;AAAA,QACF;AAAA,QAEA,KAAK,SAAS;AACZ,YAAE,eAAA;AACF,eAAK,mBAAmB,MAAA;AACxB;AAAA,QACF;AAAA,QAEA,KAAK,OAAO;AACV,YAAE,eAAA;AACF,eAAK,WAAW,KAAK,SAAS,SAAS,CAAC;AACxC;AAAA,QACF;AAAA,MAGE;AAAA,IAEN;AAAA,EAAA;AAAA,EAhSA,IAAW,QAAQ;AACjB,WAAO,KAAK;AAAA,EACd;AAAA,EACA,IAAW,MAAM,UAAU;AACzB,QAAI,KAAK,WAAW,SAAU;AAE9B,UAAM,WAAW,KAAK;AACtB,SAAK,SAAS;AAEd,SAAK,iBAAA;AACL,SAAK,cAAc,SAAS,QAAQ;AAAA,EACtC;AAAA,EAsBA,IAAW,MAAM;AACf,WAAO,KAAK;AAAA,EACd;AAAA,EACA,IAAW,IAAI,UAAmC;AAChD,QAAI,KAAK,MAAM;AACb,WAAK,KAAK,oBAAoB,WAAW,KAAK,UAAU;AAAA,IAC1D;AAEA,SAAK,OAAO;AACZ,QAAI,KAAK,MAAM;AACb,WAAK,KAAK,iBAAiB,WAAW,KAAK,UAAU;AAAA,IACvD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EA6BA,IAAW,iBAA2B;AACpC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAW,wBAAkC;AAC3C,WAAO,KAAK,kBAAkB,IAAI,CAAA,OAAM,GAAG,gBAAgB,GAAG,SAAS,EAAE;AAAA,EAC3E;AAAA,EAEA,oBAA0B;AACxB,UAAM,kBAAA;AAEN,SAAK,SAAS;AAEd,SAAK,iBAAiB,mBAAmB,UAAU,KAAK,WAAW;AACnE,SAAK,iBAAiB,mBAAmB,YAAY,KAAK,aAAa;AAAA,EACzE;AAAA,EAEA,uBAA6B;AAC3B,UAAM,qBAAA;AACN,aAAS,oBAAoB,WAAW,KAAK,UAAU;AAEvD,SAAK,oBAAoB,mBAAmB,UAAU,KAAK,WAAW;AACtE,SAAK,oBAAoB,mBAAmB,YAAY,KAAK,aAAa;AAAA,EAC5E;AAAA,EAEQ,mBAAmB;AACzB,QAAI,KAAK,UAAU;AACjB,iBAAW,UAAU,KAAK,UAAU;AAClC,YAAI,KAAK,gBAAgB,SAAS,OAAO,KAAK,GAAG;AAC/C,iBAAO,WAAW;AAClB,iBAAO,eAAe;AAAA,QACxB;AAAA,MACF;AACA,WAAK,oBAAoB,KAAK,SAAS;AAAA,QAAO,CAAA,QAC5C,KAAK,gBAAgB,SAAS,IAAI,KAAK;AAAA,MAAA;AAAA,IAE3C,OAAO;AACL,WAAK,eAAe;AACpB,iBAAW,UAAU,KAAK,UAAU;AAClC,YAAI,OAAO,UAAU,KAAK,QAAQ;AAChC,eAAK,eAAe,OAAO,gBAAgB;AAC3C,iBAAO,WAAW;AAAA,QACpB,OAAO;AACL,iBAAO,WAAW;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAwEO,iBAAiB;AACtB,SAAK,kBAAkB,CAAA;AACvB,SAAK,oBAAoB,CAAA;AAAA,EAC3B;AAAA,EAEA,IAAY,kBAA0B;AACpC,QAAI,KAAK,wBAAwB,KAAM,QAAO;AAE9C,WAAO,KAAK,SAAS;AAAA,MACnB,CAAA,YAAW,QAAQ,UAAU,KAAK;AAAA,IAAA;AAAA,EAEtC;AAAA,EAEA,IAAY,oBAAoB;AAC9B,QAAI,KAAK,wBAAwB,KAAM,QAAO;AAE9C,WAAO,KAAK,SAAS;AAAA,MACnB,CAAA,YAAW,QAAQ,UAAU,KAAK;AAAA,IAAA;AAAA,EAEtC;AAAA,EAWQ,WAAW,OAAe;AAChC,QAAI,KAAK,SAAS,WAAW,EAAG;AAEhC,YAAQ,KAAK,IAAI,KAAK,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,SAAS,CAAC;AAC7D,UAAM,gBAAgB,KAAK,SAAS,KAAK;AACzC,SAAK,sBAAsB,cAAc;AACzC,0BAAK,2DAAL;AAEA,QAAI,eAAe;AACjB,oBAAc,eAAe;AAAA,QAC3B,UAAU;AAAA,QACV,OAAO;AAAA,QACP,QAAQ;AAAA,MAAA,CACT;AAAA,IACH;AAAA,EACF;AAAA,EAgDA,SAAS;AACP,WAAO,0BAA0B,KAAK,aAAa;AAAA,EACrD;AAWF;AAvTO;AAqJL,yBAAA,WAAuB;AACrB,aAAW,UAAU,KAAK,gBAAgB;AACxC,WAAO,SAAS;AAAA,EAClB;AAEA,QAAM,gBAAgB,KAAK;AAC3B,MAAI,eAAe;AACjB,kBAAc,SAAS;AAAA,EACzB,OAAO;AACL,SAAK,WAAW,CAAC;AAAA,EACnB;AACF;AA8IA,wBAAyB,SAAS;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA/SG,IAAM,yBAAN;AAQM,gBAAA;AAAA,EADV,SAAA;AAAS,GAPC,uBAQA,WAAA,SAAA,CAAA;AAoBJ,gBAAA;AAAA,EADN,SAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GA3Bf,uBA4BJ,WAAA,gBAAA,CAAA;AAGP,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,MAAM;AAAA,GA9B/B,uBA+BX,WAAA,YAAA,CAAA;AAUW,gBAAA;AAAA,EADV,SAAS,EAAE,WAAW,MAAA,CAAO;AAAA,GAxCnB,uBAyCA,WAAA,OAAA,CAAA;AAkBM,gBAAA;AAAA,EAJhB,sBAAsB;AAAA,IACrB,SAAS;AAAA,IACT,UAAU;AAAA,EAAA,CACX;AAAA,GA1DU,uBA2DM,WAAA,YAAA,CAAA;AAMA,gBAAA;AAAA,EAJhB,sBAAsB;AAAA,IACrB,SAAS;AAAA,IACT,UAAU;AAAA,EAAA,CACX;AAAA,GAhEU,uBAiEM,WAAA,kBAAA,CAAA;AAGT,gBAAA;AAAA,EADP,MAAA;AAAM,GAnEI,uBAoEH,WAAA,UAAA,CAAA;AAGA,gBAAA;AAAA,EADP,MAAA;AAAM,GAtEI,uBAuEH,WAAA,uBAAA,CAAA;AAKA,gBAAA;AAAA,EADP,MAAA;AAAM,GA3EI,uBA4EH,WAAA,mBAAA,CAAA;"}
@@ -46,21 +46,15 @@ export declare class UUIFileDropzoneElement extends UUIFileDropzoneElement_base
46
46
  */
47
47
  browse(): void;
48
48
  constructor();
49
- /**
50
- * Process a single file entry and categorize it as accepted or rejected.
51
- * @param entry - The data transfer item containing the file
52
- * @param files - Array to store accepted files
53
- * @param rejectedFiles - Array to store rejected files
54
- */
55
- private _processFileEntry;
56
49
  /**
57
50
  * Check if folder upload should be processed based on component settings.
58
51
  * @returns true if folder upload is allowed and multiple files are enabled
59
52
  */
60
53
  private _shouldProcessFolder;
61
54
  private _getAllEntries;
55
+ private _processRootEntries;
62
56
  /**
63
- * Get the directory entry from a DataTransferItem.
57
+ * Get the filesystem entry (file or directory) from a DataTransferItem.
64
58
  * @remark Supports both WebKit and non-WebKit browsers.
65
59
  */
66
60
  private _getEntry;
@@ -58,21 +58,6 @@ const _UUIFileDropzoneElement = class _UUIFileDropzoneElement extends LabelMixin
58
58
  browse() {
59
59
  this._input.click();
60
60
  }
61
- /**
62
- * Process a single file entry and categorize it as accepted or rejected.
63
- * @param entry - The data transfer item containing the file
64
- * @param files - Array to store accepted files
65
- * @param rejectedFiles - Array to store rejected files
66
- */
67
- _processFileEntry(entry, files, rejectedFiles) {
68
- const file = entry.getAsFile();
69
- if (!file) return;
70
- if (this._isAccepted(file)) {
71
- files.push(file);
72
- } else {
73
- rejectedFiles.push(file);
74
- }
75
- }
76
61
  /**
77
62
  * Check if folder upload should be processed based on component settings.
78
63
  * @returns true if folder upload is allowed and multiple files are enabled
@@ -81,25 +66,29 @@ const _UUIFileDropzoneElement = class _UUIFileDropzoneElement extends LabelMixin
81
66
  return !this.disallowFolderUpload && this.multiple;
82
67
  }
83
68
  async _getAllEntries(dataTransferItemList) {
84
- const queue = [...dataTransferItemList];
69
+ const rootEntries = [...dataTransferItemList].filter((item) => item?.kind === "file").map((item) => this._getEntry(item)).filter((entry) => entry !== null);
70
+ return this._processRootEntries(rootEntries);
71
+ }
72
+ async _processRootEntries(rootEntries) {
85
73
  const folders = [];
86
74
  const files = [];
87
75
  const rejectedFiles = [];
88
- for (const entry of queue) {
89
- if (entry?.kind !== "file") continue;
90
- const fileEntry = this._getEntry(entry);
91
- if (!fileEntry) continue;
92
- if (!fileEntry.isDirectory) {
93
- this._processFileEntry(entry, files, rejectedFiles);
76
+ for (const entry of rootEntries) {
77
+ if (!entry.isDirectory) {
78
+ const file = await this._getAsFile(entry);
79
+ if (this._isAccepted(file)) {
80
+ files.push(file);
81
+ } else {
82
+ rejectedFiles.push(file);
83
+ }
94
84
  } else if (this._shouldProcessFolder()) {
95
- const structure = await this._mkdir(fileEntry);
96
- folders.push(structure);
85
+ folders.push(await this._mkdir(entry));
97
86
  }
98
87
  }
99
88
  return { files, folders, rejectedFiles };
100
89
  }
101
90
  /**
102
- * Get the directory entry from a DataTransferItem.
91
+ * Get the filesystem entry (file or directory) from a DataTransferItem.
103
92
  * @remark Supports both WebKit and non-WebKit browsers.
104
93
  */
105
94
  _getEntry(entry) {
@@ -1 +1 @@
1
- {"version":3,"file":"file-dropzone.element.js","sources":["../../../src/components/file-dropzone/file-dropzone.element.ts"],"sourcesContent":["import { css, html, LitElement } from 'lit';\nimport { query, property } from 'lit/decorators.js';\nimport { UUIFileDropzoneEvent } from './UUIFileDropzoneEvent.js';\nimport { LabelMixin } from '../../internal/mixins/index.js';\n\nimport '../symbol-file-dropzone/symbol-file-dropzone.js';\n\nexport interface UUIFileFolder {\n folderName: string;\n folders: UUIFileFolder[];\n files: File[];\n}\n\n/**\n * @element uui-file-dropzone\n * @fires {UUIFileDropzoneEvent} change - fires when a file has been selected.\n * @fires {UUIFileDropzoneEvent} reject - fires when files are rejected due to not matching the accept attribute.\n * @slot - For the content of the dropzone\n * @description - Dropzone for file upload. Supports native browsing and drag n drop.\n */\nexport class UUIFileDropzoneElement extends LabelMixin('', LitElement) {\n @query('#input')\n private readonly _input!: HTMLInputElement;\n\n @query('#dropzone')\n private readonly _dropzone!: HTMLElement;\n\n private _acceptedFileExtensions: string[] = [];\n private _acceptedMimeTypes: string[] = [];\n private _accept = '';\n\n /**\n * Comma-separated list of accepted mime types or file extensions (denoted with a `.`).\n * If this is left empty, it will allow all types.\n *\n * @type {string}\n * @attr\n * @examples [\n * \"image/*,application/pdf\",\n * \".gif,.png,.jpg,.jpeg,.pdf\",\n * ]\n */\n @property({ type: String })\n public set accept(value: string) {\n if (value) {\n const mimetypes: string[] = [];\n const fileextensions: string[] = [];\n\n // Create the arrays defined above\n value.split(',').forEach(item => {\n item = item.trim().toLowerCase();\n\n // If the item is a mime type, add it to the accept list\n if (/^[a-z]+\\/[a-z*]+$/.test(item)) {\n mimetypes.push(item);\n } else {\n fileextensions.push(item.replace(/^\\./, ''));\n }\n });\n\n this._acceptedMimeTypes = mimetypes;\n this._acceptedFileExtensions = fileextensions;\n } else {\n this._acceptedMimeTypes = [];\n this._acceptedFileExtensions = [];\n }\n const old = this._accept;\n this._accept = value;\n this.requestUpdate('accept', old);\n }\n public get accept(): string {\n return this._accept;\n }\n\n @property({\n type: Boolean,\n reflect: true,\n attribute: 'disallow-folder-upload',\n })\n public disallowFolderUpload: boolean = false;\n\n /**\n * Allows for multiple files to be selected.\n * @type {boolean}\n * @attr\n * @default false\n */\n @property({ type: Boolean })\n public multiple: boolean = false;\n\n /**\n * Opens the native file picker to select a file.\n * @method browse\n */\n public browse() {\n this._input.click();\n }\n\n constructor() {\n super();\n\n this.addEventListener('dragenter', this._onDragEnter, false);\n this.addEventListener('dragleave', this._onDragLeave, false);\n this.addEventListener('dragover', this._onDragOver, false);\n this.addEventListener('drop', this._onDrop, false);\n }\n\n /**\n * Process a single file entry and categorize it as accepted or rejected.\n * @param entry - The data transfer item containing the file\n * @param files - Array to store accepted files\n * @param rejectedFiles - Array to store rejected files\n */\n private _processFileEntry(\n entry: DataTransferItem,\n files: File[],\n rejectedFiles: File[],\n ): void {\n const file = entry.getAsFile();\n if (!file) return;\n\n if (this._isAccepted(file)) {\n files.push(file);\n } else {\n rejectedFiles.push(file);\n }\n }\n\n /**\n * Check if folder upload should be processed based on component settings.\n * @returns true if folder upload is allowed and multiple files are enabled\n */\n private _shouldProcessFolder(): boolean {\n return !this.disallowFolderUpload && this.multiple;\n }\n\n private async _getAllEntries(dataTransferItemList: DataTransferItemList) {\n // Use BFS to traverse entire directory/file structure\n const queue = [...dataTransferItemList];\n\n const folders: UUIFileFolder[] = [];\n const files: File[] = [];\n const rejectedFiles: File[] = [];\n\n for (const entry of queue) {\n if (entry?.kind !== 'file') continue;\n\n const fileEntry = this._getEntry(entry);\n if (!fileEntry) continue;\n\n if (!fileEntry.isDirectory) {\n // Entry is a file\n this._processFileEntry(entry, files, rejectedFiles);\n } else if (this._shouldProcessFolder()) {\n // Entry is a directory\n const structure = await this._mkdir(fileEntry);\n folders.push(structure);\n }\n }\n\n return { files, folders, rejectedFiles };\n }\n\n /**\n * Get the directory entry from a DataTransferItem.\n * @remark Supports both WebKit and non-WebKit browsers.\n */\n private _getEntry(entry: DataTransferItem): FileSystemDirectoryEntry | null {\n let dir: FileSystemDirectoryEntry | null = null;\n\n if ('webkitGetAsEntry' in entry) {\n dir = entry.webkitGetAsEntry() as FileSystemDirectoryEntry;\n } else if ('getAsEntry' in entry) {\n // non-WebKit browsers may rename webkitGetAsEntry to getAsEntry. MDN recommends looking for both.\n dir = (entry as any).getAsEntry();\n }\n\n return dir;\n }\n\n // Process entries from a directory reader\n private async _processEntries(\n entries: FileSystemEntry[],\n folders: UUIFileFolder[],\n files: File[],\n ): Promise<void> {\n for (const en of entries) {\n if (en.isFile) {\n const file = await this._getAsFile(en as FileSystemFileEntry);\n if (this._isAccepted(file)) {\n files.push(file);\n }\n } else if (en.isDirectory) {\n const directory = await this._mkdir(en as FileSystemDirectoryEntry);\n folders.push(directory);\n }\n }\n }\n\n // Read entries from a directory reader recursively\n private async _readAllEntries(\n reader: FileSystemDirectoryReader,\n folders: UUIFileFolder[],\n files: File[],\n ): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n reader.readEntries(async entries => {\n if (!entries.length) {\n resolve();\n return;\n }\n\n await this._processEntries(entries, folders, files);\n\n // readEntries only reads up to 100 entries at a time. It is on purpose we call readEntries recursively.\n await this._readAllEntries(reader, folders, files);\n\n resolve();\n }, reject);\n });\n }\n\n // Make directory structure\n private async _mkdir(\n entry: FileSystemDirectoryEntry,\n ): Promise<UUIFileFolder> {\n const reader = entry.createReader();\n const folders: UUIFileFolder[] = [];\n const files: File[] = [];\n\n await this._readAllEntries(reader, folders, files);\n\n const result: UUIFileFolder = { folderName: entry.name, folders, files };\n return result;\n }\n\n private _isAccepted(file: File) {\n if (\n this._acceptedFileExtensions.length === 0 &&\n this._acceptedMimeTypes.length === 0\n ) {\n return true;\n }\n\n const fileType = file.type.toLowerCase();\n const fileExtension = file.name.split('.').pop();\n\n if (\n fileExtension &&\n this._acceptedFileExtensions.includes(fileExtension.toLowerCase())\n ) {\n return true;\n }\n\n for (const mimeType of this._acceptedMimeTypes) {\n if (\n fileType === mimeType ||\n (mimeType.endsWith('/*') &&\n fileType.startsWith(mimeType.replace('*', '')))\n ) {\n return true;\n }\n }\n\n return false;\n }\n\n private async _getAsFile(fileEntry: FileSystemFileEntry): Promise<File> {\n return new Promise((resolve, reject) => fileEntry.file(resolve, reject));\n }\n\n private async _onDrop(e: DragEvent) {\n e.preventDefault();\n this._dropzone.classList.remove('hover');\n\n const items = e.dataTransfer?.items;\n\n if (items) {\n const fileSystemResult = await this._getAllEntries(items);\n\n if (this.multiple === false && fileSystemResult.files.length) {\n fileSystemResult.files = [fileSystemResult.files[0]];\n fileSystemResult.folders = [];\n // When multiple is false and we have an accepted file, don't report rejections\n fileSystemResult.rejectedFiles = [];\n }\n\n if (fileSystemResult.rejectedFiles.length > 0) {\n this.dispatchEvent(\n new UUIFileDropzoneEvent(UUIFileDropzoneEvent.REJECT, {\n detail: { files: fileSystemResult.rejectedFiles, folders: [] },\n }),\n );\n }\n\n if (!fileSystemResult.files.length && !fileSystemResult.folders.length) {\n return;\n }\n\n this.dispatchEvent(\n new UUIFileDropzoneEvent(UUIFileDropzoneEvent.CHANGE, {\n detail: {\n files: fileSystemResult.files,\n folders: fileSystemResult.folders,\n },\n }),\n );\n }\n }\n\n private _onDragOver(e: DragEvent) {\n e.preventDefault();\n }\n\n private _onDragEnter(e: DragEvent) {\n // TODO: make visual indication of wether the file is acceptable or not. If not we need to make a more negative/disabled visual look.\n this._dropzone.classList.add('hover');\n e.preventDefault();\n }\n\n private _onDragLeave(e: DragEvent) {\n this._dropzone.classList.remove('hover');\n e.preventDefault();\n }\n\n private _onFileInputChange() {\n const files = this._input.files ? Array.from(this._input.files) : [];\n\n if (this.multiple === false && files.length > 1) {\n files.splice(1, files.length - 1);\n }\n\n const allowedFiles = files.filter(file => this._isAccepted(file));\n const rejectedFiles = files.filter(file => !this._isAccepted(file));\n\n // When multiple is false and we have an accepted file, don't report rejections\n const shouldReportRejections =\n rejectedFiles.length > 0 && (this.multiple || allowedFiles.length === 0);\n\n if (shouldReportRejections) {\n this.dispatchEvent(\n new UUIFileDropzoneEvent(UUIFileDropzoneEvent.REJECT, {\n detail: { files: rejectedFiles, folders: [] },\n }),\n );\n }\n\n if (!allowedFiles.length) {\n return;\n }\n\n this.dispatchEvent(\n new UUIFileDropzoneEvent(UUIFileDropzoneEvent.CHANGE, {\n detail: {\n files: allowedFiles,\n folders: [],\n },\n }),\n );\n }\n\n render() {\n return html`\n <div id=\"dropzone\">\n <uui-symbol-file-dropzone id=\"symbol\"></uui-symbol-file-dropzone>\n ${this.renderLabel()}\n <input\n @click=${(e: Event) => e.stopImmediatePropagation()}\n id=\"input\"\n type=\"file\"\n accept=${this.accept}\n ?multiple=${this.multiple}\n @change=${this._onFileInputChange}\n aria-label=\"${this.label}\" />\n <slot></slot>\n </div>\n `;\n }\n\n static override readonly styles = [\n css`\n #dropzone {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n position: relative;\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n padding: var(--uui-size-4);\n border: 3px solid transparent;\n margin: -3px;\n backdrop-filter: blur(2px);\n }\n #dropzone.hover {\n border-color: var(--uui-color-default);\n }\n #dropzone.hover::before {\n content: '';\n position: absolute;\n inset: 0;\n opacity: 0.2;\n border-color: var(--uui-color-default);\n background-color: var(--uui-color-default);\n }\n #symbol {\n color: var(--uui-color-default);\n max-width: 100%;\n max-height: 100%;\n }\n #input {\n position: absolute;\n width: 0px;\n height: 0px;\n opacity: 0;\n display: none;\n }\n `,\n ];\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file-dropzone.element.js","sources":["../../../src/components/file-dropzone/file-dropzone.element.ts"],"sourcesContent":["import { css, html, LitElement } from 'lit';\nimport { query, property } from 'lit/decorators.js';\nimport { UUIFileDropzoneEvent } from './UUIFileDropzoneEvent.js';\nimport { LabelMixin } from '../../internal/mixins/index.js';\n\nimport '../symbol-file-dropzone/symbol-file-dropzone.js';\n\nexport interface UUIFileFolder {\n folderName: string;\n folders: UUIFileFolder[];\n files: File[];\n}\n\n/**\n * @element uui-file-dropzone\n * @fires {UUIFileDropzoneEvent} change - fires when a file has been selected.\n * @fires {UUIFileDropzoneEvent} reject - fires when files are rejected due to not matching the accept attribute.\n * @slot - For the content of the dropzone\n * @description - Dropzone for file upload. Supports native browsing and drag n drop.\n */\nexport class UUIFileDropzoneElement extends LabelMixin('', LitElement) {\n @query('#input')\n private readonly _input!: HTMLInputElement;\n\n @query('#dropzone')\n private readonly _dropzone!: HTMLElement;\n\n private _acceptedFileExtensions: string[] = [];\n private _acceptedMimeTypes: string[] = [];\n private _accept = '';\n\n /**\n * Comma-separated list of accepted mime types or file extensions (denoted with a `.`).\n * If this is left empty, it will allow all types.\n *\n * @type {string}\n * @attr\n * @examples [\n * \"image/*,application/pdf\",\n * \".gif,.png,.jpg,.jpeg,.pdf\",\n * ]\n */\n @property({ type: String })\n public set accept(value: string) {\n if (value) {\n const mimetypes: string[] = [];\n const fileextensions: string[] = [];\n\n // Create the arrays defined above\n value.split(',').forEach(item => {\n item = item.trim().toLowerCase();\n\n // If the item is a mime type, add it to the accept list\n if (/^[a-z]+\\/[a-z*]+$/.test(item)) {\n mimetypes.push(item);\n } else {\n fileextensions.push(item.replace(/^\\./, ''));\n }\n });\n\n this._acceptedMimeTypes = mimetypes;\n this._acceptedFileExtensions = fileextensions;\n } else {\n this._acceptedMimeTypes = [];\n this._acceptedFileExtensions = [];\n }\n const old = this._accept;\n this._accept = value;\n this.requestUpdate('accept', old);\n }\n public get accept(): string {\n return this._accept;\n }\n\n @property({\n type: Boolean,\n reflect: true,\n attribute: 'disallow-folder-upload',\n })\n public disallowFolderUpload: boolean = false;\n\n /**\n * Allows for multiple files to be selected.\n * @type {boolean}\n * @attr\n * @default false\n */\n @property({ type: Boolean })\n public multiple: boolean = false;\n\n /**\n * Opens the native file picker to select a file.\n * @method browse\n */\n public browse() {\n this._input.click();\n }\n\n constructor() {\n super();\n\n this.addEventListener('dragenter', this._onDragEnter, false);\n this.addEventListener('dragleave', this._onDragLeave, false);\n this.addEventListener('dragover', this._onDragOver, false);\n this.addEventListener('drop', this._onDrop, false);\n }\n\n /**\n * Check if folder upload should be processed based on component settings.\n * @returns true if folder upload is allowed and multiple files are enabled\n */\n private _shouldProcessFolder(): boolean {\n return !this.disallowFolderUpload && this.multiple;\n }\n\n private async _getAllEntries(dataTransferItemList: DataTransferItemList) {\n // Phase 1: Extract ALL FileSystemEntry refs synchronously.\n // DataTransferItem.webkitGetAsEntry() returns null after the first await\n // because the browser expires the drag data store. FileSystemEntry objects\n // obtained here remain valid indefinitely.\n const rootEntries = [...dataTransferItemList]\n .filter(item => item?.kind === 'file')\n .map(item => this._getEntry(item))\n .filter((entry): entry is FileSystemEntry => entry !== null);\n\n return this._processRootEntries(rootEntries);\n }\n\n private async _processRootEntries(rootEntries: FileSystemEntry[]) {\n const folders: UUIFileFolder[] = [];\n const files: File[] = [];\n const rejectedFiles: File[] = [];\n\n for (const entry of rootEntries) {\n if (!entry.isDirectory) {\n const file = await this._getAsFile(entry as FileSystemFileEntry);\n if (this._isAccepted(file)) {\n files.push(file);\n } else {\n rejectedFiles.push(file);\n }\n } else if (this._shouldProcessFolder()) {\n folders.push(await this._mkdir(entry as FileSystemDirectoryEntry));\n }\n }\n\n return { files, folders, rejectedFiles };\n }\n\n /**\n * Get the filesystem entry (file or directory) from a DataTransferItem.\n * @remark Supports both WebKit and non-WebKit browsers.\n */\n private _getEntry(entry: DataTransferItem): FileSystemEntry | null {\n let dir: FileSystemDirectoryEntry | null = null;\n\n if ('webkitGetAsEntry' in entry) {\n dir = entry.webkitGetAsEntry() as FileSystemDirectoryEntry;\n } else if ('getAsEntry' in entry) {\n // non-WebKit browsers may rename webkitGetAsEntry to getAsEntry. MDN recommends looking for both.\n dir = (entry as any).getAsEntry();\n }\n\n return dir;\n }\n\n // Process entries from a directory reader\n private async _processEntries(\n entries: FileSystemEntry[],\n folders: UUIFileFolder[],\n files: File[],\n ): Promise<void> {\n for (const en of entries) {\n if (en.isFile) {\n const file = await this._getAsFile(en as FileSystemFileEntry);\n if (this._isAccepted(file)) {\n files.push(file);\n }\n } else if (en.isDirectory) {\n const directory = await this._mkdir(en as FileSystemDirectoryEntry);\n folders.push(directory);\n }\n }\n }\n\n // Read entries from a directory reader recursively\n private async _readAllEntries(\n reader: FileSystemDirectoryReader,\n folders: UUIFileFolder[],\n files: File[],\n ): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n reader.readEntries(async entries => {\n if (!entries.length) {\n resolve();\n return;\n }\n\n await this._processEntries(entries, folders, files);\n\n // readEntries only reads up to 100 entries at a time. It is on purpose we call readEntries recursively.\n await this._readAllEntries(reader, folders, files);\n\n resolve();\n }, reject);\n });\n }\n\n // Make directory structure\n private async _mkdir(\n entry: FileSystemDirectoryEntry,\n ): Promise<UUIFileFolder> {\n const reader = entry.createReader();\n const folders: UUIFileFolder[] = [];\n const files: File[] = [];\n\n await this._readAllEntries(reader, folders, files);\n\n const result: UUIFileFolder = { folderName: entry.name, folders, files };\n return result;\n }\n\n private _isAccepted(file: File) {\n if (\n this._acceptedFileExtensions.length === 0 &&\n this._acceptedMimeTypes.length === 0\n ) {\n return true;\n }\n\n const fileType = file.type.toLowerCase();\n const fileExtension = file.name.split('.').pop();\n\n if (\n fileExtension &&\n this._acceptedFileExtensions.includes(fileExtension.toLowerCase())\n ) {\n return true;\n }\n\n for (const mimeType of this._acceptedMimeTypes) {\n if (\n fileType === mimeType ||\n (mimeType.endsWith('/*') &&\n fileType.startsWith(mimeType.replace('*', '')))\n ) {\n return true;\n }\n }\n\n return false;\n }\n\n private async _getAsFile(fileEntry: FileSystemFileEntry): Promise<File> {\n return new Promise((resolve, reject) => fileEntry.file(resolve, reject));\n }\n\n private async _onDrop(e: DragEvent) {\n e.preventDefault();\n this._dropzone.classList.remove('hover');\n\n const items = e.dataTransfer?.items;\n\n if (items) {\n const fileSystemResult = await this._getAllEntries(items);\n\n if (this.multiple === false && fileSystemResult.files.length) {\n fileSystemResult.files = [fileSystemResult.files[0]];\n fileSystemResult.folders = [];\n // When multiple is false and we have an accepted file, don't report rejections\n fileSystemResult.rejectedFiles = [];\n }\n\n if (fileSystemResult.rejectedFiles.length > 0) {\n this.dispatchEvent(\n new UUIFileDropzoneEvent(UUIFileDropzoneEvent.REJECT, {\n detail: { files: fileSystemResult.rejectedFiles, folders: [] },\n }),\n );\n }\n\n if (!fileSystemResult.files.length && !fileSystemResult.folders.length) {\n return;\n }\n\n this.dispatchEvent(\n new UUIFileDropzoneEvent(UUIFileDropzoneEvent.CHANGE, {\n detail: {\n files: fileSystemResult.files,\n folders: fileSystemResult.folders,\n },\n }),\n );\n }\n }\n\n private _onDragOver(e: DragEvent) {\n e.preventDefault();\n }\n\n private _onDragEnter(e: DragEvent) {\n // TODO: make visual indication of wether the file is acceptable or not. If not we need to make a more negative/disabled visual look.\n this._dropzone.classList.add('hover');\n e.preventDefault();\n }\n\n private _onDragLeave(e: DragEvent) {\n this._dropzone.classList.remove('hover');\n e.preventDefault();\n }\n\n private _onFileInputChange() {\n const files = this._input.files ? Array.from(this._input.files) : [];\n\n if (this.multiple === false && files.length > 1) {\n files.splice(1, files.length - 1);\n }\n\n const allowedFiles = files.filter(file => this._isAccepted(file));\n const rejectedFiles = files.filter(file => !this._isAccepted(file));\n\n // When multiple is false and we have an accepted file, don't report rejections\n const shouldReportRejections =\n rejectedFiles.length > 0 && (this.multiple || allowedFiles.length === 0);\n\n if (shouldReportRejections) {\n this.dispatchEvent(\n new UUIFileDropzoneEvent(UUIFileDropzoneEvent.REJECT, {\n detail: { files: rejectedFiles, folders: [] },\n }),\n );\n }\n\n if (!allowedFiles.length) {\n return;\n }\n\n this.dispatchEvent(\n new UUIFileDropzoneEvent(UUIFileDropzoneEvent.CHANGE, {\n detail: {\n files: allowedFiles,\n folders: [],\n },\n }),\n );\n }\n\n render() {\n return html`\n <div id=\"dropzone\">\n <uui-symbol-file-dropzone id=\"symbol\"></uui-symbol-file-dropzone>\n ${this.renderLabel()}\n <input\n @click=${(e: Event) => e.stopImmediatePropagation()}\n id=\"input\"\n type=\"file\"\n accept=${this.accept}\n ?multiple=${this.multiple}\n @change=${this._onFileInputChange}\n aria-label=\"${this.label}\" />\n <slot></slot>\n </div>\n `;\n }\n\n static override readonly styles = [\n css`\n #dropzone {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n position: relative;\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n padding: var(--uui-size-4);\n border: 3px solid transparent;\n margin: -3px;\n backdrop-filter: blur(2px);\n }\n #dropzone.hover {\n border-color: var(--uui-color-default);\n }\n #dropzone.hover::before {\n content: '';\n position: absolute;\n inset: 0;\n opacity: 0.2;\n border-color: var(--uui-color-default);\n background-color: var(--uui-color-default);\n }\n #symbol {\n color: var(--uui-color-default);\n max-width: 100%;\n max-height: 100%;\n }\n #input {\n position: absolute;\n width: 0px;\n height: 0px;\n opacity: 0;\n display: none;\n }\n `,\n ];\n}\n"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@ import { iconAdd } from "./svgs/iconAdd.js";
3
3
  import { iconAlert } from "./svgs/iconAlert.js";
4
4
  import { iconAttachment } from "./svgs/iconAttachment.js";
5
5
  import { iconCalendar } from "./svgs/iconCalendar.js";
6
+ import { iconCheck } from "./svgs/iconCheck.js";
6
7
  import { iconClipboard } from "./svgs/iconClipboard.js";
7
8
  import { iconCode } from "./svgs/iconCode.js";
8
9
  import { iconColorPicker } from "./svgs/iconColorPicker.js";
@@ -30,7 +31,6 @@ import { iconSync } from "./svgs/iconSync.js";
30
31
  import { iconUnlock } from "./svgs/iconUnlock.js";
31
32
  import { iconUnsee } from "./svgs/iconUnsee.js";
32
33
  import { iconWand } from "./svgs/iconWand.js";
33
- import { iconCheck } from "./svgs/iconCheck.js";
34
34
  import { iconWrong } from "./svgs/iconWrong.js";
35
35
  class UUIIconRegistryEssential extends UUIIconRegistry {
36
36
  constructor() {
@@ -1,6 +1,39 @@
1
1
  import { defineElement } from "../../internal/registration/index.js";
2
2
  import { UUIIconRegistryEssentialElement } from "./icon-registry-essential.element.js";
3
3
  import "../icon/UUIIconRequestEvent.js";
4
+ import "./svgs/iconAdd.js";
5
+ import "./svgs/iconAlert.js";
6
+ import "./svgs/iconAttachment.js";
7
+ import "./svgs/iconCalendar.js";
8
+ import "./svgs/iconCheck.js";
9
+ import "./svgs/iconClipboard.js";
10
+ import "./svgs/iconCode.js";
11
+ import "./svgs/iconColorPicker.js";
12
+ import "./svgs/iconCopy.js";
13
+ import "./svgs/iconDelete.js";
14
+ import "./svgs/iconDocument.js";
15
+ import "./svgs/iconDownload.js";
16
+ import "./svgs/iconDrag.js";
17
+ import "./svgs/iconEdit.js";
18
+ import "./svgs/iconFavorite.js";
19
+ import "./svgs/iconFolder.js";
20
+ import "./svgs/iconForbidden.js";
21
+ import "./svgs/iconInfo.js";
22
+ import "./svgs/iconLink.js";
23
+ import "./svgs/iconLock.js";
24
+ import "./svgs/iconPause.js";
25
+ import "./svgs/iconPicture.js";
26
+ import "./svgs/iconPlay.js";
27
+ import "./svgs/iconRemove.js";
28
+ import "./svgs/iconSearch.js";
29
+ import "./svgs/iconSee.js";
30
+ import "./svgs/iconSettings.js";
31
+ import "./svgs/iconSubtract.js";
32
+ import "./svgs/iconSync.js";
33
+ import "./svgs/iconUnlock.js";
34
+ import "./svgs/iconUnsee.js";
35
+ import "./svgs/iconWand.js";
36
+ import "./svgs/iconWrong.js";
4
37
  defineElement("uui-icon-registry-essential", UUIIconRegistryEssentialElement);
5
38
  export {
6
39
  UUIIconRegistryEssentialElement,
@@ -1 +1 @@
1
- {"version":3,"file":"icon-registry-essential.js","sources":["../../../src/components/icon-registry-essential/icon-registry-essential.ts"],"sourcesContent":["import { defineElement } from '../../internal/registration/index.js';\nimport { UUIIconRegistryEssentialElement } from './icon-registry-essential.element.js';\n\ndefineElement('uui-icon-registry-essential', UUIIconRegistryEssentialElement);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'uui-icon-registry-essential': UUIIconRegistryEssentialElement;\n }\n}\n\nexport * from './icon-registry-essential.element.js';\nexport * from './UUIIconRegistryEssential.js';\nexport { UUIIconRegistryEssentialElement as default } from './icon-registry-essential.element.js';\n"],"names":[],"mappings":";;;AAGA,cAAc,+BAA+B,+BAA+B;"}
1
+ {"version":3,"file":"icon-registry-essential.js","sources":["../../../src/components/icon-registry-essential/icon-registry-essential.ts"],"sourcesContent":["import { defineElement } from '../../internal/registration/index.js';\nimport { UUIIconRegistryEssentialElement } from './icon-registry-essential.element.js';\n\ndefineElement('uui-icon-registry-essential', UUIIconRegistryEssentialElement);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'uui-icon-registry-essential': UUIIconRegistryEssentialElement;\n }\n}\n\nexport * from './icon-registry-essential.element.js';\nexport * from './UUIIconRegistryEssential.js';\nexport { UUIIconRegistryEssentialElement as default } from './icon-registry-essential.element.js';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,cAAc,+BAA+B,+BAA+B;"}
@@ -0,0 +1,81 @@
1
+ export * from './button/button.js';
2
+ export * from './badge/badge.js';
3
+ export * from './icon/icon.js';
4
+ export * from './icon-registry/icon-registry.js';
5
+ export * from './icon-registry-essential/icon-registry-essential.js';
6
+ export * from './input/input.js';
7
+ export * from './input-password/input-password.js';
8
+ export * from './dialog/dialog.js';
9
+ export * from './dialog-layout/dialog-layout.js';
10
+ export * from './table/table.js';
11
+ export * from './label/label.js';
12
+ export * from './action-bar/action-bar.js';
13
+ export * from './avatar/avatar.js';
14
+ export * from './boolean-input/boolean-input.js';
15
+ export * from './breadcrumbs/breadcrumbs.js';
16
+ export * from './checkbox/checkbox.js';
17
+ export * from './color-area/color-area.js';
18
+ export * from './color-slider/color-slider.js';
19
+ export * from './color-swatch/color-swatch.js';
20
+ export * from './form/form.js';
21
+ export * from './form-layout-item/form-layout-item.js';
22
+ export * from './form-validation-message/form-validation-message.js';
23
+ export * from './keyboard-shortcut/keyboard-shortcut.js';
24
+ export * from './loader/loader.js';
25
+ export * from './loader-bar/loader-bar.js';
26
+ export * from './loader-circle/loader-circle.js';
27
+ export * from './modal/modal.js';
28
+ export * from './popover-container/popover-container.js';
29
+ export * from './progress-bar/progress-bar.js';
30
+ export * from './radio/radio.js';
31
+ export * from './range-slider/range-slider.js';
32
+ export * from './responsive-container/responsive-container.js';
33
+ export * from './scroll-container/scroll-container.js';
34
+ export * from './select/select.js';
35
+ export * from './slider/slider.js';
36
+ export * from './symbol-drag-handle/symbol-drag-handle.js';
37
+ export * from './symbol-expand/symbol-expand.js';
38
+ export * from './symbol-file/symbol-file.js';
39
+ export * from './symbol-folder/symbol-folder.js';
40
+ export * from './symbol-lock/symbol-lock.js';
41
+ export * from './symbol-more/symbol-more.js';
42
+ export * from './symbol-sort/symbol-sort.js';
43
+ export * from './tag/tag.js';
44
+ export * from './textarea/textarea.js';
45
+ export * from './toggle/toggle.js';
46
+ export * from './visually-hidden/visually-hidden.js';
47
+ export * from './box/box.js';
48
+ export * from './card/card.js';
49
+ export * from './avatar-group/avatar-group.js';
50
+ export * from './button-group/button-group.js';
51
+ export * from './button-inline-create/button-inline-create.js';
52
+ export * from './button-copy-text/button-copy-text.js';
53
+ export * from './color-swatches/color-swatches.js';
54
+ export * from './combobox-list/combobox-list.js';
55
+ export * from './menu-item/menu-item.js';
56
+ export * from './ref/ref.js';
57
+ export * from './symbol-file-dropzone/symbol-file-dropzone.js';
58
+ export * from './tabs/tabs.js';
59
+ export * from './toast-notification/toast-notification.js';
60
+ export * from './card-block-type/card-block-type.js';
61
+ export * from './card-content-node/card-content-node.js';
62
+ export * from './card-media/card-media.js';
63
+ export * from './card-user/card-user.js';
64
+ export * from './ref-list/ref-list.js';
65
+ export * from './ref-node/ref-node.js';
66
+ export * from './symbol-file-thumbnail/symbol-file-thumbnail.js';
67
+ export * from './toast-notification-container/toast-notification-container.js';
68
+ export * from './toast-notification-layout/toast-notification-layout.js';
69
+ export * from './input-lock/input-lock.js';
70
+ export * from './pagination/pagination.js';
71
+ export * from './ref-node-data-type/ref-node-data-type.js';
72
+ export * from './ref-node-document-type/ref-node-document-type.js';
73
+ export * from './ref-node-form/ref-node-form.js';
74
+ export * from './ref-node-member/ref-node-member.js';
75
+ export * from './ref-node-package/ref-node-package.js';
76
+ export * from './ref-node-user/ref-node-user.js';
77
+ export * from './file-dropzone/file-dropzone.js';
78
+ export * from './file-preview/file-preview.js';
79
+ export * from './input-file/input-file.js';
80
+ export * from './combobox/combobox.js';
81
+ export * from './color-picker/color-picker.js';
@@ -115,7 +115,10 @@ const _UUIInputElement = class _UUIInputElement extends UUIFormControlWithBasics
115
115
  render() {
116
116
  return html`
117
117
  ${this.renderPrepend()}
118
- ${this.autoWidth ? this.renderInputWithAutoWidth() : this.renderInput()}
118
+ <div id="inner">
119
+ <slot></slot>
120
+ ${this.autoWidth ? this.renderInputWithAutoWidth() : this.renderInput()}
121
+ </div>
119
122
  ${this.renderAppend()}
120
123
  `;
121
124
  }
@@ -138,7 +141,12 @@ const _UUIInputElement = class _UUIInputElement extends UUIFormControlWithBasics
138
141
  spellcheck=${this.spellcheck}
139
142
  autocomplete=${ifDefined(this.autocomplete)}
140
143
  placeholder=${ifDefined(this.placeholder)}
141
- aria-label=${ifDefined(this.label)}
144
+ aria-label=${ifDefined(
145
+ this.getAttribute("aria-label") || this.label || void 0
146
+ )}
147
+ aria-labelledby=${ifDefined(
148
+ this.getAttribute("aria-labelledby") || void 0
149
+ )}
142
150
  inputmode=${ifDefined(this.inputMode)}
143
151
  ?disabled=${this.disabled}
144
152
  ?autofocus=${this.autofocus}
@@ -182,7 +190,8 @@ _UUIInputElement.styles = [
182
190
  border-radius: var(--uui-input-border-radius, var(--uui-border-radius));
183
191
  min-width: 0;
184
192
 
185
- --uui-input-padding: 1px var(--uui-size-space-3);
193
+ --uui-input-padding: 1px var(--uui-size-space-3) 3px
194
+ var(--uui-size-space-3);
186
195
  --uui-button-height: 100%;
187
196
  --uui-button-border-radius: var(
188
197
  --uui-input-border-radius,
@@ -284,6 +293,9 @@ _UUIInputElement.styles = [
284
293
  text-align: inherit;
285
294
  outline: none;
286
295
  text-overflow: ellipsis;
296
+ line-height: 1;
297
+ flex: 1 1 auto;
298
+ min-width: 60px;
287
299
  }
288
300
 
289
301
  input[type='password']::-ms-reveal {
@@ -306,11 +318,29 @@ _UUIInputElement.styles = [
306
318
  min-width: 0;
307
319
  }
308
320
 
321
+ uui-input,
322
+ uui-input-lock,
309
323
  ::slotted(uui-input),
310
324
  ::slotted(uui-input-lock) {
311
325
  height: 100%;
312
326
  --uui-input-border-width: 0;
313
327
  }
328
+
329
+ uui-button,
330
+ ::slotted(uui-button) {
331
+ height: 100%;
332
+ --uui-button-border-width: 0;
333
+ }
334
+
335
+ #inner {
336
+ display: flex;
337
+ flex-wrap: wrap;
338
+ align-items: center;
339
+ gap: 4px;
340
+ flex: 1 1 auto;
341
+ min-width: 0;
342
+ padding: 2px;
343
+ }
314
344
  `
315
345
  ];
316
346
  let UUIInputElement = _UUIInputElement;