@kubex/zinc 1.0.4 → 1.0.6

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 (158) hide show
  1. package/dist/custom-elements.json +1278 -191
  2. package/dist/vscode.html-custom-data.json +93 -16
  3. package/dist/web-types.json +235 -25
  4. package/dist/zn.d.ts +1313 -941
  5. package/dist/zn.min.css +1 -1
  6. package/dist/zn.min.js +2049 -931
  7. package/docs/_includes/default.njk +1 -0
  8. package/docs/assets/scripts/docs.js +4 -5
  9. package/docs/assets/scripts/search.js +0 -9
  10. package/docs/assets/styles/docs.css +3 -3
  11. package/docs/data/data-table.json +79 -0
  12. package/docs/data/products-table.json +36 -0
  13. package/docs/eleventy.config.cjs +3 -0
  14. package/docs/pages/components/data-select.md +10 -0
  15. package/docs/pages/components/data-table.md +84 -45
  16. package/docs/pages/components/dialog.md +1 -1
  17. package/docs/pages/components/editor.md +1 -3
  18. package/docs/pages/components/filter-wrapper.md +20 -0
  19. package/docs/pages/components/icon.md +2 -0
  20. package/docs/pages/components/item.md +2 -2
  21. package/docs/pages/components/menu-item.md +12 -3
  22. package/docs/pages/components/panel.md +17 -0
  23. package/docs/pages/components/progress-tile.md +17 -1
  24. package/docs/pages/components/settings-container.md +137 -0
  25. package/docs/pages/components/textarea.md +1 -1
  26. package/package.json +3 -1
  27. package/scss/_root.scss +26 -0
  28. package/scss/boot.scss +27 -1
  29. package/scss/mixins/index.scss +30 -1
  30. package/scss/shared/_base.scss +1 -1
  31. package/scss/shared/_button.scss +1 -1
  32. package/scss/shared/layout.scss +7 -0
  33. package/scss/themes/_dark.scss +5 -5
  34. package/scss/themes/_light.scss +6 -5
  35. package/scss/variables/index.scss +9 -0
  36. package/src/components/alert/alert.component.ts +1 -1
  37. package/src/components/alert/alert.scss +18 -4
  38. package/src/components/bulk-actions/bulk-actions.component.ts +152 -84
  39. package/src/components/bulk-actions/bulk-actions.scss +2 -0
  40. package/src/components/button/button.component.ts +6 -2
  41. package/src/components/button/button.scss +16 -1
  42. package/src/components/button-menu/button-menu.component.ts +23 -15
  43. package/src/components/button-menu/button-menu.scss +4 -4
  44. package/src/components/chart/chart.component.ts +14 -12
  45. package/src/components/checkbox/checkbox.component.ts +5 -1
  46. package/src/components/checkbox/checkbox.scss +1 -1
  47. package/src/components/chip/chip.component.ts +7 -3
  48. package/src/components/chip/chip.scss +9 -1
  49. package/src/components/collapsible/collapsible.component.ts +48 -2
  50. package/src/components/cols/cols.component.ts +7 -3
  51. package/src/components/cols/cols.scss +22 -14
  52. package/src/components/confirm/confirm.component.ts +1 -2
  53. package/src/components/content-block/content-block.component.ts +104 -14
  54. package/src/components/content-block/content-block.scss +8 -0
  55. package/src/components/data-select/data-select.component.ts +1 -1
  56. package/src/components/data-table/data-table.component.ts +394 -430
  57. package/src/components/data-table/data-table.scss +6 -1
  58. package/src/components/datepicker/datepicker.scss +1 -1
  59. package/src/components/dialog/dialog.component.ts +52 -33
  60. package/src/components/dialog/dialog.scss +15 -1
  61. package/src/components/dropdown/dropdown.component.ts +1 -1
  62. package/src/components/editor/editor.component.ts +196 -158
  63. package/src/components/editor/editor.scss +25 -5
  64. package/src/components/editor/modules/ai/index.ts +281 -0
  65. package/src/components/editor/modules/ai/panel/ai-panel.component.ts +102 -0
  66. package/src/components/editor/modules/ai/panel/ai-panel.scss +83 -0
  67. package/src/components/editor/modules/ai/tooltip/ai-tooltip.component.ts +30 -0
  68. package/src/components/editor/modules/ai/tooltip/ai-tooltip.scss +28 -0
  69. package/src/components/editor/modules/{attachment-module.ts → attachment/attachment.ts} +7 -7
  70. package/src/components/editor/modules/context-menu/context-menu-component.ts +115 -0
  71. package/src/components/editor/modules/context-menu/context-menu.scss +49 -0
  72. package/src/components/editor/modules/context-menu/context-menu.ts +296 -0
  73. package/src/components/editor/modules/context-menu/quick-action/index.ts +12 -0
  74. package/src/components/editor/modules/context-menu/quick-action/quick-action.component.ts +18 -0
  75. package/src/components/editor/modules/date-picker/date-picker.ts +77 -0
  76. package/src/components/editor/modules/dialog/dialog.component.ts +115 -0
  77. package/src/components/editor/modules/dialog/dialog.scss +43 -0
  78. package/src/components/editor/modules/dialog/dialog.ts +46 -0
  79. package/src/components/editor/modules/{drag-drop-module.ts → drag-drop/drag-drop.ts} +6 -6
  80. package/src/components/editor/modules/emoji/emoji.ts +106 -0
  81. package/src/components/editor/modules/emoji/headless/headless-emoji.component.ts +122 -0
  82. package/src/components/editor/modules/emoji/headless/headless-emoji.scss +52 -0
  83. package/src/components/editor/modules/emoji/headless/headless-emoji.ts +223 -0
  84. package/src/components/editor/modules/{image-resize-module/image-resize-module.ts → image-resize/image-resize.ts} +5 -5
  85. package/src/components/editor/modules/{time-tracking-module.ts → time-tracking/time-tracking.ts} +5 -5
  86. package/src/components/editor/modules/toolbar/tool/index.ts +12 -0
  87. package/src/components/editor/modules/toolbar/tool/tool.component.ts +30 -0
  88. package/src/components/editor/modules/toolbar/tool/tool.scss +5 -0
  89. package/src/components/editor/modules/toolbar/toolbar.component.ts +738 -0
  90. package/src/components/editor/modules/toolbar/toolbar.scss +98 -0
  91. package/src/components/editor/modules/toolbar/toolbar.ts +328 -0
  92. package/src/components/expanding-action/expanding-action.component.ts +2 -2
  93. package/src/components/expanding-action/expanding-action.scss +2 -2
  94. package/src/components/filter-wrapper/filter-wrapper.component.ts +91 -0
  95. package/src/components/filter-wrapper/filter-wrapper.scss +11 -0
  96. package/src/components/filter-wrapper/filter-wrapper.test.ts +10 -0
  97. package/src/components/filter-wrapper/index.ts +12 -0
  98. package/src/components/header/header.component.ts +1 -1
  99. package/src/components/header/header.scss +8 -1
  100. package/src/components/hover-container/hover-container.scss +39 -36
  101. package/src/components/icon/icon.component.ts +11 -5
  102. package/src/components/icon/icon.scss +15 -2
  103. package/src/components/inline-edit/inline-edit.component.ts +52 -6
  104. package/src/components/inline-edit/inline-edit.scss +15 -2
  105. package/src/components/input/input.scss +1 -1
  106. package/src/components/item/item.component.ts +30 -19
  107. package/src/components/item/item.scss +57 -23
  108. package/src/components/linked-select/linked-select.component.ts +5 -1
  109. package/src/components/menu/menu.component.ts +1 -0
  110. package/src/components/menu/menu.scss +1 -1
  111. package/src/components/menu-item/menu-item.component.ts +22 -4
  112. package/src/components/menu-item/menu-item.scss +54 -7
  113. package/src/components/navbar/navbar.component.ts +7 -1
  114. package/src/components/navbar/navbar.scss +26 -16
  115. package/src/components/option/option.component.ts +4 -1
  116. package/src/components/option/option.scss +9 -0
  117. package/src/components/page-nav/page-nav.component.ts +2 -2
  118. package/src/components/page-nav/page-nav.scss +4 -4
  119. package/src/components/panel/panel.component.ts +20 -9
  120. package/src/components/panel/panel.scss +5 -1
  121. package/src/components/popup/popup.component.ts +16 -2
  122. package/src/components/progress-tile/progress-tile.component.ts +10 -4
  123. package/src/components/progress-tile/progress-tile.scss +7 -4
  124. package/src/components/query-builder/query-builder.component.ts +1 -1
  125. package/src/components/radio/radio.scss +1 -1
  126. package/src/components/scroll-container/scroll-container.component.ts +56 -9
  127. package/src/components/scroll-container/scroll-container.scss +37 -2
  128. package/src/components/select/select.component.ts +3 -0
  129. package/src/components/select/select.scss +1 -1
  130. package/src/components/settings-container/index.ts +12 -0
  131. package/src/components/settings-container/settings-container.component.ts +226 -0
  132. package/src/components/settings-container/settings-container.scss +99 -0
  133. package/src/components/settings-container/settings-container.test.ts +10 -0
  134. package/src/components/skeleton/skeleton.scss +5 -4
  135. package/src/components/sp/sp.component.ts +2 -0
  136. package/src/components/sp/sp.scss +2 -0
  137. package/src/components/split-button/split-button.component.ts +24 -18
  138. package/src/components/split-pane/split-pane.component.ts +5 -5
  139. package/src/components/stat/stat.component.ts +5 -1
  140. package/src/components/stat/stat.scss +24 -1
  141. package/src/components/style/style.component.ts +25 -1
  142. package/src/components/tabs/tabs.component.ts +12 -1
  143. package/src/components/textarea/textarea.component.ts +3 -1
  144. package/src/components/textarea/textarea.scss +21 -2
  145. package/src/components/vertical-stepper/vertical-stepper.scss +1 -1
  146. package/src/internal/form.ts +3 -1
  147. package/src/internal/slot.ts +29 -3
  148. package/src/utilities/on.ts +7 -8
  149. package/src/utilities/query.ts +5 -1
  150. package/src/wc.scss +7 -0
  151. package/src/zinc.ts +5 -0
  152. package/src/components/editor/modules/dialog-module/dialog-module.component.ts +0 -289
  153. package/src/components/editor/modules/dialog-module/dialog-module.scss +0 -115
  154. package/src/components/editor/modules/dialog-module/dialog-module.ts +0 -99
  155. package/src/components/editor/modules/events/zn-show-canned-response-dialog.ts +0 -15
  156. package/src/components/editor/modules/menu-module/menu-module.component.ts +0 -149
  157. package/src/components/editor/modules/menu-module/menu-module.scss +0 -17
  158. package/src/components/editor/modules/menu-module/menu-module.ts +0 -203
