@kubex/zinc 1.0.113 → 1.0.115

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 (101) hide show
  1. package/.github/workflows/eleventy_build.yml +5 -5
  2. package/.github/workflows/js_build_and_deploy.yaml +1 -1
  3. package/dist/custom-elements.json +2422 -190
  4. package/dist/vscode.html-custom-data.json +86 -5
  5. package/dist/web-types.json +251 -9
  6. package/dist/zn.d.ts +518 -340
  7. package/dist/zn.min.css +1 -1
  8. package/dist/zn.min.js +960 -882
  9. package/docs/eleventy.config.cjs +4 -2
  10. package/docs/pages/components/header.md +13 -0
  11. package/docs/pages/components/inline-edit.md +20 -0
  12. package/docs/pages/components/item.md +12 -1
  13. package/docs/pages/components/page.md +149 -0
  14. package/docs/pages/components/progress-bar.md +16 -0
  15. package/docs/pages/components/select.md +25 -0
  16. package/docs/pages/components/split-pane.md +6 -7
  17. package/docs/pages/components/tabs.md +59 -9
  18. package/package.json +8 -5
  19. package/scripts/build.js +40 -19
  20. package/scss/_global-spacing.scss +12 -1
  21. package/scss/_root.scss +34 -2
  22. package/scss/mixins/_spacing-mixins.scss +1 -1
  23. package/scss/shared/layout.scss +15 -2
  24. package/scss/themes/_light.scss +1 -1
  25. package/src/components/absolute-container/absolute-container.component.ts +9 -25
  26. package/src/components/animated-button/animated-button.test.ts +8 -8
  27. package/src/components/button/button.component.ts +3 -1
  28. package/src/components/button/button.scss +5 -0
  29. package/src/components/button-menu/button-menu.component.ts +36 -21
  30. package/src/components/button-menu/button-menu.test.ts +55 -1
  31. package/src/components/chart/chart.component.ts +7 -7
  32. package/src/components/collapsible/collapsible.component.ts +7 -14
  33. package/src/components/cols/cols.scss +1 -1
  34. package/src/components/content-block/content-block.component.ts +11 -33
  35. package/src/components/data-select/data-select.component.ts +7 -11
  36. package/src/components/data-select/data-select.scss +1 -0
  37. package/src/components/data-table/data-table.component.ts +10 -14
  38. package/src/components/dialog/dialog.scss +4 -0
  39. package/src/components/editor/modules/toolbar/toolbar.component.ts +5 -9
  40. package/src/components/expanding-action/expanding-action.component.ts +37 -43
  41. package/src/components/form-group/form-group.component.ts +32 -27
  42. package/src/components/form-group/form-group.scss +1 -0
  43. package/src/components/header/header.component.ts +6 -5
  44. package/src/components/header/header.scss +28 -26
  45. package/src/components/inline-edit/inline-edit.component.ts +13 -1
  46. package/src/components/inline-edit/inline-edit.test.ts +50 -0
  47. package/src/components/input/input.test.ts +77 -0
  48. package/src/components/input-group/input-group.test.ts +2 -10
  49. package/src/components/item/item.component.ts +12 -6
  50. package/src/components/item/item.scss +1 -1
  51. package/src/components/item/item.test.ts +8 -0
  52. package/src/components/navbar/navbar.component.ts +222 -48
  53. package/src/components/navbar/navbar.scss +134 -21
  54. package/src/components/navbar/navbar.test.ts +114 -9
  55. package/src/components/option/option.scss +5 -7
  56. package/src/components/option/option.test.ts +30 -0
  57. package/src/components/page/index.ts +13 -0
  58. package/src/components/page/page.component.ts +406 -0
  59. package/src/components/page/page.scss +325 -0
  60. package/src/components/page/page.test.ts +397 -0
  61. package/src/components/page-nav/page-nav.scss +7 -5
  62. package/src/components/pane/pane.component.ts +2 -2
  63. package/src/components/pane/pane.scss +0 -1
  64. package/src/components/pane/pane.test.ts +31 -0
  65. package/src/components/panel/panel.scss +5 -16
  66. package/src/components/progress-bar/progress-bar.component.ts +5 -2
  67. package/src/components/progress-bar/progress-bar.scss +17 -1
  68. package/src/components/progress-bar/progress-bar.test.ts +12 -0
  69. package/src/components/scroll-container/scroll-container.component.ts +22 -21
  70. package/src/components/select/select.component.ts +243 -39
  71. package/src/components/select/select.scss +36 -5
  72. package/src/components/select/select.test.ts +533 -0
  73. package/src/components/settings-container/settings-container.component.ts +15 -19
  74. package/src/components/settings-container/settings-container.scss +8 -8
  75. package/src/components/sidebar/sidebar.component.ts +11 -11
  76. package/src/components/simple-chart/simple-chart.component.ts +6 -7
  77. package/src/components/sp/sp.scss +46 -15
  78. package/src/components/sp/sp.test.ts +15 -0
  79. package/src/components/split-pane/split-pane.component.ts +153 -26
  80. package/src/components/split-pane/split-pane.scss +89 -13
  81. package/src/components/split-pane/split-pane.test.ts +187 -0
  82. package/src/components/style/style.component.ts +8 -0
  83. package/src/components/tab/index.ts +13 -0
  84. package/src/components/tab/tab.component.ts +25 -0
  85. package/src/components/tab/tab.scss +7 -0
  86. package/src/components/table/table.component.ts +7 -2
  87. package/src/components/table/table.scss +1 -0
  88. package/src/components/tabs/tabs.component.ts +75 -70
  89. package/src/components/tabs/tabs.scss +1 -1
  90. package/src/components/textarea/textarea.component.ts +5 -8
  91. package/src/components/tile/tile.scss +2 -2
  92. package/src/components/translation-group/translation-group.component.ts +15 -14
  93. package/src/components/translations/translations.component.ts +18 -17
  94. package/src/components/translations/translations.scss +1 -0
  95. package/src/components/translations/translations.test.ts +3 -2
  96. package/src/internal/form.ts +234 -0
  97. package/src/internal/theme.ts +26 -46
  98. package/src/internal/zinc-element.ts +12 -7
  99. package/src/utilities/form.ts +1 -0
  100. package/src/wc.scss +1 -1
  101. package/src/zinc.ts +3 -0
