@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,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,13 @@
1
+ import ZnTab from './tab.component';
2
+
3
+ export * from './tab.component';
4
+ export default ZnTab;
5
+
6
+ ZnTab.define('zn-tab');
7
+
8
+ declare global {
9
+ interface HTMLElementTagNameMap {
10
+ 'zn-tab': ZnTab;
11
+ }
12
+ }
13
+
@@ -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
+ }
@@ -0,0 +1,7 @@
1
+ @use "../../wc";
2
+
3
+ :host {
4
+ display: contents;
5
+ height: 100%;
6
+ }
7
+
@@ -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
- new ResizeObserver((_) => this.resizing).observe(this.parentElement as Element);
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) {
@@ -95,6 +95,7 @@ td.capcol {
95
95
  }
96
96
 
97
97
  .actions button {
98
+ display: flex;
98
99
  padding: 0;
99
100
  margin: 0;
100
101
  background: transparent;
@@ -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 {property} from 'lit/decorators.js';
7
- import {Store} from "../../internal/storage";
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-max', type: Number, reflect: true}) _splitMax: number;
37
- @property({attribute: 'primary-caption', reflect: true}) primaryCaption = 'Navigation';
38
- @property({attribute: 'secondary-caption', reflect: true}) secondaryCaption = 'Content';
39
- @property({attribute: 'no-prefetch', type: Boolean, reflect: true}) noPrefetch = false;
40
- @property({attribute: 'no-cache', type: Boolean, reflect: true}) noCache = false;
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
- const observer = new MutationObserver((mutations) => {
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
- // observe the DOM for changes
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>
@@ -28,7 +28,7 @@
28
28
  width: 100%;
29
29
 
30
30
  zn-header::part(base) {
31
- border-bottom-width: 0 !important;
31
+ //border-bottom-width: 0 !important;
32
32
  }
33
33
  }
34
34
 
@@ -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: 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');
@@ -12,7 +12,7 @@
12
12
  &--has-properties,
13
13
  &--has-actions,
14
14
  &--has-image {
15
- padding: var(--zn-spacing-large);
15
+ padding: var(--zn-spacing-medium);
16
16
  }
17
17
 
18
18
 
@@ -62,7 +62,7 @@
62
62
  justify-content: flex-end;
63
63
  width: 50%;
64
64
  flex-grow: 1;
65
- column-gap: var(--zn-spacing-large);
65
+ column-gap: var(--zn-spacing-medium);
66
66
  }
67
67
 
68
68
  .tile__properties {
@@ -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
- connectedCallback() {
64
- super.connectedCallback();
65
- this._resizeObserver = new ResizeObserver(entries => {
66
- const width = entries[0]?.contentRect.width ?? 0;
67
- if (Math.abs(width - this._lastObservedWidth) < 1) return;
68
- this._lastObservedWidth = width;
69
- if (this._overflowIndex !== -1) {
70
- this._overflowIndex = -1;
71
- } else {
72
- this._scheduleLangOverflow();
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) {