@kubex/zinc 1.0.113 → 1.0.114
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 +2636 -421
- package/dist/vscode.html-custom-data.json +96 -16
- package/dist/web-types.json +268 -31
- package/dist/zn.d.ts +517 -340
- package/dist/zn.min.css +1 -1
- package/dist/zn.min.js +942 -863
- 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/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-table/data-table.component.ts +10 -14
- 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 +8 -3
- package/src/components/header/header.component.ts +6 -5
- package/src/components/header/header.scss +31 -25
- 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 +1 -0
- 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 +240 -38
- package/src/components/select/select.scss +15 -0
- package/src/components/select/select.test.ts +477 -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/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/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,5 +1,6 @@
|
|
|
1
1
|
import '../../../dist/zn.min.js';
|
|
2
2
|
import { expect, fixture, html } from '@open-wc/testing';
|
|
3
|
+
import type ZnSplitPane from './split-pane.component';
|
|
3
4
|
|
|
4
5
|
describe('<zn-split-pane>', () => {
|
|
5
6
|
it('should render a component', async () => {
|
|
@@ -7,4 +8,190 @@ describe('<zn-split-pane>', () => {
|
|
|
7
8
|
|
|
8
9
|
expect(el).to.exist;
|
|
9
10
|
});
|
|
11
|
+
|
|
12
|
+
it('should hide the secondary pane and disable the resizer', async () => {
|
|
13
|
+
const el = await fixture(html`
|
|
14
|
+
<zn-split-pane hide="secondary">
|
|
15
|
+
<div slot="primary">Primary content</div>
|
|
16
|
+
<div slot="secondary">Secondary content</div>
|
|
17
|
+
</zn-split-pane>
|
|
18
|
+
`);
|
|
19
|
+
const primaryPane = el.shadowRoot?.querySelector('#primary-pane') as HTMLElement;
|
|
20
|
+
const secondaryPane = el.shadowRoot?.querySelector('#secondary-pane') as HTMLElement;
|
|
21
|
+
const resizer = el.shadowRoot?.querySelector('#resizer') as HTMLElement;
|
|
22
|
+
|
|
23
|
+
expect(getComputedStyle(secondaryPane).maxWidth).to.equal('0px');
|
|
24
|
+
expect(getComputedStyle(secondaryPane).visibility).to.equal('hidden');
|
|
25
|
+
expect(getComputedStyle(secondaryPane).pointerEvents).to.equal('none');
|
|
26
|
+
expect(getComputedStyle(resizer).display).to.equal('none');
|
|
27
|
+
expect(getComputedStyle(primaryPane).maxWidth).to.equal('100%');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should hide the primary pane and disable the resizer', async () => {
|
|
31
|
+
const el = await fixture(html`
|
|
32
|
+
<zn-split-pane hide="primary">
|
|
33
|
+
<div slot="primary">Primary content</div>
|
|
34
|
+
<div slot="secondary">Secondary content</div>
|
|
35
|
+
</zn-split-pane>
|
|
36
|
+
`);
|
|
37
|
+
const primaryPane = el.shadowRoot?.querySelector('#primary-pane') as HTMLElement;
|
|
38
|
+
const secondaryPane = el.shadowRoot?.querySelector('#secondary-pane') as HTMLElement;
|
|
39
|
+
const resizer = el.shadowRoot?.querySelector('#resizer') as HTMLElement;
|
|
40
|
+
|
|
41
|
+
expect(getComputedStyle(primaryPane).maxWidth).to.equal('0px');
|
|
42
|
+
expect(getComputedStyle(primaryPane).visibility).to.equal('hidden');
|
|
43
|
+
expect(getComputedStyle(primaryPane).pointerEvents).to.equal('none');
|
|
44
|
+
expect(getComputedStyle(resizer).display).to.equal('none');
|
|
45
|
+
expect(getComputedStyle(secondaryPane).maxWidth).to.equal('100%');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should render split pane chrome when pane slots are provided', async () => {
|
|
49
|
+
const el = await fixture(html`
|
|
50
|
+
<zn-split-pane>
|
|
51
|
+
<div slot="primary">Primary content</div>
|
|
52
|
+
<div slot="secondary">Secondary content</div>
|
|
53
|
+
</zn-split-pane>
|
|
54
|
+
`);
|
|
55
|
+
|
|
56
|
+
expect(el.shadowRoot?.querySelector('slot[name="primary"]')).to.exist;
|
|
57
|
+
expect(el.shadowRoot?.querySelector('slot[name="secondary"]')).to.exist;
|
|
58
|
+
expect(el.shadowRoot?.querySelector('#resizer')).to.exist;
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('merges immediate nested split pane navigation into the parent navigation', async () => {
|
|
62
|
+
const el = await fixture<ZnSplitPane>(html`
|
|
63
|
+
<zn-split-pane primary-caption="List" secondary-caption="Workspace" style="width: 500px; height: 400px;">
|
|
64
|
+
<div slot="primary">List content</div>
|
|
65
|
+
<div slot="secondary">
|
|
66
|
+
<zn-split-pane primary-caption="Preview" secondary-caption="Details">
|
|
67
|
+
<div slot="primary">Preview content</div>
|
|
68
|
+
<div slot="secondary">Details content</div>
|
|
69
|
+
</zn-split-pane>
|
|
70
|
+
</div>
|
|
71
|
+
</zn-split-pane>
|
|
72
|
+
`);
|
|
73
|
+
await el.updateComplete;
|
|
74
|
+
const nested = el.querySelector<ZnSplitPane>('zn-split-pane')!;
|
|
75
|
+
await nested.updateComplete;
|
|
76
|
+
const navItems = Array.from(el.shadowRoot!.querySelectorAll('#split-nav li'));
|
|
77
|
+
|
|
78
|
+
expect(nested.hasAttribute('merged-navigation')).to.equal(true);
|
|
79
|
+
expect(navItems.map(item => item.textContent?.trim())).to.deep.equal(['List', 'Preview', 'Details']);
|
|
80
|
+
|
|
81
|
+
(navItems[2] as HTMLElement).click();
|
|
82
|
+
await el.updateComplete;
|
|
83
|
+
await nested.updateComplete;
|
|
84
|
+
|
|
85
|
+
expect(el.getAttribute('focus-pane')).to.equal('1');
|
|
86
|
+
expect(nested.getAttribute('focus-pane')).to.equal('1');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('does not merge nested navigation when the parent is wide enough to hide its own nav', async () => {
|
|
90
|
+
const el = await fixture<ZnSplitPane>(html`
|
|
91
|
+
<zn-split-pane primary-caption="List" secondary-caption="Workspace" style="width: 1000px; height: 400px;">
|
|
92
|
+
<div slot="primary">List content</div>
|
|
93
|
+
<div slot="secondary">
|
|
94
|
+
<zn-split-pane primary-caption="Preview" secondary-caption="Details">
|
|
95
|
+
<div slot="primary">Preview content</div>
|
|
96
|
+
<div slot="secondary">Details content</div>
|
|
97
|
+
</zn-split-pane>
|
|
98
|
+
</div>
|
|
99
|
+
</zn-split-pane>
|
|
100
|
+
`);
|
|
101
|
+
await el.updateComplete;
|
|
102
|
+
const nested = el.querySelector<ZnSplitPane>('zn-split-pane')!;
|
|
103
|
+
await nested.updateComplete;
|
|
104
|
+
|
|
105
|
+
expect(nested.hasAttribute('merged-navigation')).to.equal(false);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('keeps nested split pane navigation visible when the parent does not merge navigation', async () => {
|
|
109
|
+
const el = await fixture<ZnSplitPane>(html`
|
|
110
|
+
<zn-split-pane vertical>
|
|
111
|
+
<div slot="primary">
|
|
112
|
+
<zn-split-pane primary-caption="Preview" secondary-caption="Details">
|
|
113
|
+
<div slot="primary">Preview content</div>
|
|
114
|
+
<div slot="secondary">Details content</div>
|
|
115
|
+
</zn-split-pane>
|
|
116
|
+
</div>
|
|
117
|
+
<div slot="secondary">Bottom content</div>
|
|
118
|
+
</zn-split-pane>
|
|
119
|
+
`);
|
|
120
|
+
const nested = el.querySelector<ZnSplitPane>('zn-split-pane')!;
|
|
121
|
+
|
|
122
|
+
expect(nested.hasAttribute('merged-navigation')).to.equal(false);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('recursively merges nested split pane navigation', async () => {
|
|
126
|
+
const el = await fixture<ZnSplitPane>(html`
|
|
127
|
+
<zn-split-pane primary-caption="List" secondary-caption="Workspace" style="width: 500px; height: 400px;">
|
|
128
|
+
<div slot="primary">List content</div>
|
|
129
|
+
<div slot="secondary">
|
|
130
|
+
<zn-split-pane primary-caption="Preview" secondary-caption="Details">
|
|
131
|
+
<div slot="primary">Preview content</div>
|
|
132
|
+
<div slot="secondary">
|
|
133
|
+
<zn-split-pane primary-caption="Data" secondary-caption="Settings">
|
|
134
|
+
<div slot="primary">Data content</div>
|
|
135
|
+
<div slot="secondary">Settings content</div>
|
|
136
|
+
</zn-split-pane>
|
|
137
|
+
</div>
|
|
138
|
+
</zn-split-pane>
|
|
139
|
+
</div>
|
|
140
|
+
</zn-split-pane>
|
|
141
|
+
`);
|
|
142
|
+
await el.updateComplete;
|
|
143
|
+
const nested = el.querySelector<ZnSplitPane>('zn-split-pane')!;
|
|
144
|
+
const deepNested = nested.querySelector<ZnSplitPane>('zn-split-pane')!;
|
|
145
|
+
await nested.updateComplete;
|
|
146
|
+
await deepNested.updateComplete;
|
|
147
|
+
const navItems = Array.from(el.shadowRoot!.querySelectorAll('#split-nav li'));
|
|
148
|
+
|
|
149
|
+
expect(deepNested.hasAttribute('merged-navigation')).to.equal(true);
|
|
150
|
+
expect(navItems.map(item => item.textContent?.trim())).to.deep.equal(['List', 'Preview', 'Data', 'Settings']);
|
|
151
|
+
|
|
152
|
+
(navItems[3] as HTMLElement).click();
|
|
153
|
+
await el.updateComplete;
|
|
154
|
+
await nested.updateComplete;
|
|
155
|
+
await deepNested.updateComplete;
|
|
156
|
+
|
|
157
|
+
expect(el.getAttribute('focus-pane')).to.equal('1');
|
|
158
|
+
expect(nested.getAttribute('focus-pane')).to.equal('1');
|
|
159
|
+
expect(deepNested.getAttribute('focus-pane')).to.equal('1');
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('should keep the secondary pane above the configured percentage minimum', async () => {
|
|
163
|
+
const el = await fixture<ZnSplitPane>(html`
|
|
164
|
+
<zn-split-pane min-secondary-size="25" style="display: flex; width: 400px; height: 200px;">
|
|
165
|
+
<div slot="primary">Primary content</div>
|
|
166
|
+
<div slot="secondary">Secondary content</div>
|
|
167
|
+
</zn-split-pane>
|
|
168
|
+
`);
|
|
169
|
+
const resizer = el.shadowRoot!.querySelector('#resizer')!;
|
|
170
|
+
|
|
171
|
+
resizer.dispatchEvent(new MouseEvent('mousedown', {clientX: 0, bubbles: true}));
|
|
172
|
+
window.dispatchEvent(new MouseEvent('mousemove', {clientX: 380, bubbles: true}));
|
|
173
|
+
await el.updateComplete;
|
|
174
|
+
window.dispatchEvent(new MouseEvent('mouseup', {bubbles: true}));
|
|
175
|
+
|
|
176
|
+
expect((el.shadowRoot?.querySelector('style')?.textContent ?? '')).to.contain('--min-secondary-panel-size: 25%');
|
|
177
|
+
expect((el.shadowRoot?.querySelector('style')?.textContent ?? '')).to.contain('--initial-size: 75%');
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should keep the secondary pane above the configured pixel minimum', async () => {
|
|
181
|
+
const el = await fixture<ZnSplitPane>(html`
|
|
182
|
+
<zn-split-pane pixels min-secondary-size="125" style="display: flex; width: 400px; height: 200px;">
|
|
183
|
+
<div slot="primary">Primary content</div>
|
|
184
|
+
<div slot="secondary">Secondary content</div>
|
|
185
|
+
</zn-split-pane>
|
|
186
|
+
`);
|
|
187
|
+
const resizer = el.shadowRoot!.querySelector('#resizer')!;
|
|
188
|
+
|
|
189
|
+
resizer.dispatchEvent(new MouseEvent('mousedown', {clientX: 0, bubbles: true}));
|
|
190
|
+
window.dispatchEvent(new MouseEvent('mousemove', {clientX: 350, bubbles: true}));
|
|
191
|
+
await el.updateComplete;
|
|
192
|
+
window.dispatchEvent(new MouseEvent('mouseup', {bubbles: true}));
|
|
193
|
+
|
|
194
|
+
expect((el.shadowRoot?.querySelector('style')?.textContent ?? '')).to.contain('--min-secondary-panel-size: 125px');
|
|
195
|
+
expect((el.shadowRoot?.querySelector('style')?.textContent ?? '')).to.contain('--initial-size: 275px');
|
|
196
|
+
});
|
|
10
197
|
});
|
|
@@ -26,6 +26,7 @@ export default class ZnStyle extends ZincElement {
|
|
|
26
26
|
@property() height = '';
|
|
27
27
|
@property() pad = '';
|
|
28
28
|
@property() margin = '';
|
|
29
|
+
@property({type: Boolean}) gutter = false;
|
|
29
30
|
@property({attribute: 'a-margin'}) autoMargin = '';
|
|
30
31
|
|
|
31
32
|
connectedCallback() {
|
|
@@ -33,6 +34,13 @@ export default class ZnStyle extends ZincElement {
|
|
|
33
34
|
|
|
34
35
|
let display = this.display || 'contents';
|
|
35
36
|
|
|
37
|
+
if (this.gutter) {
|
|
38
|
+
this.classList.add('zn-gutter');
|
|
39
|
+
if (display === 'contents') {
|
|
40
|
+
display = 'block'
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
36
44
|
if (this.color === '') {
|
|
37
45
|
if (this.error) {
|
|
38
46
|
this.color = 'error';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {type CSSResultGroup, html, unsafeCSS} from 'lit';
|
|
2
|
+
import {property} from 'lit/decorators.js';
|
|
3
|
+
import ZincElement from '../../internal/zinc-element';
|
|
4
|
+
|
|
5
|
+
import styles from './tab.scss';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @summary Defines a tab panel for use inside zn-page.
|
|
9
|
+
* @documentation https://zinc.style/components/tab
|
|
10
|
+
* @status experimental
|
|
11
|
+
* @since 1.0
|
|
12
|
+
*
|
|
13
|
+
* @slot - The tab panel content.
|
|
14
|
+
*/
|
|
15
|
+
export default class ZnTab extends ZincElement {
|
|
16
|
+
static styles: CSSResultGroup = unsafeCSS(styles);
|
|
17
|
+
|
|
18
|
+
@property() caption: string;
|
|
19
|
+
@property({type: Number}) priority: number;
|
|
20
|
+
@property() uri: string;
|
|
21
|
+
|
|
22
|
+
render() {
|
|
23
|
+
return html`<slot></slot>`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -2,6 +2,7 @@ import {classMap} from "lit/directives/class-map.js";
|
|
|
2
2
|
import {type CSSResultGroup, html, unsafeCSS} from 'lit';
|
|
3
3
|
import {ifDefined} from "lit/directives/if-defined.js";
|
|
4
4
|
import {property} from 'lit/decorators.js';
|
|
5
|
+
import {ResizeController} from '@lit-labs/observers/resize-controller.js';
|
|
5
6
|
import {unsafeHTML} from "lit/directives/unsafe-html.js";
|
|
6
7
|
import ZincElement from '../../internal/zinc-element';
|
|
7
8
|
|
|
@@ -40,14 +41,18 @@ export default class ZnTable extends ZincElement {
|
|
|
40
41
|
private wideColumn: any = [];
|
|
41
42
|
private rows: any = [];
|
|
42
43
|
|
|
44
|
+
private readonly resizeObserver = new ResizeController(this, {
|
|
45
|
+
target: null,
|
|
46
|
+
callback: () => this.resizing(),
|
|
47
|
+
});
|
|
43
48
|
|
|
44
49
|
resizing() {
|
|
45
50
|
// TODO Resizing event
|
|
46
51
|
}
|
|
47
52
|
|
|
48
53
|
connectedCallback() {
|
|
49
|
-
if (this.fixedFirst) {
|
|
50
|
-
|
|
54
|
+
if (this.fixedFirst && this.parentElement) {
|
|
55
|
+
this.resizeObserver.observe(this.parentElement);
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
if (this.data === null || this.data === undefined) {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {type CSSResultGroup, html, type PropertyValues, unsafeCSS} from 'lit';
|
|
2
|
-
import {deepQuerySelectorAll} from "../../utilities/query";
|
|
3
|
-
import {HasSlotController} from "../../internal/slot";
|
|
4
|
-
import {ifDefined} from "lit/directives/if-defined.js";
|
|
5
|
-
import {md5} from "../../utilities/md5";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { type CSSResultGroup, html, type PropertyValues, unsafeCSS } from 'lit';
|
|
2
|
+
import { deepQuerySelectorAll } from "../../utilities/query";
|
|
3
|
+
import { HasSlotController } from "../../internal/slot";
|
|
4
|
+
import { ifDefined } from "lit/directives/if-defined.js";
|
|
5
|
+
import { md5 } from "../../utilities/md5";
|
|
6
|
+
import { MutationController } from '@lit-labs/observers/mutation-controller.js';
|
|
7
|
+
import { property } from 'lit/decorators.js';
|
|
8
|
+
import { Store } from "../../internal/storage";
|
|
8
9
|
import ZincElement from '../../internal/zinc-element';
|
|
9
10
|
|
|
10
11
|
import styles from './tabs.scss';
|
|
@@ -28,24 +29,25 @@ import styles from './tabs.scss';
|
|
|
28
29
|
*/
|
|
29
30
|
export default class ZnTabs extends ZincElement {
|
|
30
31
|
static styles: CSSResultGroup = unsafeCSS(styles);
|
|
31
|
-
@property({attribute: 'master-id', reflect: true}) masterId: string;
|
|
32
|
-
@property({attribute: 'default-uri', reflect: true}) defaultUri = '';
|
|
33
|
-
@property({attribute: 'active', reflect: true}) _current = '';
|
|
34
|
-
@property({attribute: 'split', type: Number, reflect: true}) _split: number;
|
|
35
|
-
@property({attribute: 'split-min', type: Number, reflect: true}) _splitMin = 60;
|
|
36
|
-
@property({attribute: 'split-
|
|
37
|
-
@property({attribute: '
|
|
38
|
-
@property({attribute: '
|
|
39
|
-
@property({attribute: '
|
|
40
|
-
@property({attribute: 'no-
|
|
32
|
+
@property({ attribute: 'master-id', reflect: true }) masterId: string;
|
|
33
|
+
@property({ attribute: 'default-uri', reflect: true }) defaultUri = '';
|
|
34
|
+
@property({ attribute: 'active', reflect: true }) _current = '';
|
|
35
|
+
@property({ attribute: 'split', type: Number, reflect: true }) _split: number;
|
|
36
|
+
@property({ attribute: 'split-min', type: Number, reflect: true }) _splitMin = 60;
|
|
37
|
+
@property({ attribute: 'split-min-secondary', type: Number, reflect: true }) _splitMinSecondary: number;
|
|
38
|
+
@property({ attribute: 'split-max', type: Number, reflect: true }) _splitMax: number;
|
|
39
|
+
@property({ attribute: 'primary-caption', reflect: true }) primaryCaption = 'Navigation';
|
|
40
|
+
@property({ attribute: 'secondary-caption', reflect: true }) secondaryCaption = 'Content';
|
|
41
|
+
@property({ attribute: 'no-prefetch', type: Boolean, reflect: true }) noPrefetch = false;
|
|
42
|
+
@property({ attribute: 'no-cache', type: Boolean, reflect: true }) noCache = false;
|
|
41
43
|
// session storage if not local
|
|
42
|
-
@property({attribute: 'local-storage', type: Boolean, reflect: true}) localStorage: boolean;
|
|
43
|
-
@property({attribute: 'store-key'}) storeKey: string;
|
|
44
|
-
@property({attribute: 'store-ttl', type: Number, reflect: true}) storeTtl = 0;
|
|
45
|
-
@property({attribute: 'padded', type: Boolean, reflect: true}) padded = false;
|
|
46
|
-
@property({attribute: 'fetch-style', type: String, reflect: true}) fetchStyle = "";
|
|
47
|
-
@property({attribute: 'full-width', type: Boolean, reflect: true}) fullWidth = false;
|
|
48
|
-
@property({attribute: 'padded-right', type: Boolean, reflect: true}) paddedRight = false;
|
|
44
|
+
@property({ attribute: 'local-storage', type: Boolean, reflect: true }) localStorage: boolean;
|
|
45
|
+
@property({ attribute: 'store-key' }) storeKey: string;
|
|
46
|
+
@property({ attribute: 'store-ttl', type: Number, reflect: true }) storeTtl = 0;
|
|
47
|
+
@property({ attribute: 'padded', type: Boolean, reflect: true }) padded = false;
|
|
48
|
+
@property({ attribute: 'fetch-style', type: String, reflect: true }) fetchStyle = "";
|
|
49
|
+
@property({ attribute: 'full-width', type: Boolean, reflect: true }) fullWidth = false;
|
|
50
|
+
@property({ attribute: 'padded-right', type: Boolean, reflect: true }) paddedRight = false;
|
|
49
51
|
@property() monitor: string;
|
|
50
52
|
// Creating a header
|
|
51
53
|
@property() caption: string;
|
|
@@ -61,6 +63,45 @@ export default class ZnTabs extends ZincElement {
|
|
|
61
63
|
private _knownUri: Map<string, string> = new Map<string, string>();
|
|
62
64
|
private readonly hasSlotController = new HasSlotController(this, '[default]', 'bottom', 'right', 'left', 'top', 'actions');
|
|
63
65
|
|
|
66
|
+
private readonly _domObserver = new MutationController(this, {
|
|
67
|
+
target: null,
|
|
68
|
+
config: { childList: true, subtree: true },
|
|
69
|
+
callback: mutations => {
|
|
70
|
+
mutations.forEach(mutation => {
|
|
71
|
+
if (mutation.type !== 'childList') return;
|
|
72
|
+
if (mutation.addedNodes.length > 0) {
|
|
73
|
+
this._registerTabs();
|
|
74
|
+
}
|
|
75
|
+
if (mutation.removedNodes.length > 0) {
|
|
76
|
+
mutation.removedNodes.forEach(node => {
|
|
77
|
+
const id = node instanceof HTMLElement ? node.id : '';
|
|
78
|
+
if (id) this.removeTabAndPanel(id);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
private readonly _monitorObserver = new MutationController(this, {
|
|
86
|
+
target: null,
|
|
87
|
+
config: { childList: true, subtree: true },
|
|
88
|
+
callback: mutations => {
|
|
89
|
+
mutations.forEach(mutation => {
|
|
90
|
+
if (mutation.type !== 'childList') return;
|
|
91
|
+
mutation.addedNodes.forEach(node => {
|
|
92
|
+
if (node instanceof HTMLElement && node.id === this.monitor) {
|
|
93
|
+
this.reRegisterTabs();
|
|
94
|
+
const storedValue = this._store.get(this.storeKey);
|
|
95
|
+
if (storedValue !== null) {
|
|
96
|
+
this._prepareTab(storedValue);
|
|
97
|
+
this.setActiveTab(storedValue, false, false);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
64
105
|
constructor() {
|
|
65
106
|
super();
|
|
66
107
|
this._panels = new Map<string, Element[]>();
|
|
@@ -100,25 +141,7 @@ export default class ZnTabs extends ZincElement {
|
|
|
100
141
|
|
|
101
142
|
monitorDom() {
|
|
102
143
|
if (this.monitor) {
|
|
103
|
-
|
|
104
|
-
mutations.forEach((mutation) => {
|
|
105
|
-
if (mutation.type === 'childList') {
|
|
106
|
-
mutation.addedNodes.forEach((node) => {
|
|
107
|
-
if (node instanceof HTMLElement && node.id === this.monitor) {
|
|
108
|
-
this.reRegisterTabs();
|
|
109
|
-
|
|
110
|
-
const storedValue = this._store.get(this.storeKey);
|
|
111
|
-
if (storedValue !== null) {
|
|
112
|
-
this._prepareTab(storedValue);
|
|
113
|
-
this.setActiveTab(storedValue, false, false);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
observer.observe(this, {childList: true, subtree: true});
|
|
144
|
+
this._monitorObserver.observe(this);
|
|
122
145
|
}
|
|
123
146
|
}
|
|
124
147
|
|
|
@@ -170,7 +193,7 @@ export default class ZnTabs extends ZincElement {
|
|
|
170
193
|
|
|
171
194
|
this.addEventListener('zn-menu-select', () => {
|
|
172
195
|
setTimeout(this.reRegisterTabs, 200);
|
|
173
|
-
}, {passive: true});
|
|
196
|
+
}, { passive: true });
|
|
174
197
|
}
|
|
175
198
|
|
|
176
199
|
switchTab(inc: number) {
|
|
@@ -237,6 +260,8 @@ export default class ZnTabs extends ZincElement {
|
|
|
237
260
|
tabNode.setAttribute("id", tabId);
|
|
238
261
|
if (this.fetchStyle !== "") {
|
|
239
262
|
tabNode.setAttribute("data-fetch-style", this.fetchStyle);
|
|
263
|
+
} else if (tabEle.hasAttribute('data-fetch-style')) {
|
|
264
|
+
tabNode.setAttribute("data-fetch-style", tabEle.getAttribute('data-fetch-style') ?? "");
|
|
240
265
|
}
|
|
241
266
|
tabNode.setAttribute('data-self-uri', tabUri);
|
|
242
267
|
tabNode.textContent = "Loading ...";
|
|
@@ -245,8 +270,9 @@ export default class ZnTabs extends ZincElement {
|
|
|
245
270
|
this._panel.appendChild(tabNode);
|
|
246
271
|
this._panels.set(tabId, [tabNode]);
|
|
247
272
|
}
|
|
273
|
+
|
|
248
274
|
document.dispatchEvent(new CustomEvent('zn-new-element', {
|
|
249
|
-
detail: {element: tabNode, source: tabEle}
|
|
275
|
+
detail: { element: tabNode, source: tabEle }
|
|
250
276
|
}));
|
|
251
277
|
return tabNode;
|
|
252
278
|
}
|
|
@@ -371,7 +397,7 @@ export default class ZnTabs extends ZincElement {
|
|
|
371
397
|
gaid = this._activeTab.getAttribute('gaid')!;
|
|
372
398
|
}
|
|
373
399
|
document.dispatchEvent(new CustomEvent('zn-refresh-element', {
|
|
374
|
-
detail: {element: element, uri: uri, gaid: gaid}
|
|
400
|
+
detail: { element: element, uri: uri, gaid: gaid }
|
|
375
401
|
}));
|
|
376
402
|
}
|
|
377
403
|
});
|
|
@@ -393,29 +419,7 @@ export default class ZnTabs extends ZincElement {
|
|
|
393
419
|
}
|
|
394
420
|
|
|
395
421
|
observerDom() {
|
|
396
|
-
|
|
397
|
-
const observer = new MutationObserver((mutations) => {
|
|
398
|
-
mutations.forEach((mutation) => {
|
|
399
|
-
if (mutation.type === 'childList') {
|
|
400
|
-
if (mutation.addedNodes.length > 0) {
|
|
401
|
-
this._registerTabs();
|
|
402
|
-
}
|
|
403
|
-
if (mutation.removedNodes.length > 0) {
|
|
404
|
-
for (let i = 0; i < mutation.removedNodes.length; i++) {
|
|
405
|
-
const node = mutation.removedNodes[i] as HTMLElement;
|
|
406
|
-
if (node.id) {
|
|
407
|
-
this.removeTabAndPanel(node.id);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
});
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
observer.observe(this, {
|
|
416
|
-
childList: true,
|
|
417
|
-
subtree: true
|
|
418
|
-
});
|
|
422
|
+
this._domObserver.observe(this);
|
|
419
423
|
}
|
|
420
424
|
|
|
421
425
|
removeTabAndPanel(tabId: string) {
|
|
@@ -504,6 +508,7 @@ export default class ZnTabs extends ZincElement {
|
|
|
504
508
|
padded-right="${ifDefined(this.paddedRight ? true : undefined)}"
|
|
505
509
|
pixels bordered
|
|
506
510
|
min-size="${this._splitMin}"
|
|
511
|
+
min-secondary-size="${ifDefined(this._splitMinSecondary ? this._splitMinSecondary : undefined)}"
|
|
507
512
|
max-size="${ifDefined(this._splitMax ? this._splitMax : undefined)}"
|
|
508
513
|
initial-size="${this._split}">
|
|
509
514
|
<slot slot="primary" name="left"></slot>
|
|
@@ -526,7 +531,7 @@ export default class ZnTabs extends ZincElement {
|
|
|
526
531
|
<slot name="top"></slot>
|
|
527
532
|
<div id="mid" part="mid">
|
|
528
533
|
<slot name="left"></slot>
|
|
529
|
-
<div id="content">
|
|
534
|
+
<div id="content" part="content">
|
|
530
535
|
<slot></slot>
|
|
531
536
|
</div>
|
|
532
537
|
<slot name="right"></slot>
|
|
@@ -6,6 +6,7 @@ import {HasSlotController} from "../../internal/slot";
|
|
|
6
6
|
import {ifDefined} from "lit/directives/if-defined.js";
|
|
7
7
|
import {live} from "lit/directives/live.js";
|
|
8
8
|
import {property, query, state} from 'lit/decorators.js';
|
|
9
|
+
import {ResizeController} from '@lit-labs/observers/resize-controller.js';
|
|
9
10
|
import {watch} from '../../internal/watch';
|
|
10
11
|
import ZincElement, {type ZincFormControl} from '../../internal/zinc-element';
|
|
11
12
|
|
|
@@ -42,7 +43,10 @@ export default class ZnTextarea extends ZincElement implements ZincFormControl {
|
|
|
42
43
|
assumeInteractionOn: ['zn-blur', 'zn-input']
|
|
43
44
|
});
|
|
44
45
|
private readonly hasSlotController = new HasSlotController(this, 'help-text', 'label');
|
|
45
|
-
private resizeObserver
|
|
46
|
+
private readonly resizeObserver = new ResizeController(this, {
|
|
47
|
+
target: null,
|
|
48
|
+
callback: () => this.setTextareaHeight(),
|
|
49
|
+
});
|
|
46
50
|
/** Ensures we only attempt to derive the initial value from light DOM content once */
|
|
47
51
|
private _didInitFromContent = false;
|
|
48
52
|
|
|
@@ -187,8 +191,6 @@ export default class ZnTextarea extends ZincElement implements ZincFormControl {
|
|
|
187
191
|
}
|
|
188
192
|
}
|
|
189
193
|
|
|
190
|
-
this.resizeObserver = new ResizeObserver(() => this.setTextareaHeight());
|
|
191
|
-
|
|
192
194
|
this.updateComplete.then(() => {
|
|
193
195
|
this.resizeObserver.observe(this.input);
|
|
194
196
|
|
|
@@ -202,11 +204,6 @@ export default class ZnTextarea extends ZincElement implements ZincFormControl {
|
|
|
202
204
|
this.formControlController.updateValidity();
|
|
203
205
|
}
|
|
204
206
|
|
|
205
|
-
disconnectedCallback() {
|
|
206
|
-
super.disconnectedCallback();
|
|
207
|
-
this.resizeObserver.unobserve(this.input);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
207
|
private handleBlur() {
|
|
211
208
|
this.hasFocus = false;
|
|
212
209
|
this.emit('zn-blur');
|
|
@@ -3,6 +3,7 @@ import {type CSSResultGroup, html, nothing, type PropertyValues, unsafeCSS} from
|
|
|
3
3
|
import {HasSlotController} from '../../internal/slot';
|
|
4
4
|
import {ifDefined} from 'lit/directives/if-defined.js';
|
|
5
5
|
import {property, state} from 'lit/decorators.js';
|
|
6
|
+
import {ResizeController} from '@lit-labs/observers/resize-controller.js';
|
|
6
7
|
import ZnButton from '../button';
|
|
7
8
|
import ZnButtonGroup from '../button-group';
|
|
8
9
|
import ZnDropdown from '../dropdown';
|
|
@@ -56,27 +57,28 @@ export default class ZnTranslationGroup extends ZnPanel {
|
|
|
56
57
|
|
|
57
58
|
@state() private _overflowIndex = -1;
|
|
58
59
|
|
|
59
|
-
private _resizeObserver?: ResizeObserver;
|
|
60
60
|
private _lastObservedWidth = 0;
|
|
61
61
|
private _measureRafId = 0;
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
super
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
this.
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
63
|
+
constructor() {
|
|
64
|
+
super();
|
|
65
|
+
// eslint-disable-next-line no-new
|
|
66
|
+
new ResizeController(this, {
|
|
67
|
+
callback: entries => {
|
|
68
|
+
const width = entries[0]?.contentRect.width ?? 0;
|
|
69
|
+
if (Math.abs(width - this._lastObservedWidth) < 1) return;
|
|
70
|
+
this._lastObservedWidth = width;
|
|
71
|
+
if (this._overflowIndex !== -1) {
|
|
72
|
+
this._overflowIndex = -1;
|
|
73
|
+
} else {
|
|
74
|
+
this._scheduleLangOverflow();
|
|
75
|
+
}
|
|
76
|
+
},
|
|
74
77
|
});
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
disconnectedCallback() {
|
|
78
81
|
super.disconnectedCallback();
|
|
79
|
-
this._resizeObserver?.disconnect();
|
|
80
82
|
if (this._measureRafId) {
|
|
81
83
|
cancelAnimationFrame(this._measureRafId);
|
|
82
84
|
this._measureRafId = 0;
|
|
@@ -86,7 +88,6 @@ export default class ZnTranslationGroup extends ZnPanel {
|
|
|
86
88
|
protected firstUpdated(_changedProperties: PropertyValues) {
|
|
87
89
|
super.firstUpdated(_changedProperties);
|
|
88
90
|
this.syncChildren();
|
|
89
|
-
this._resizeObserver?.observe(this);
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
protected updated(changedProperties: PropertyValues) {
|