@@ -1,14 +1,7 @@
1
- import '../../components/input/index';
2
- import '../../components/select/index';
3
- import '../../components/button/index';
4
- import './index';
1
+ import '../../../dist/zn.min.js';
5
2
  import {expect, fixture, html} from '@open-wc/testing';
6
3
  import type ZnInputGroup from './input-group.component';
7
4
 
8
- // We need to ensure components are defined for the test
9
- customElements.define('zn-input-group-test-input', class extends HTMLElement {
10
- });
11
-
12
5
  describe('<zn-input-group>', () => {
13
6
  it('should render a component', async () => {
14
7
  const el = await fixture(html`
@@ -68,8 +61,8 @@ describe('<zn-input-group>', () => {
68
61
  const button = el.querySelector('zn-button');
69
62
 
70
63
  expect(input).to.have.attribute('data-zn-input-group__input--first');
71
- expect(button).to.have.attribute('data-zn-input-group__input--last');
72
64
  expect(button).to.have.attribute('data-zn-input-group__input');
65
+ expect(button).to.not.have.attribute('data-zn-input-group__input--last');
73
66
  });
74
67
 
75
68
  it('should render a label when the label attribute is set', async () => {
@@ -93,6 +86,5 @@ describe('<zn-input-group>', () => {
93
86
  expect(label).to.exist;
94
87
  const slot = label?.querySelector('slot');
95
88
  expect(slot).to.exist;
96
- // Note: checking slot content in shadow DOM is tricky, but existence of label wrapper is enough to prove logic works
97
89
  });
98
90
  });
@@ -51,8 +51,11 @@ export default class ZnItem extends ZincElement {
51
51
 
52
52
  @property({type: Boolean}) grid: boolean;
53
53
 
54
+ //@deprecated
54
55
  @property({type: Boolean, attribute: 'no-padding'}) noPadding: boolean;
55
56
 
57
+ @property({type: Boolean, attribute: 'flush'}) flush: boolean;
58
+
56
59
  // align items to the right
57
60
  @property({type: Boolean, attribute: 'align-end'}) alignEnd: boolean;
58
61
 
@@ -62,6 +65,9 @@ export default class ZnItem extends ZincElement {
62
65
  connectedCallback() {
63
66
  super.connectedCallback();
64
67
  this.setAttribute('role', 'listitem');
68
+ if (this.flush) {
69
+ this.noPadding = true;
70
+ }
65
71
  }
66
72
 
67
73
  protected updated(_changedProperties: PropertyValues) {
@@ -91,15 +97,15 @@ export default class ZnItem extends ZincElement {
91
97
 
92
98
  const headings = html`
93
99
  <div class="item__headings">
94
- <div class=${classMap({
100
+ <div class="${classMap({
95
101
  'item__caption': true,
96
102
  'item__caption--required': this._hasRequiredSlot(),
97
103
  'item__caption--has-help': hasHelpTooltip
98
- })} part="caption">${this.caption}
99
- ${hasHelpTooltip ? html`
100
- <zn-tooltip class="item__help-tooltip" content="${this.helpTooltip}">
101
- <zn-icon src="info"></zn-icon>
102
- </zn-tooltip>` : ''}
104
+ })}" part="caption">${this.caption}
105
+ ${hasHelpTooltip ? html`
106
+ <zn-tooltip class="item__help-tooltip" content="${this.helpTooltip}">
107
+ <zn-icon src="info"></zn-icon>
108
+ </zn-tooltip>` : ''}
103
109
  </div>
104
110
  ${this.description ? html`
105
111
  <div class="item__description">${this.description}</div>` : ''}
@@ -38,7 +38,7 @@
38
38
  }
39
39
  }
