@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.
- package/.github/workflows/eleventy_build.yml +5 -5
- package/.github/workflows/js_build_and_deploy.yaml +1 -1
- package/dist/custom-elements.json +2422 -190
- package/dist/vscode.html-custom-data.json +86 -5
- package/dist/web-types.json +251 -9
- package/dist/zn.d.ts +518 -340
- package/dist/zn.min.css +1 -1
- package/dist/zn.min.js +960 -882
- package/docs/eleventy.config.cjs +4 -2
- package/docs/pages/components/header.md +13 -0
- package/docs/pages/components/inline-edit.md +20 -0
- package/docs/pages/components/item.md +12 -1
- package/docs/pages/components/page.md +149 -0
- package/docs/pages/components/progress-bar.md +16 -0
- package/docs/pages/components/select.md +25 -0
- package/docs/pages/components/split-pane.md +6 -7
- package/docs/pages/components/tabs.md +59 -9
- package/package.json +8 -5
- package/scripts/build.js +40 -19
- package/scss/_global-spacing.scss +12 -1
- package/scss/_root.scss +34 -2
- package/scss/mixins/_spacing-mixins.scss +1 -1
- package/scss/shared/layout.scss +15 -2
- package/scss/themes/_light.scss +1 -1
- package/src/components/absolute-container/absolute-container.component.ts +9 -25
- package/src/components/animated-button/animated-button.test.ts +8 -8
- package/src/components/button/button.component.ts +3 -1
- package/src/components/button/button.scss +5 -0
- package/src/components/button-menu/button-menu.component.ts +36 -21
- package/src/components/button-menu/button-menu.test.ts +55 -1
- package/src/components/chart/chart.component.ts +7 -7
- package/src/components/collapsible/collapsible.component.ts +7 -14
- package/src/components/cols/cols.scss +1 -1
- package/src/components/content-block/content-block.component.ts +11 -33
- package/src/components/data-select/data-select.component.ts +7 -11
- package/src/components/data-select/data-select.scss +1 -0
- package/src/components/data-table/data-table.component.ts +10 -14
- package/src/components/dialog/dialog.scss +4 -0
- package/src/components/editor/modules/toolbar/toolbar.component.ts +5 -9
- package/src/components/expanding-action/expanding-action.component.ts +37 -43
- package/src/components/form-group/form-group.component.ts +32 -27
- package/src/components/form-group/form-group.scss +1 -0
- package/src/components/header/header.component.ts +6 -5
- package/src/components/header/header.scss +28 -26
- package/src/components/inline-edit/inline-edit.component.ts +13 -1
- package/src/components/inline-edit/inline-edit.test.ts +50 -0
- package/src/components/input/input.test.ts +77 -0
- package/src/components/input-group/input-group.test.ts +2 -10
- package/src/components/item/item.component.ts +12 -6
- package/src/components/item/item.scss +1 -1
- package/src/components/item/item.test.ts +8 -0
- package/src/components/navbar/navbar.component.ts +222 -48
- package/src/components/navbar/navbar.scss +134 -21
- package/src/components/navbar/navbar.test.ts +114 -9
- package/src/components/option/option.scss +5 -7
- package/src/components/option/option.test.ts +30 -0
- package/src/components/page/index.ts +13 -0
- package/src/components/page/page.component.ts +406 -0
- package/src/components/page/page.scss +325 -0
- package/src/components/page/page.test.ts +397 -0
- package/src/components/page-nav/page-nav.scss +7 -5
- package/src/components/pane/pane.component.ts +2 -2
- package/src/components/pane/pane.scss +0 -1
- package/src/components/pane/pane.test.ts +31 -0
- package/src/components/panel/panel.scss +5 -16
- package/src/components/progress-bar/progress-bar.component.ts +5 -2
- package/src/components/progress-bar/progress-bar.scss +17 -1
- package/src/components/progress-bar/progress-bar.test.ts +12 -0
- package/src/components/scroll-container/scroll-container.component.ts +22 -21
- package/src/components/select/select.component.ts +243 -39
- package/src/components/select/select.scss +36 -5
- package/src/components/select/select.test.ts +533 -0
- package/src/components/settings-container/settings-container.component.ts +15 -19
- package/src/components/settings-container/settings-container.scss +8 -8
- package/src/components/sidebar/sidebar.component.ts +11 -11
- package/src/components/simple-chart/simple-chart.component.ts +6 -7
- package/src/components/sp/sp.scss +46 -15
- package/src/components/sp/sp.test.ts +15 -0
- package/src/components/split-pane/split-pane.component.ts +153 -26
- package/src/components/split-pane/split-pane.scss +89 -13
- package/src/components/split-pane/split-pane.test.ts +187 -0
- package/src/components/style/style.component.ts +8 -0
- package/src/components/tab/index.ts +13 -0
- package/src/components/tab/tab.component.ts +25 -0
- package/src/components/tab/tab.scss +7 -0
- package/src/components/table/table.component.ts +7 -2
- package/src/components/table/table.scss +1 -0
- package/src/components/tabs/tabs.component.ts +75 -70
- package/src/components/tabs/tabs.scss +1 -1
- package/src/components/textarea/textarea.component.ts +5 -8
- package/src/components/tile/tile.scss +2 -2
- package/src/components/translation-group/translation-group.component.ts +15 -14
- package/src/components/translations/translations.component.ts +18 -17
- package/src/components/translations/translations.scss +1 -0
- package/src/components/translations/translations.test.ts +3 -2
- package/src/internal/form.ts +234 -0
- package/src/internal/theme.ts +26 -46
- package/src/internal/zinc-element.ts +12 -7
- package/src/utilities/form.ts +1 -0
- package/src/wc.scss +1 -1
- package/src/zinc.ts +3 -0
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
import '
|
|
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
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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>` : ''}
|
|
@@ -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
|
|
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:
|
|
67
|
+
private _expanding: Element[] = [];
|
|
63
68
|
private _openedTabs: string[] = [];
|
|
64
|
-
|
|
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
|
|
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
|
-
|
|
114
|
-
const itemCount =
|
|
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
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
|
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 =
|
|
157
|
-
if (hideRemaining || ((itemWidth + takenWidth) >
|
|
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 =
|
|
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 =
|
|
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
|
|
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}
|
|
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({
|
|
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="
|
|
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
|
}
|