@@ -1,5 +1,6 @@
1
- import {type CSSResultGroup, html, unsafeCSS} from 'lit';
1
+ import {type CSSResultGroup, html, unsafeCSS, PropertyValues} from 'lit';
2
2
  import ZincElement from '../../internal/zinc-element';
3
+ import {property, query} from "lit/decorators.js";
3
4
 
4
5
  import styles from './scroll-container.scss';
5
6
 
@@ -23,19 +24,65 @@ import styles from './scroll-container.scss';
23
24
  export default class ZnScrollContainer extends ZincElement {
24
25
  static styles: CSSResultGroup = unsafeCSS(styles);
25
26
 
26
- constructor() {
27
- super();
27
+ @property({attribute: 'start-scrolled', type: Boolean, reflect: true}) startScrolled: boolean = false;
28
28
 
29
- this.addEventListener('scroll-to-bottom', () => {
30
- setTimeout(() => {
31
- this.scrollTop = this.scrollHeight;
32
- }, 100);
33
- });
29
+ @query('.scroll-container')
30
+ private container: HTMLElement;
31
+
32
+ @query('.scroll-footer')
33
+ private footer: HTMLElement;
34
+
35
+ protected firstUpdated(_changedProperties: PropertyValues) {
36
+ super.firstUpdated(_changedProperties);
37
+ if (this.startScrolled && this.container) {
38
+ setTimeout(this.scrollEnd.bind(this), 10);
39
+ }
40
+ }
41
+
42
+ scrollEnd() {
43
+ this.container.scrollTop = this.container.scrollHeight;
44
+ }
45
+
46
+ private _footerResizeObserver?: ResizeObserver;
47
+
48
+ connectedCallback() {
49
+ super.connectedCallback();
50
+ if (this.startScrolled) {
51
+ const observer = new MutationObserver(() => {
52
+ setTimeout(this.scrollEnd.bind(this), 100);
53
+ if (this.footer) {
54
+ // Initialize height immediately
55
+ this.style.setProperty('--zn-scroll-footer-height', `${this.footer.clientHeight}px`);
56
+ // Attach ResizeObserver to watch for size changes
57
+ this._footerResizeObserver = new ResizeObserver(() => {
58
+ this.style.setProperty('--zn-scroll-footer-height', `${this.footer?.clientHeight ?? 0}px`);
59
+ });
60
+ this._footerResizeObserver.observe(this.footer);
61
+ }
62
+ });
63
+ observer.observe(this, {childList: true, subtree: true});
64
+ }
65
+ }
66
+
67
+ disconnectedCallback() {
68
+ super.disconnectedCallback();
69
+ this._footerResizeObserver?.disconnect();
70
+ this._footerResizeObserver = undefined;
34
71
  }
35
72
 
36
73
  render() {
37
74
  return html`
38
- <slot></slot>
75
+ <div class="container">
76
+ <div class="scroll-header">
77
+ <slot name="header"></slot>
78
+ </div>
79
+ <div class="scroll-container">
80
+ <slot></slot>
81
+ </div>
82
+ <div class="scroll-footer">
83
+ <slot name="footer"></slot>
84
+ </div>
85
+ </div>
39
86
  `;
40
87
  }
41
88
  }
@@ -1,6 +1,27 @@
1
1
  @use "../../wc";
2
2
 
3
3
  :host {
4
+ display: contents;
5
+ --zn-scroll-footer-height: 0px;
6
+ --zn-scroll-header-height: 0px;
7
+ }
8
+
9
+ .container {
10
+ max-height: 100%;
11
+ max-width: 100%;
12
+ height: 100%;
13
+ width: 100%;
14
+ display: flex;
15
+ flex-direction: column;
16
+ position: relative;
17
+ overflow: hidden;
18
+ }
19
+
20
+ :host([flex-end]) ::slotted(*) {
21
+ // margin-top: auto;
22
+ }
23
+
24
+ .scroll-container {
4
25
  @include wc.scrollbars;
5
26
  container-type: inline-size;
6
27
  display: flex;
@@ -10,8 +31,22 @@
10
31
  max-width: 100%;
11
32
  width: 100%;
12
33
  overflow-y: auto;
34
+ flex-grow: 1;
35
+ margin: 0;
36
+ padding: 0 0 var(--zn-scroll-footer-height, 0px) 0;
13
37
  }
14
38
 
15
- :host([flex-end]) ::slotted(*) {
16
- // margin-top: auto;
39
+ .scroll-header {
40
+ display: contents;
41
+ }
42
+
43
+ .scroll-footer {
44
+ padding: 0;
45
+ margin: 0;
46
+
47
+ position: absolute;
48
+ bottom: 0;
49
+ left: 0;
50
+ right: 0;
51
+ display: flex;
17
52
  }
@@ -623,6 +623,8 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
623
623
 
624
624
  // Update the value and display label
625
625
  if (this.multiple) {
626
+ this.getAllOptions().filter(el => el.multiple !== true).forEach(el => el.multiple = true);
627
+
626
628
  this.value = this.selectedOptions.map(el => el.value);
627
629
 
628
630
  if (this.placeholder && this.value.length === 0) {
@@ -632,6 +634,7 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
632
634
  this.displayLabel = this.localize.term('numOptionsSelected', this.selectedOptions.length);
633
635
  }
634
636
  } else {
637
+ this.getAllOptions().filter(el => el.multiple === true).forEach(el => el.multiple = false);
635
638
  const selectedOption = this.selectedOptions[0];
636
639
  this.value = selectedOption?.value ?? '';
637
640
  this.displayLabel = selectedOption?.getTextLabel() ?? '';
@@ -38,7 +38,7 @@
38
38
  font-family: var(--zn-input-font-family);
39
39
  font-weight: var(--zn-input-font-weight);
40
40
  letter-spacing: var(--zn-input-letter-spacing);
41
- box-shadow: var(--zn-shadow-small);
41
+ box-shadow: var(--zn-shadow-x-small);
42
42
  vertical-align: middle;
43
43
  overflow: hidden;
44
44
  cursor: pointer;
@@ -0,0 +1,12 @@
1
+ import ZnSettingsContainer from './settings-container.component';
2
+
3
+ export * from './settings-container.component';
4
+ export default ZnSettingsContainer;
5
+
6
+ ZnSettingsContainer.define('zn-settings-container');
7
+
8
+ declare global {
9
+ interface HTMLElementTagNameMap {
10
+ 'zn-settings-container': ZnSettingsContainer;
11
+ }
12
+ }
@@ -0,0 +1,226 @@
1
+ import {classMap} from "lit/directives/class-map.js";
2
+ import {type CSSResultGroup, html, unsafeCSS} from 'lit';
3
+ import {property, state} from "lit/decorators.js";
4
+ import {Store} from "../../internal/storage";
5
+ import {type ZnChangeEvent} from "../../events/zn-change";
6
+ import ZincElement from '../../internal/zinc-element';
7
+ import type ZnCheckbox from "../checkbox";
8
+
9
+ import styles from './settings-container.scss';
10
+ import {deepQuerySelectorAll} from "../../utilities/query";
11
+
12
+ interface SettingsContainerFilter {
13
+ attribute: string;
14
+ checked: boolean;
15
+ label: string;
16
+ itemSelector?: string;
17
+ }
18
+
19
+ /**
20
+ * @summary Short summary of the component's intended use.
21
+ * @documentation https://zinc.style/components/settings-container
22
+ * @status experimental
23
+ * @since 1.0
24
+ *
25
+ * @dependency zn-example
26
+ *
27
+ * @event zn-event-name - Emitted as an example.
28
+ *
29
+ * @slot - The default slot.
30
+ * @slot example - An example slot.
31
+ *
32
+ * @csspart base - The component's base wrapper.
33
+ *
34
+ * @cssproperty --example - An example CSS custom property.
35
+ */
36
+ export default class ZnSettingsContainer extends ZincElement {
37
+ static styles: CSSResultGroup = unsafeCSS(styles);
38
+
39
+ @state() filters: SettingsContainerFilter[] = [];
40
+
41
+ @property() position: 'top-end' | 'top-start' | 'bottom-end' | 'bottom-start' = 'bottom-start';
42
+
43
+ @property({attribute: 'store-key'}) storeKey: string;
44
+ @property({attribute: 'no-scroll'}) noScroll: boolean;
45
+
46
+ private _mutationObserver: MutationObserver | null = null;
47
+
48
+ private _updateFiltersScheduled = false;
49
+
50
+ private _store: Store;
51
+
52
+ private _hiddenElements: Set<Element> = new Set();
53
+
54
+ connectedCallback() {
55
+ super.connectedCallback();
56
+
57
+ this._store = new Store(window.sessionStorage, this.storeKey);
58
+
59
+ this.recomputeFiltersFromSlot();
60
+ this.updateFilters();
61
+
62
+ // Load saved filter states
63
+ if (this.storeKey) {
64
+ const savedFilters = this._store.get('filters');
65
+ if (savedFilters) {
66
+ const parsedFilters = JSON.parse(savedFilters) as Record<string, boolean>;
67
+ this.filters = this.filters.map(filter => ({
68
+ ...filter,
69
+ checked: Object.prototype.hasOwnProperty.call(parsedFilters, filter.attribute) ? parsedFilters[filter.attribute] : filter.checked
70
+ }));
71
+ this.updateFilters();
72
+ }
73
+ }
74
+
75
+ this._mutationObserver = new MutationObserver(mutations => {
76
+ for (const mutation of mutations) {
77
+ if (mutation.type === 'attributes' && mutation.attributeName === 'hidden') {
78
+ continue;
79
+ }
80
+ this.scheduleUpdateFilters();
81
+ break;
82
+ }
83
+ });
84
+ this._mutationObserver.observe(this, {childList: true, subtree: true, attributes: true});
85
+ }
86
+
87
+ disconnectedCallback() {
88
+ super.disconnectedCallback();
89
+ if (this._mutationObserver) {
90
+ this._mutationObserver.disconnect();
91
+ this._mutationObserver = null;
92
+ }
93
+ }
94
+
95
+ // Debounced scheduling to avoid excessive updates on rapid DOM mutations
96
+ private scheduleUpdateFilters() {
97
+ if (this._updateFiltersScheduled) return;
98
+ this._updateFiltersScheduled = true;
99
+ Promise.resolve().then(() => {
100
+ this._updateFiltersScheduled = false;
101
+ this.updateFilters();
102
+ });
103
+ }
104
+
105
+ private handleContentSlotChange = () => {
106
+ this.updateFilters();
107
+ };
108
+
109
+ private handleFiltersSlotChange = () => {
110
+ this.recomputeFiltersFromSlot();
111
+ this.updateFilters();
112
+ };
113
+
114
+ private recomputeFiltersFromSlot() {
115
+ const existingChecked = new Map(this.filters.map(f => [f.attribute, f.checked]));
116
+ const slotFilters = this.querySelectorAll('[slot="filter"]');
117
+ const nextFilters: SettingsContainerFilter[] = [];
118
+ slotFilters.forEach(filter => {
119
+ const attribute = filter.getAttribute('attribute');
120
+ if (!attribute) return;
121
+ const defaultChecked = filter.getAttribute('default') === 'true';
122
+ const checked = existingChecked.has(attribute) ? !!existingChecked.get(attribute) : defaultChecked;
123
+ const label = filter.textContent || 'Unnamed Filter';
124
+ const itemSelector = filter.getAttribute('item-selector') || '*';
125
+ nextFilters.push({attribute, checked, label, itemSelector});
126
+ });
127
+ this.filters = nextFilters;
128
+ }
129
+
130
+ updateFilters() {
131
+ // reset all items
132
+ this._hiddenElements.forEach(el => el.removeAttribute('hidden'));
133
+
134
+ // apply filters
135
+ this.filters.forEach(filter => {
136
+ let items;
137
+ const attrAppend = filter.attribute === "*" ? `` : `[${filter.attribute}]`;
138
+ if (filter.itemSelector && filter.itemSelector.startsWith('>')) {
139
+ items = deepQuerySelectorAll(filter.itemSelector.substring(1) + attrAppend, this, "");
140
+ } else {
141
+ items = this.querySelectorAll(filter.itemSelector + attrAppend);
142
+ }
143
+ items.forEach(item => {
144
+ if (filter.checked) {
145
+ item.removeAttribute('hidden');
146
+ } else {
147
+ item.setAttribute('hidden', 'true');
148
+ this._hiddenElements.add(item);
149
+ }
150
+ });
151
+ });
152
+ }
153
+
154
+ updateFilter(e: ZnChangeEvent) {
155
+ const attribute = (e.target as ZnCheckbox).getAttribute('data-attribute');
156
+ const checked = (e.target as ZnCheckbox).isChecked
157
+
158
+ this.filters = this.filters.map(filter => {
159
+ if (filter.attribute === attribute) {
160
+ return {...filter, checked};
161
+ }
162
+ return filter;
163
+ });
164
+
165
+ // Save filter states
166
+ if (this.storeKey) {
167
+ const filterStates = this.filters.reduce((acc: Record<string, boolean>, filter) => {
168
+ acc[filter.attribute] = filter.checked;
169
+ return acc;
170
+ }, {} satisfies Record<string, boolean>);
171
+ this._store.set('filters', JSON.stringify(filterStates));
172
+ }
173
+
174
+ this.updateFilters();
175
+ }
176
+
177
+ render() {
178
+ let placement = 'top-start';
179
+
180
+ switch (this.position) {
181
+ case 'top-end':
182
+ placement = 'bottom-end';
183
+ break;
184
+ case 'top-start':
185
+ placement = 'bottom-start';
186
+ break;
187
+ case 'bottom-end':
188
+ placement = 'top-end';
189
+ break;
190
+ case 'bottom-start':
191
+ placement = 'top-start';
192
+ break;
193
+ }
194
+
195
+ return html`
196
+ <div class="${classMap({
197
+ 'container': true,
198
+ 'container--scroll': !this.noScroll,
199
+ })}">
200
+ <div class="scroll-content">
201
+ <slot @slotchange="${this.handleContentSlotChange}"></slot>
202
+ </div>
203
+ <zn-dropdown placement="${placement}" class="${classMap({
204
+ 'setting-container__dropdown': true,
205
+ 'setting-container__dropdown--top-end': this.position === 'top-end',
206
+ 'setting-container__dropdown--top-start': this.position === 'top-start',
207
+ 'setting-container__dropdown--bottom-end': this.position === 'bottom-end',
208
+ 'setting-container__dropdown--bottom-start': this.position === 'bottom-start',
209
+ })}">
210
+ <zn-icon class="setting-container__toggle-button" slot="trigger" size="24" src="settings" round></zn-icon>
211
+ <div class="settings-container__dropdown-content">
212
+ <slot name="filter" style="display: none;" @slotchange="${this.handleFiltersSlotChange}"></slot>
213
+ ${this.filters.map(filter => html`
214
+ <zn-checkbox class="settings-container__dropdown-item"
215
+ data-attribute="${filter.attribute}"
216
+ ?checked="${filter.checked}"
217
+ @zn-change="${this.updateFilter}">
218
+ ${filter.label}
219
+ </zn-checkbox>
220
+ `)}
221
+ </div>
222
+ </zn-dropdown>
223
+ </div>
224
+ `;
225
+ }
226
+ }
@@ -0,0 +1,99 @@
1
+ @use "../../wc";
2
+
3
+ :host {
4
+ display: contents;
5
+ }
6
+
7
+ .container {
8
+ padding-bottom: 30px;
9
+ }
10
+
11
+ .container--scroll {
12
+ height: 100%;
13
+ width: 100%;
14
+ overflow: hidden;
15
+ position: relative;
16
+ }
17
+
18
+ .container--scroll .scroll-content {
19
+ height: 100%;
20
+ width: 100%;
21
+ overflow: auto;
22
+ box-sizing: border-box;
23
+ }
24
+
25
+ .setting-container__dropdown {
26
+ z-index: 10;
27
+ position: absolute;
28
+ border-radius: 50%;
29
+ width: 32px;
30
+ height: 32px;
31
+ padding: 4px;
32
+ background: rgba(var(--zn-panel, 0.8));
33
+ box-shadow: var(--zn-shadow-small);
34
+ transition: bottom 0.2s ease;
35
+ opacity: 0.7;
36
+ transition-duration: 0.3s;
37
+ transition-property: opacity;
38
+
39
+ &:hover {
40
+ background: rgba(var(--zn-panel, 1));
41
+ }
42
+
43
+ &--top-end {
44
+ top: var(--zn-spacing-medium);
45
+ right: var(--zn-spacing-medium);
46
+ bottom: auto;
47
+ }
48
+
49
+ &--top-start {
50
+ top: var(--zn-spacing-medium);
51
+ right: auto;
52
+ left: var(--zn-spacing-medium);
53
+ bottom: auto;
54
+ }
55
+
56
+ &--bottom-end {
57
+ bottom: calc(var(--zn-spacing-medium) + var(--zn-scroll-footer-height, 0px));
58
+ right: var(--zn-spacing-medium);
59
+ top: auto;
60
+ }
61
+
62
+ &--bottom-start {
63
+ bottom: calc(var(--zn-spacing-medium) + var(--zn-scroll-footer-height, 0px));
64
+ left: var(--zn-spacing-medium);
65
+ top: auto;
66
+ }
67
+ }
68
+
69
+ .setting-container__dropdown[open], .setting-container__dropdown:hover {
70
+ opacity: 1;
71
+ }
72
+
73
+ .setting-container__dropdown[open] .setting-container__toggle-button::part(icon), .setting-container__toggle-button:hover::part(icon) {
74
+ color: rgb(var(--zn-primary));
75
+ cursor: pointer;
76
+ transition-duration: 0.9s;
77
+ transition-property: rotate, color;
78
+ rotate: 380deg;
79
+ transition-timing-function: ease-in-out;
80
+ }
81
+
82
+ zn-button {
83
+ border-radius: var(--zn-border-radius-medium);
84
+ }
85
+
86
+ .settings-container__dropdown-content {
87
+ display: flex;
88
+ flex-direction: column;
89
+ gap: var(--zn-spacing-large);
90
+ background-color: rgb(var(--zn-panel));
91
+ padding: var(--zn-spacing-large);
92
+ box-shadow: var(--zn-shadow-small);
93
+ border-radius: var(--zn-border-radius-medium);
94
+ max-width: var(--zn-size-mpanel);
95
+ width: fit-content;
96
+ z-index: 20;
97
+ border: 1px solid rgb(var(--zn-border-color));
98
+ margin-bottom: 10px;
99
+ }
@@ -0,0 +1,10 @@
1
+ import '../../../dist/zn.min.js';
2
+ import { expect, fixture, html } from '@open-wc/testing';
3
+
4
+ describe('<zn-settings-container>', () => {
5
+ it('should render a component', async () => {
6
+ const el = await fixture(html` <zn-settings-container></zn-settings-container> `);
7
+
8
+ expect(el).to.exist;
9
+ });
10
+ });
@@ -9,19 +9,20 @@
9
9
  height: var(--skeleton-height);
10
10
  width: var(--skeleton-width);
11
11
  border-radius: var(--skeleton-border-radius);
12
+ background-color: lightgrey;
12
13
 
13
14
  @media (prefers-reduced-motion: reduce) {
14
15
  background-repeat: no-repeat;
15
- background-color: rgba(lightgrey, 0.8);
16
+ background-color: lightgrey;
16
17
  }
17
18
 
18
19
  @media (prefers-reduced-motion: no-preference) {
19
20
  background-repeat: no-repeat;
20
21
  background-image: linear-gradient(
21
22
  90deg,
22
- rgba(lightgrey, 0) 0%,
23
- rgba(lightgrey, 0.8) 50%,
24
- rgba(lightgrey, 0) 100%
23
+ rgba(255, 255, 255, 0) 0%,
24
+ rgba(255, 255, 255, 0.8) 50%,
25
+ rgba(255, 255, 255, 0) 100%
25
26
  );
26
27
  background-size: 200% 100%;
27
28
  background-position: -150% 0;
@@ -51,6 +51,7 @@ export default class ZnSp extends ZincElement {
51
51
  @property({attribute: 'flush-l', type: Boolean, reflect: true}) flushL: boolean = false;
52
52
  @property({attribute: 'flush-r', type: Boolean, reflect: true}) flushR: boolean = false;
53
53
  @property({attribute: 'width-container', type: Boolean, reflect: true}) widthContainer: boolean = false;
54
+ @property({attribute: 'form-container', type: Boolean, reflect: true}) formContainer: boolean = false;
54
55
 
55
56
  connectedCallback() {
56
57
  if (this.gap) {
@@ -79,6 +80,7 @@ export default class ZnSp extends ZincElement {
79
80
  'sp--flush-l': this.flushL,
80
81
  'sp--flush-r': this.flushR,
81
82
  'width-container': this.widthContainer,
83
+ 'form-container': this.formContainer,
82
84
  })}">
83
85
  <slot></slot>
84
86
  </div>`;
@@ -10,12 +10,14 @@
10
10
  }
11
11
 
12
12
  .sp {
13
+ position: relative;
13
14
  display: flex;
14
15
  flex-direction: column;
15
16
  flex-grow: 0;
16
17
  padding: var(--zn-sp-padding);
17
18
  gap: var(--zn-sp-gap);
18
19
  width: 100%;
20
+ height: 100%;
19
21
  //max-width: var(--zn-container-hd); //don't worry about max width just yet
20
22
  margin: 0 auto;
21
23
 
@@ -3,8 +3,8 @@ import {defaultValue} from "../../internal/default-value";
3
3
  import {FormControlController, validValidityState} from "../../internal/form";
4
4
  import {ifDefined} from "lit/directives/if-defined.js";
5
5
  import {property, query} from 'lit/decorators.js';
6
- import type {ZincFormControl} from '../../internal/zinc-element';
7
6
  import ZincElement from '../../internal/zinc-element';
7
+ import type {ZincFormControl} from '../../internal/zinc-element';
8
8
  import type {ZnMenuSelectEvent} from "../../events/zn-menu-select";
9
9
  import type ZnButton from "../button";
10
10
  import type ZnDropdown from "../dropdown";
@@ -51,14 +51,12 @@ export default class ZnSplitButton extends ZincElement implements ZincFormContro
51
51
 
52
52
  connectedCallback() {
53
53
  super.connectedCallback();
54
- this.addEventListener('click', this.handleClick)
55
54
  this.addEventListener('zn-menu-select', this.handleMenuItemClick);
56
55
  this.defaultValue = this.value;
57
56
  }
58
57
 
59
58
  disconnectedCallback() {
60
59
  super.disconnectedCallback();
61
- this.removeEventListener('click', this.handleClick);
62
60
  this.removeEventListener('zn-menu-select', this.handleMenuItemClick);
63
61
  }
64
62
 
@@ -73,10 +71,6 @@ export default class ZnSplitButton extends ZincElement implements ZincFormContro
73
71
  }
74
72
  }
75
73
 
76
- public handleClick(e: MouseEvent) {
77
- e.stopPropagation();
78
- }
79
-
80
74
  public handleTriggerClick() {
81
75
  this.value = this.defaultValue;
82
76
 
@@ -87,17 +81,8 @@ export default class ZnSplitButton extends ZincElement implements ZincFormContro
87
81
 
88
82
  render() {
89
83
  return html`
90
- <zn-dropdown placement="bottom-start">
91
- <div slot="trigger">
92
- <zn-button-group>
93
- <zn-button id="trigger-btn"
94
- href=${ifDefined(this.href)}
95
- @click=${this.handleTriggerClick}>
96
- ${this.caption}
97
- </zn-button>
98
- <zn-button icon="keyboard_arrow_down"></zn-button>
99
- </zn-button-group>
100
- </div>
84
+ <zn-dropdown placement="bottom-end">
85
+ ${this.renderTriggerSlot()}
101
86
  <div>
102
87
  <slot name="menu"></slot>
103
88
  </div>
@@ -105,6 +90,27 @@ export default class ZnSplitButton extends ZincElement implements ZincFormContro
105
90
  `;
106
91
  }
107
92
 
93
+ private renderTriggerSlot() {
94
+ const hasTriggerSlot = !!this.querySelector('[slot="trigger"]');
95
+ if (hasTriggerSlot) {
96
+ return html`
97
+ <slot name="trigger" slot="trigger"></slot>`;
98
+ }
99
+
100
+ return html`
101
+ <div slot="trigger">
102
+ <zn-button-group>
103
+ <zn-button id="trigger-btn"
104
+ href=${ifDefined(this.href)}
105
+ @click=${this.handleTriggerClick}>
106
+ ${this.caption}
107
+ </zn-button>
108
+ <zn-button icon="keyboard_arrow_down"></zn-button>
109
+ </zn-button-group>
110
+ </div>
111
+ `;
112
+ }
113
+
108
114
  checkValidity(): boolean {
109
115
  if (this._isButton() && this.button) {
110
116
  return this.button.checkValidity();
@@ -1,10 +1,10 @@
1
- import {eventOptions, property} from 'lit/decorators.js';
2
1
  import {type CSSResultGroup, html, unsafeCSS} from 'lit';
2
+ import {eventOptions, property} from 'lit/decorators.js';
3
+ import {on} from "../../utilities/on";
4
+ import {Store} from "../../internal/storage";
3
5
  import ZincElement from '../../internal/zinc-element';
4
6
 
5
7
  import styles from './split-pane.scss';
6
- import {Store} from "../../internal/storage";
7
- import {on} from "../../utilities/on";
8
8
 
9
9
  /**
10
10
  * @summary Short summary of the component's intended use.
@@ -64,7 +64,7 @@ export default class ZnSplitPane extends ZincElement {
64
64
  on(this, 'click', '[split-pane-focus]', (e: Event & { selectedTarget: EventTarget }) => {
65
65
  e.preventDefault();
66
66
  e.stopPropagation();
67
- this._setFocusPane(parseInt((e.selectedTarget as HTMLElement).getAttribute('split-pane-focus') as string));
67
+ this._setFocusPane(parseInt((e.selectedTarget as HTMLElement).getAttribute('split-pane-focus')!));
68
68
  });
69
69
  }
70
70
 
@@ -160,7 +160,7 @@ export default class ZnSplitPane extends ZincElement {
160
160
  _setFocusPane(idx: number) {
161
161
  this._focusPane = idx;
162
162
  this.querySelectorAll('ul#split-nav li').forEach((el) => {
163
- el.classList.toggle('active', parseInt(el.getAttribute('idx') as string) == idx);
163
+ el.classList.toggle('active', parseInt(el.getAttribute('idx')!) == idx);
164
164
  });
165
165
  }
166
166