40
40
 
41
- &--align-end .description-item__content {
41
+ &--align-end .item__content-inner {
42
42
  text-align: right;
43
43
  }
44
44
 
@@ -7,4 +7,12 @@ describe('<zn-item>', () => {
7
7
 
8
8
  expect(el).to.exist;
9
9
  });
10
+
11
+ it('right aligns content when align-end is set', async () => {
12
+ const el = await fixture(html` <zn-item align-end caption="Total">$100.00</zn-item> `);
13
+ const content = el.shadowRoot?.querySelector<HTMLElement>('.item__content-inner');
14
+
15
+ expect(content).to.exist;
16
+ expect(getComputedStyle(content!).textAlign).to.equal('right');
17
+ });
10
18
  });
@@ -1,7 +1,9 @@
1
1
  import {classMap} from "lit/directives/class-map.js";
2
2
  import {type CSSResultGroup, html, type PropertyValues, unsafeCSS} from 'lit';
3
3
  import {ifDefined} from "lit/directives/if-defined.js";
4
+ import {MutationController} from '@lit-labs/observers/mutation-controller.js';
4
5
  import {property} from 'lit/decorators.js';
6
+ import {ResizeController} from '@lit-labs/observers/resize-controller.js';
5
7
  import {Store} from "../../internal/storage";
6
8
  import ZincElement from '../../internal/zinc-element';
7
9
  import ZnDropdown from "../dropdown";
@@ -14,6 +16,8 @@ interface StoredTab {
14
16
  title: string;
15
17
  }
16
18
 
19
+ const NAVBAR_MIN_WIDTH = 200;
20
+
17
21
  /**
18
22
  * @summary Short summary of the component's intended use.
19
23
  * @documentation https://zinc.style/components/navbar
@@ -25,7 +29,8 @@ interface StoredTab {
25
29
  * @event zn-event-name - Emitted as an example.
26
30
  *
27
31
  * @slot - The default slot.
28
- * @slot example - An example slot.
32
+ * @slot expand - Expanding action panels rendered alongside the navbar items.
33
+ * @slot bottom - Content rendered below the navbar row (e.g. chips, filters).
29
34
  *
30
35
  * @csspart base - The component's base wrapper.
31
36
  *
@@ -59,17 +64,24 @@ export default class ZnNavbar extends ZincElement {
59
64
  private _postItems: NodeListOf<Element>;
60
65
  @property()
61
66
  private _appended: Element[];
62
- private _expanding: NodeListOf<Element>;
67
+ private _expanding: Element[] = [];
63
68
  private _openedTabs: string[] = [];
64
- private resizeObserver: ResizeObserver | null = null;
69
+
70
+ private readonly _itemsObserver = new MutationController(this, {
71
+ target: null,
72
+ config: {childList: true},
73
+ callback: () => this._updateVisibility(),
74
+ });
65
75
 
66
76
  private _navItems: HTMLElement | null = null;
67
77
  private _expandable: HTMLElement | null = null;
68
78
  private _extendedMenu: HTMLElement | null = null;
79
+ private readonly _cloneSources = new WeakMap<HTMLElement, HTMLElement>();
69
80
  private _navItemsGap: number = 0;
70
81
  private _expandableMargin: number = 0;
71
82
  private _totalItemWidth: number = 0;
72
- private _itemsObserver: MutationObserver | null = null;
83
+ private _resizeFrame: number | null = null;
84
+ private _resizeController: ResizeController;
73
85
 
74
86
  protected _store: Store;
75
87
 
@@ -77,14 +89,82 @@ export default class ZnNavbar extends ZincElement {
77
89
  this._appended = [...(this._appended || []), item];
78
90
  }
79
91
 
92
+ addExpandingAction(action: Element) {
93
+ if (!this._expanding.includes(action)) {
94
+ this._expanding = [...this._expanding, action];
95
+ }
96
+
97
+ if (action.parentElement !== this) {
98
+ this.appendChild(action);
99
+ }
100
+
101
+ this.requestUpdate();
102
+ this._updateVisibility();
103
+ this._observeExpandingAction(action);
104
+ this._scheduleResize();
105
+ }
106
+
107
+ constructor() {
108
+ super();
109
+ this._resizeController = new ResizeController(this, {
110
+ callback: () => this._scheduleResize(),
111
+ });
112
+ // eslint-disable-next-line no-new
113
+ new MutationController(this, {
114
+ config: {childList: true},
115
+ callback: mutations => this._adoptNewLightItems(mutations),
116
+ });
117
+ }
118
+
119
+ private readonly _expandingActionObserver = new MutationController(this, {
120
+ target: null,
121
+ config: {attributes: true, attributeFilter: ['open', 'method', 'basis']},
122
+ callback: () => this._scheduleResize(),
123
+ });
124
+
125
+ private _scheduleResize = () => {
126
+ if (this._resizeFrame !== null) {
127
+ cancelAnimationFrame(this._resizeFrame);
128
+ }
129
+
130
+ this._resizeFrame = requestAnimationFrame(() => {
131
+ this._resizeFrame = null;
132
+ this.handleResize();
133
+ });
134
+ };
135
+
136
+ private _observeExpandingAction(action: Element) {
137
+ this._expandingActionObserver.observe(action);
138
+ this._resizeController.observe(action);
139
+ }
140
+
141
+ private _adoptNewLightItems(mutations: MutationRecord[]) {
142
+ const ul = this.shadowRoot?.querySelector('ul');
143
+ if (!ul) return;
144
+ const moreItem = ul.querySelector('li.more');
145
+ for (const m of mutations) {
146
+ for (const node of Array.from(m.addedNodes)) {
147
+ if (node instanceof Element && node.tagName === 'ZN-EXPANDING-ACTION') {
148
+ this.addExpandingAction(node);
149
+ continue;
150
+ }
151
+
152
+ if (!(node instanceof HTMLLIElement)) continue;
153
+ if (node.hasAttribute('suffix')) continue;
154
+ if (moreItem) {
155
+ ul.insertBefore(node, moreItem);
156
+ } else {
157
+ ul.appendChild(node);
158
+ }
159
+ }
160
+ }
161
+ }
162
+
80
163
  connectedCallback() {
81
164
  super.connectedCallback();
82
165
  this._preItems = this.querySelectorAll('li:not([suffix])');
83
166
  this._postItems = this.querySelectorAll('li[suffix]');
84
- this._expanding = this.querySelectorAll('zn-expanding-action');
85
-
86
- this.resizeObserver = new ResizeObserver(this.handleResize.bind(this));
87
- this.resizeObserver.observe(this as HTMLElement); // Observe the parent node
167
+ this._expanding = Array.from(this.querySelectorAll('zn-expanding-action'));
88
168
 
89
169
  if (!this.masterId) {
90
170
  this.masterId = this.storeKey || Math.floor(Math.random() * 1000000).toString();
@@ -97,21 +177,13 @@ export default class ZnNavbar extends ZincElement {
97
177
  this._store = new Store(this.localStorage ? window.localStorage : window.sessionStorage, "znnav:", this.storeTtl);
98
178
  }
99
179
 
100
- disconnectedCallback() {
101
- super.disconnectedCallback();
102
- this._itemsObserver?.disconnect();
103
- this._itemsObserver = null;
104
- this.resizeObserver?.disconnect();
105
- this.resizeObserver = null;
106
- }
107
-
108
180
  private _updateVisibility = () => {
109
181
  if (this._expanding.length > 0) {
110
182
  this.style.display = '';
111
183
  return;
112
184
  }
113
- const items = this._navItems?.querySelectorAll(':scope > li:not(.more):not(#dropdown-item)') || [];
114
- const itemCount = items.length;
185
+
186
+ const itemCount = this.itemCount()
115
187
  if (itemCount === 0 || (itemCount < 2 && this.hideOne)) {
116
188
  this.style.display = 'none';
117
189
  } else {
@@ -119,20 +191,12 @@ export default class ZnNavbar extends ZincElement {
119
191
  }
120
192
  };
121
193
 
122
- handleResize = () => {
123
- if (this._totalItemWidth === 0 || this._extendedMenu === null || this.iconBar || this.stacked) {
124
- // If we can't do anything with the nav items, we just return
125
- return;
126
- }
127
-
128
- const expandWidth = this._expandableMargin + (this._expandable?.offsetWidth || 0);
129
- let hasHidden = (this._navItems?.querySelectorAll('li.hidden').length || 0) > 0
130
-
131
- if (!hasHidden && expandWidth + this._totalItemWidth <= this.offsetWidth) {
132
- this._navItems?.classList.toggle('has-hidden', false)
133
- return
134
- }
194
+ itemCount(): number {
195
+ const items = this._navItems?.querySelectorAll(':scope > li:not(.more):not(#dropdown-item)') || [];
196
+ return items.length;
197
+ }
135
198
 
199
+ private _resolveAvailableWidth(): number {
136
200
  let parent = this.parentElement;
137
201
  let availableWidth = this.offsetWidth || parent?.offsetWidth || 0;
138
202
 
@@ -143,7 +207,102 @@ export default class ZnNavbar extends ZincElement {
143
207
  availableWidth = parent.offsetWidth || 0;
144
208
  }
145
209
 
146
- availableWidth -= expandWidth;
210
+ return availableWidth;
211
+ }
212
+
213
+ private _measureTotalItemWidth(): number {
214
+ const items = this._navItems?.querySelectorAll(':scope > li') || [];
215
+ let totalWidth = 0;
216
+
217
+ for (const item of items) {
218
+ if (item.classList.contains('more') || !(item instanceof HTMLElement)) {
219
+ continue;
220
+ }
221
+
222
+ totalWidth += this._getItemWidth(item);
223
+ }
224
+
225
+ return totalWidth;
226
+ }
227
+
228
+ private _getItemWidth(item: HTMLElement): number {
229
+ return (item.getBoundingClientRect().width || item.offsetWidth || 0) + this._navItemsGap + 5;
230
+ }
231
+
232
+ private _getHorizontalSpacing(element: HTMLElement): number {
233
+ const computed = getComputedStyle(element);
234
+ return (parseFloat(computed.paddingLeft) || 0) + (parseFloat(computed.paddingRight) || 0);
235
+ }
236
+
237
+ private _getMoreItemWidth(): number {
238
+ const moreItem = this._navItems?.querySelector<HTMLElement>(':scope > li.more');
239
+ if (!moreItem || !this._navItems) {
240
+ return 0;
241
+ }
242
+
243
+ let moreWidth = this._getItemWidth(moreItem);
244
+ if (moreWidth > 0) {
245
+ return moreWidth;
246
+ }
247
+
248
+ const hadHidden = this._navItems.classList.contains('has-hidden');
249
+ this._navItems.classList.add('has-hidden');
250
+ moreWidth = this._getItemWidth(moreItem);
251
+ this._navItems.classList.toggle('has-hidden', hadHidden);
252
+
253
+ return moreWidth;
254
+ }
255
+
256
+ private _getExpandableWidth(containerWidth: number): number {
257
+ const expandableWidth = this._expandableMargin + (this._expandable?.getBoundingClientRect().width || this._expandable?.offsetWidth || 0);
258
+ let fillWidth = 0;
259
+
260
+ for (const action of this._expanding) {
261
+ if (!(action instanceof HTMLElement)) {
262
+ continue;
263
+ }
264
+
265
+ const method = (action as HTMLElement & {method?: string}).method || action.getAttribute('method') || 'drop';
266
+ const open = Boolean((action as HTMLElement & {open?: boolean}).open || action.hasAttribute('open'));
267
+
268
+ if (method !== 'fill' || !open) {
269
+ continue;
270
+ }
271
+
272
+ const panel = action.shadowRoot?.querySelector<HTMLElement>('.expanding-action--fill');
273
+ const panelWidth = panel?.getBoundingClientRect().width || 0;
274
+ fillWidth = Math.max(fillWidth, panelWidth, Math.min(containerWidth, 800));
275
+ }
276
+
277
+ return Math.max(expandableWidth, fillWidth);
278
+ }
279
+
280
+ handleResize = () => {
281
+ if (this._extendedMenu === null || this.iconBar || this.stacked) {
282
+ // If we can't do anything with the nav items, we just return
283
+ return;
284
+ }
285
+
286
+ const availableContainerWidth = this._resolveAvailableWidth();
287
+ const expandWidth = this._getExpandableWidth(availableContainerWidth);
288
+ this._totalItemWidth = this._measureTotalItemWidth();
289
+ if (this._totalItemWidth === 0) {
290
+ return;
291
+ }
292
+
293
+ let hasHidden = (this._navItems?.querySelectorAll('li.hidden').length || 0) > 0
294
+
295
+ const navSpacing = this._navItems ? this._getHorizontalSpacing(this._navItems) : 0;
296
+ const availableWidth = Math.max(availableContainerWidth - expandWidth, NAVBAR_MIN_WIDTH);
297
+ const availableWithoutMore = availableWidth - navSpacing;
298
+
299
+ if (!hasHidden && this._totalItemWidth <= availableWithoutMore) {
300
+ this._navItems?.classList.toggle('has-hidden', false)
301
+ return
302
+ }
303
+
304
+ const moreWidth = this._getMoreItemWidth();
305
+ const availableWithMore = availableWithoutMore - moreWidth;
147
306
  // reduce the items
148
307
  let takenWidth = 0;
149
308
  let hideRemaining = false;
@@ -153,10 +312,11 @@ export default class ZnNavbar extends ZincElement {
153
312
  if (item.classList.contains('more') || !(item instanceof HTMLElement)) {
154
313
  continue;
155
314
  }
156
- const itemWidth = item.offsetWidth + this._navItemsGap + 5
157
- if (hideRemaining || ((itemWidth + takenWidth) > availableWidth)) {
315
+ const itemWidth = this._getItemWidth(item);
316
+ if (hideRemaining || ((itemWidth + takenWidth) > availableWithMore)) {
158
317
  const extMenu = item.cloneNode(true) as HTMLElement;
159
318
  extMenu.classList.remove('hidden');
319
+ this._cloneSources.set(extMenu, item);
160
320
  extMenu.addEventListener('click', () => {
161
321
  item.click();
162
322
  (this.shadowRoot?.querySelector('#extended-dropdown') as ZnDropdown || null)?.hide()
@@ -173,6 +333,18 @@ export default class ZnNavbar extends ZincElement {
173
333
  this._navItems?.classList.toggle('has-hidden', hasHidden && hideRemaining)
174
334
  }
175
335
 
336
+ // Clones in the extended menu are static snapshots, so mirror the active
337
+ // state of their source items each time the dropdown opens.
338
+ private _syncExtendedActive = () => {
339
+ const clones = this._extendedMenu?.querySelectorAll<HTMLElement>(':scope > li') || [];
340
+ for (const clone of clones) {
341
+ const source = this._cloneSources.get(clone);
342
+ if (!source) continue;
343
+ clone.classList.toggle('active', source.classList.contains('active'));
344
+ clone.classList.toggle('zn-tb-active', source.classList.contains('zn-tb-active'));
345
+ }
346
+ };
347
+
176
348
  public addItem(item: Element, persist: boolean = true): void {
177
349
  const tabUri = item.getAttribute('tab-uri');
178
350
  if (typeof tabUri !== 'string' || this._openedTabs.includes(tabUri)) {
@@ -195,21 +367,26 @@ export default class ZnNavbar extends ZincElement {
195
367
  } else {
196
368
  ul?.appendChild(item);
197
369
  }
370
+
371
+ this._updateVisibility();
198
372
  }
199
373
 
200
374
  protected firstUpdated(_changedProperties: PropertyValues) {
201
375
  super.firstUpdated(_changedProperties);
202
376
 
203
377
  this._extendedMenu = this.shadowRoot?.querySelector('#extended-menu') as HTMLElement || null;
378
+ this.shadowRoot?.querySelector('#extended-dropdown')?.addEventListener('zn-show', this._syncExtendedActive);
204
379
  this._expandable = this.shadowRoot?.querySelector('.navbar__container > div.expandables') as HTMLElement || null;
205
380
  if (this._expandable) {
206
381
  const computed = getComputedStyle(this._expandable);
207
- this._expandableMargin = parseInt(computed.marginLeft) + parseInt(computed.marginRight);
382
+ this._expandableMargin = (parseFloat(computed.marginLeft) || 0) + (parseFloat(computed.marginRight) || 0);
383
+ this._resizeController.observe(this._expandable);
208
384
  }
209
385
  this._navItems = this.shadowRoot?.querySelector('.navbar__container > ul') as HTMLElement || null;
210
386
  if (this._navItems) {
211
387
  const computed = getComputedStyle(this._navItems);
212
- this._navItemsGap = parseInt(computed.columnGap);
388
+ this._navItemsGap = parseFloat(computed.columnGap) || 0;
389
+ this._resizeController.observe(this._navItems);
213
390
 
214
391
  this._navItems.addEventListener('click', (e) => {
215
392
  const target = (e.target as HTMLElement).closest('li[tab-uri]');
@@ -226,17 +403,12 @@ export default class ZnNavbar extends ZincElement {
226
403
  this._loadStoredTabs();
227
404
 
228
405
  if (this._navItems) {
229
- this._itemsObserver = new MutationObserver(this._updateVisibility);
230
- this._itemsObserver.observe(this._navItems, {childList: true});
406
+ this._itemsObserver.observe(this._navItems);
231
407
  }
408
+ this._expanding.forEach(action => this._observeExpandingAction(action));
232
409
  this._updateVisibility();
233
410
 
234
411
  setTimeout(() => {
235
- const items = this._navItems?.querySelectorAll('li') || [];
236
- for (const item of items) {
237
- this._totalItemWidth += item.offsetWidth + this._navItemsGap
238
- }
239
-
240
412
  this.handleResize();
241
413
  }, 100)
242
414
 
@@ -337,7 +509,7 @@ export default class ZnNavbar extends ZincElement {
337
509
  }
338
510
 
339
511
  return html`
340
- <div class="${classMap({
512
+ <div part="container" class="${classMap({
341
513
  'navbar__container': true,
342
514
  'navbar__container--stacked': this.stacked,
343
515
  'navbar__container--icon-bar': this.iconBar
@@ -360,10 +532,11 @@ export default class ZnNavbar extends ZincElement {
360
532
  }
361
533
  if (item.path != undefined) {
362
534
  return html`
363
- <li class="${classMap({'active': item.active})}" part="navbar-item" tab-uri="${item.path}">${content}</li>`;
535
+ <li class="${classMap({'active': item.active})}" part="navbar-item" tab-uri="${item.path}">${content}
536
+ </li>`;
364
537
  }
365
538
  return html`
366
- <li class="${classMap({ 'active': item.active })}"
539
+ <li class="${classMap({'active': item.active})}"
367
540
  part="navbar-item"
368
541
  tab="${ifDefined(!this.isolated ? item.tab : undefined)}"
369
542
  data-tab="${ifDefined(this.isolated ? item.tab : undefined)}">
@@ -373,7 +546,7 @@ export default class ZnNavbar extends ZincElement {
373
546
  <li class="more">
374
547
  <zn-dropdown placement="bottom-end" id="extended-dropdown">
375
548
  <zn-button slot="trigger" text color="transparent">
376
- <zn-icon src="double_arrow" size="16"></zn-icon>
549
+ <zn-icon src="arrow_right_alt" size="16"></zn-icon>
377
550
  </zn-button>
378
551
  <ul id="extended-menu">
379
552
  </ul>
@@ -397,6 +570,7 @@ export default class ZnNavbar extends ZincElement {
397
570
  <slot name="expand"></slot>
398
571
  </div>
399
572
  ` : ''}
400
- </div>`;
573
+ </div>
574
+ <slot name="bottom" part="bottom"></slot>`;
401
575
  }
402
576
  }