@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
@@ -0,0 +1,98 @@
1
+ @use "../../../../../scss/boot"; // Need to include the global styles again for Air Picker to work properly
2
+
3
+ .toolbar {
4
+ display: flex;
5
+ flex-wrap: wrap;
6
+ align-items: center;
7
+
8
+ &__group {
9
+ display: flex;
10
+ align-items: center;
11
+ position: relative;
12
+
13
+ &--overflow {
14
+ display: none;
15
+ }
16
+
17
+ &--empty {
18
+ display: none;
19
+ }
20
+
21
+ /* Divider between toolbar groups (only when the previous group is not empty and not hidden) */
22
+ &:not(&--empty):not(&--hidden) + &::before {
23
+ content: "";
24
+ display: inline-block;
25
+ width: 1px;
26
+ height: 18px;
27
+ background-color: var(--zn-color-gray-300);
28
+ opacity: 0.8;
29
+ margin-inline: var(--zn-spacing-2x-small);
30
+ border-radius: 10px;
31
+ }
32
+
33
+ /* Ensure divider appears when a group has any previous visible group (skips hidden/empty in between) */
34
+ &--has-prev-visible::before {
35
+ content: "";
36
+ display: inline-block;
37
+ width: 1px;
38
+ height: 18px;
39
+ background-color: var(--zn-color-gray-300);
40
+ opacity: 0.8;
41
+ margin-inline: var(--zn-spacing-2x-small);
42
+ border-radius: 10px;
43
+ }
44
+ }
45
+
46
+ &__dropdown-trigger {
47
+ width: 44px;
48
+ height: 28px;
49
+ margin: 3px 2px;
50
+
51
+ &::part(icon) {
52
+ margin-left: 4px;
53
+ }
54
+ }
55
+
56
+ &__format-button,
57
+ &__action-button,
58
+ &__overflow-trigger {
59
+ width: 28px;
60
+ height: 28px;
61
+ margin: 3px 2px;
62
+ }
63
+
64
+ /* Move underline icon down a bit */
65
+ &__format-button[icon="format_underlined"]::part(base) {
66
+ position: relative;
67
+ top: 1px;
68
+ }
69
+ }
70
+
71
+ .color-icon {
72
+ width: 15px;
73
+ height: 15px;
74
+ display: block;
75
+ border-radius: 100%;
76
+ flex-shrink: 0;
77
+
78
+ @each $name, $color in (
79
+ red: var(--zn-color-red-500),
80
+ blue: var(--zn-color-blue-500),
81
+ orange: var(--zn-color-orange-500),
82
+ yellow: var(--zn-color-yellow-400),
83
+ indigo: var(--zn-color-indigo-500),
84
+ violet: var(--zn-color-violet-500),
85
+ green: var(--zn-color-green-500),
86
+ pink: var(--zn-color-pink-500),
87
+ gray: var(--zn-color-gray-500)
88
+ ) {
89
+ &--#{"" + $name} {
90
+ background-color: #{$color};
91
+ }
92
+ }
93
+ }
94
+
95
+ /* Line up unset value with color chips */
96
+ .color-icon--unset {
97
+ margin-inline-end: var(--zn-spacing-x-small);
98
+ }
@@ -0,0 +1,328 @@
1
+ import './toolbar.component';
2
+ import Quill from "quill";
3
+ import QuillToolbar from "quill/modules/toolbar";
4
+ import type DialogComponent from "../dialog/dialog.component";
5
+ import type Emoji from "../emoji/emoji";
6
+ import type ToolbarComponent from "./toolbar.component";
7
+ import type ZnDropdown from "../../../dropdown";
8
+ import type ZnMenuItem from "../../../menu-item";
9
+
10
+ class Toolbar extends QuillToolbar {
11
+ private readonly _quill: Quill;
12
+ private readonly _component: ToolbarComponent;
13
+ private _lastDialogUri?: string;
14
+ private _formatters: Element[] = [];
15
+
16
+ constructor(quill: Quill, options: {
17
+ container: ToolbarComponent;
18
+ handlers?: Record<string, (value?: any) => void>;
19
+ }) {
20
+ super(quill, options);
21
+
22
+ // Add handlers after parent Toolbar initialization
23
+ this.addHandler('attachment', () => null);
24
+ this.addHandler('date', () => this._openDatePicker());
25
+ this.addHandler('divider', () => this._insertDivider());
26
+ this.addHandler('redo', () => quill.history.redo());
27
+ this.addHandler('undo', () => quill.history.undo());
28
+ this.addHandler('dialog', (value: string) => this._openDialog(value));
29
+
30
+ this._quill = quill;
31
+ this._component = options.container;
32
+
33
+ this._component.updateComplete.then(() => {
34
+ this._attachToolbarHandlers();
35
+ this._syncToolbarState = this._syncToolbarState.bind(this);
36
+ this._component.addEventListener('zn-toolbar-overflow-updated', this._handleOverflowUpdate);
37
+
38
+ if (quill) {
39
+ quill.on('selection-change', this._syncToolbarState);
40
+ quill.root?.addEventListener('click', this._syncToolbarState);
41
+ quill.on('text-change', this._syncToolbarState);
42
+ this._syncToolbarState();
43
+ }
44
+ });
45
+ }
46
+
47
+ public callFormat(key: string, value?: string | boolean | undefined) {
48
+ const handler = (this.handlers?.[key] as ((value?: any) => void) | undefined);
49
+ if (value === undefined) {
50
+ if (key === 'header' || key === 'color') {
51
+ value = false; // False for text normal or default color
52
+ }
53
+ if (key === 'link') {
54
+ value = true; // True for creating a link
55
+ }
56
+ }
57
+ if (typeof handler === 'function') {
58
+ handler.call(this, value);
59
+ return;
60
+ }
61
+ if (key === 'clean') {
62
+ const range = this._quill.getSelection();
63
+ if (range) {
64
+ this._quill.removeFormat(range.index, range.length || 0);
65
+ } else {
66
+ this._quill.removeFormat(0, this._quill.getLength());
67
+ }
68
+ return;
69
+ }
70
+ const range = this._quill.getSelection();
71
+ const formats: Record<string, unknown> = range ? this._quill.getFormat(range) : {};
72
+ const current = formats[key];
73
+ const next: boolean | string | number = value !== undefined ? value as boolean | string | number : !(current as boolean);
74
+ this._quill.format(key, next);
75
+ }
76
+
77
+ public trigger(key: string) {
78
+ const container = this.container;
79
+ if (!container) return;
80
+
81
+ const matches = this._formatters.filter(
82
+ formatter => formatter.getAttribute('data-toolbar-key') === key && formatter.tagName === 'ZN-BUTTON'
83
+ );
84
+
85
+ const tool = (matches?.length ? (matches[0] as HTMLElement) : null);
86
+ if (tool) {
87
+ tool.click();
88
+ return;
89
+ }
90
+
91
+ const shadowRoot = this._component.shadowRoot;
92
+ const element = shadowRoot?.querySelector(`[data-toolbar-key="${key}"]`) as HTMLElement | null;
93
+ if (element) {
94
+ const format = element.getAttribute('data-format');
95
+ const type = element.getAttribute('data-format-type') ?? undefined;
96
+ if (format) {
97
+ this.callFormat(format, type);
98
+ }
99
+ }
100
+ }
101
+
102
+ private _attachToolbarHandlers() {
103
+ const shadowRoot = this._component.shadowRoot;
104
+ const shadowFormatters = shadowRoot?.querySelectorAll('[data-format]') ?? [];
105
+ const slottedFormatters: Element[] = [];
106
+ const slot = shadowRoot?.querySelector('slot');
107
+ if (slot) {
108
+ const assigned = slot.assignedElements({flatten: true});
109
+ assigned.forEach(element => {
110
+ const formatElement = element.shadowRoot?.querySelector('[data-format]');
111
+ if (formatElement) {
112
+ slottedFormatters.push(formatElement);
113
+ }
114
+ });
115
+ }
116
+
117
+ this._formatters = [...shadowFormatters, ...slottedFormatters];
118
+
119
+ if (shadowRoot) {
120
+ shadowRoot.addEventListener('click', this._onToolbarClick);
121
+ }
122
+ }
123
+
124
+ private _onToolbarClick = (e: Event) => {
125
+ const path = (e.composedPath()) || [];
126
+ let targetEl: HTMLElement | null = null;
127
+
128
+ for (const node of path as EventTarget[]) {
129
+ if (node instanceof HTMLElement) {
130
+ if (node.hasAttribute && node.hasAttribute('data-format')) {
131
+ targetEl = node;
132
+ break;
133
+ }
134
+ }
135
+ }
136
+ if (!targetEl) return;
137
+
138
+ const format = targetEl.getAttribute('data-format');
139
+ if (!format) return;
140
+
141
+ const type: string | undefined = targetEl.getAttribute('data-format-type') ?? undefined;
142
+ this.callFormat(format, type);
143
+ }
144
+
145
+ private _syncToolbarState() {
146
+ if (!this._quill) return;
147
+
148
+ const range = this._quill.getSelection();
149
+ if (!range) return;
150
+
151
+ const formats: Record<string, any> = this._quill.getFormat(range);
152
+ if (!formats) return;
153
+
154
+ this._syncButtonState('format_bold', !!formats.bold);
155
+ this._syncButtonState('format_italic', !!formats.italic);
156
+ this._syncButtonState('format_underlined', !!formats.underline);
157
+
158
+ this._updateHeadingFormatMenu(formats);
159
+ this._updateListFormatMenu(formats);
160
+ this._updateTextFormatMenu(formats);
161
+ this._updateColorFormatMenu(formats);
162
+
163
+ this._updateDropdownTrigger('zn-dropdown.toolbar__header-dropdown', 'match_case');
164
+ this._updateDropdownTrigger('zn-dropdown.toolbar__list-dropdown', 'lists');
165
+ }
166
+
167
+ private _updateHeadingFormatMenu(formats: Record<string, any>) {
168
+ const wanted = formats.header ? String(formats.header) : ''; // Empty string for text normal
169
+ this._updateMenuCheckedState('zn-dropdown.toolbar__header-dropdown zn-menu zn-menu-item[data-format]', 'data-format-type', wanted);
170
+ }
171
+
172
+ private _updateListFormatMenu(formats: Record<string, any>) {
173
+ const list = formats.list as string | null;
174
+ const listValue = (list === 'ordered' || list === 'bullet' || list === 'checked') ? list : null;
175
+ this._updateMenuCheckedState('zn-dropdown.toolbar__list-dropdown zn-menu zn-menu-item[data-format]', 'data-format-type', listValue);
176
+ }
177
+
178
+ private _updateTextFormatMenu(formats: Record<string, any>) {
179
+ const selector = 'zn-dropdown.toolbar__format-dropdown zn-menu zn-menu-item[data-format]';
180
+ const attr = 'data-format';
181
+ const wanted = this._getTextFormats(formats);
182
+
183
+ this._updateMenuCheckedState(selector, attr, wanted);
184
+ }
185
+
186
+ private _updateColorFormatMenu(formats: Record<string, any>) {
187
+ const color = (typeof formats.color === 'string') ? formats.color : '';
188
+ this._updateMenuCheckedState('zn-dropdown.toolbar__color-dropdown zn-menu zn-menu-item[data-format]', 'data-format-type', color);
189
+ }
190
+
191
+ private _getTextFormats(formats: Record<string, any>) {
192
+ const wanted: string[] = [];
193
+ if (formats.strike) {
194
+ wanted.push('strike');
195
+ }
196
+ if (formats.blockquote) {
197
+ wanted.push('blockquote');
198
+ }
199
+ if (formats.code) {
200
+ wanted.push('code');
201
+ }
202
+ if (Object.prototype.hasOwnProperty.call(formats, 'code-block')) {
203
+ wanted.push('code-block');
204
+ }
205
+ return wanted;
206
+ }
207
+
208
+ private _updateMenuCheckedState(selector: string, matchAttr: string, wanted: string | string[] | null) {
209
+ const items = this._component.shadowRoot?.querySelectorAll(selector) as NodeListOf<ZnMenuItem> | undefined;
210
+ if (!items?.length) return;
211
+
212
+ const wantedValues: string[] = wanted === null ? [] : Array.isArray(wanted) ? wanted : [wanted];
213
+
214
+ items.forEach((item: ZnMenuItem) => {
215
+ const value = item.getAttribute(matchAttr) ?? '';
216
+ if (item.getAttribute('type') === 'checkbox') {
217
+ item.checked = wantedValues.includes(value);
218
+ }
219
+ });
220
+ }
221
+
222
+ private _updateDropdownTrigger(dropdownSelector: string, defaultIconSrc: string) {
223
+ const shadowRoot = this._component.shadowRoot;
224
+ const dropdown = shadowRoot?.querySelector(dropdownSelector) as HTMLElement | null;
225
+ if (!dropdown) return;
226
+
227
+ const trigger = dropdown.querySelector('zn-button[slot="trigger"]') as HTMLElement | null;
228
+ if (!trigger) return;
229
+
230
+ const menu = dropdown.querySelector('zn-menu');
231
+ const items = menu?.querySelectorAll('zn-menu-item') as NodeListOf<ZnMenuItem> | undefined;
232
+
233
+ let iconSrc = defaultIconSrc;
234
+ let iconColor = 'default';
235
+ if (items?.length) {
236
+ items.forEach((item: ZnMenuItem) => {
237
+ const checked = item.checked ?? (item.hasAttribute('checked'));
238
+ if (checked) {
239
+ const icon = item.querySelector('zn-icon')!;
240
+ iconSrc = icon?.getAttribute('src') ?? iconSrc;
241
+ iconColor = 'primary';
242
+ }
243
+ });
244
+ }
245
+
246
+ trigger.innerHTML = `<zn-icon src="${iconSrc}" color="${iconColor}" size="18"></zn-icon>`;
247
+ }
248
+
249
+ private _syncButtonState(icon: string, active: boolean) {
250
+ const button = this._component.shadowRoot?.querySelector(`zn-button[icon="${icon}"]`) as HTMLElement | null;
251
+ if (!button) return;
252
+ if (active) {
253
+ button.classList.add('ql-active');
254
+ button.setAttribute('icon-color', 'primary');
255
+ } else {
256
+ button.classList.remove('ql-active');
257
+ button.removeAttribute('icon-color');
258
+ }
259
+ }
260
+
261
+ private _insertDivider() {
262
+ if (!this._quill) return;
263
+
264
+ const selection = this._quill.getSelection(true);
265
+ let index = selection ? selection.index + selection.length : this._quill.getLength();
266
+
267
+ const prevChar = index > 0 ? this._quill.getText(index - 1, 1) : '\n';
268
+ if (prevChar !== '\n') {
269
+ this._quill.insertText(index, '\n', Quill.sources.USER);
270
+ index += 1;
271
+ }
272
+
273
+ this._quill.insertEmbed(index, 'hr', true, Quill.sources.USER);
274
+ this._quill.insertText(index + 1, '\n', Quill.sources.USER);
275
+ this._quill.setSelection(index + 1, 0, Quill.sources.USER);
276
+
277
+ this._syncToolbarState();
278
+ }
279
+
280
+ private _openDatePicker() {
281
+ const shadow = this._component.shadowRoot;
282
+ if (!shadow) return;
283
+
284
+ const button = shadow.querySelector(`zn-button.toolbar__date-dropdown-trigger`) as HTMLElement | null;
285
+ const isVisible = (el: HTMLElement | null) => (el?.offsetParent !== null);
286
+
287
+ if (isVisible(button)) {
288
+ button!.click();
289
+ return;
290
+ }
291
+
292
+ const overflowDropdown = shadow.querySelector('zn-dropdown.toolbar__overflow') as ZnDropdown | null;
293
+ if (overflowDropdown) {
294
+ overflowDropdown.show().then();
295
+
296
+ const overflowMenu = shadow.querySelector('.toolbar__overflow-menu') as HTMLElement | null;
297
+ const dateParentItem = overflowMenu?.querySelector('zn-menu-item[data-overflow-source="date"]') as HTMLElement | null;
298
+
299
+ if (dateParentItem) {
300
+ // Trigger submenu open by simulating hover/focus
301
+ dateParentItem.dispatchEvent(new MouseEvent('mouseover', {bubbles: true}));
302
+ dateParentItem.focus?.();
303
+ }
304
+ }
305
+ }
306
+
307
+ private _openDialog(uri: string) {
308
+ if (this._lastDialogUri === uri) {
309
+ const dialog = document.querySelector(`zn-editor-dialog`) as DialogComponent | null;
310
+ if (!dialog) return;
311
+
312
+ dialog.dialogEl.showModal();
313
+ }
314
+
315
+ const dialog = document.querySelector(`zn-editor-dialog`) as DialogComponent | null;
316
+ if (!dialog) return;
317
+
318
+ dialog.dialogEl.showModal();
319
+ dialog.setContent(`<app-space id="app-editor-modal" allow-scripts auto-load uri="${uri}"></app-space>`);
320
+ }
321
+
322
+ private _handleOverflowUpdate = () => {
323
+ const emoji = this._quill.getModule('emoji') as Emoji;
324
+ emoji?.initPicker();
325
+ }
326
+ }
327
+
328
+ export default Toolbar;
@@ -281,7 +281,7 @@ export default class ZnExpandingAction extends ZincElement {
281
281
  <zn-button slot="trigger"
282
282
  class="expanding-action__button"
283
283
  color="transparent"
284
- size="x-small"
284
+ size="medium"
285
285
  icon="${this.icon}"
286
286
  icon-color="${this.color}"
287
287
  icon-size="20"
@@ -303,7 +303,7 @@ export default class ZnExpandingAction extends ZincElement {
303
303
  <zn-button slot="trigger"
304
304
  class="expanding-action__button expanding-action__close-icon"
305
305
  color="transparent"
306
- size="x-small"
306
+ size="medium"
307
307
  @click="${this.handleIconCloseClicked}"
308
308
  icon="close"
309
309
  icon-size="20">
@@ -67,8 +67,8 @@
67
67
  }
68
68
  }
69
69
 
70
- zn-button.expanding-action__button::part(base) {
71
- padding: 7px 5px;
70
+ zn-button.expanding-action__button {
71
+ aspect-ratio: 1/1;
72
72
  }
73
73
 
74
74
  .expanding-action--drop .expanding-action__content {
@@ -0,0 +1,91 @@
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 type ZnDataSelect from "../data-select";
6
+ import type ZnDataTable from "../data-table";
7
+ import type ZnInput from "../input";
8
+ import type ZnQueryBuilder from "../query-builder";
9
+ import type ZnSelect from "../select";
10
+
11
+ import styles from './filter-wrapper.scss';
12
+
13
+ type AllowedInputElement =
14
+ HTMLInputElement
15
+ | HTMLSelectElement
16
+ | HTMLTextAreaElement
17
+ | ZnInput
18
+ | ZnSelect
19
+ | ZnDataSelect
20
+ | ZnQueryBuilder
21
+
22
+ /**
23
+ * @summary Short summary of the component's intended use.
24
+ * @documentation https://zinc.style/components/filter-wrapper
25
+ * @status experimental
26
+ * @since 1.0
27
+ *
28
+ * @dependency zn-example
29
+ *
30
+ * @event zn-event-name - Emitted as an example.
31
+ *
32
+ * @slot - The default slot.
33
+ * @slot example - An example slot.
34
+ *
35
+ * @csspart base - The component's base wrapper.
36
+ *
37
+ * @cssproperty --example - An example CSS custom property.
38
+ */
39
+ export default class ZnFilterWrapper extends ZincElement {
40
+ static styles: CSSResultGroup = unsafeCSS(styles);
41
+
42
+ @property() button: string = 'Filter';
43
+
44
+ private hasSubmitButton: boolean = false;
45
+
46
+ handleSubmit = (event: Event) => {
47
+ event.preventDefault();
48
+ const dataTable: ZnDataTable | null = this.closest('zn-data-table');
49
+ if (dataTable) {
50
+ const allowedInputs = ['zn-input', 'zn-select', 'zn-query-builder', 'zn-data-select', 'input', 'select', 'textarea'];
51
+ const inputs = Array.from(this.querySelectorAll(allowedInputs.join(','))) as AllowedInputElement[];
52
+ const params: Record<string, any> = {};
53
+ inputs.forEach(input => {
54
+ if (!input.value && input.hasAttribute('omit-empty')) {
55
+ return;
56
+ }
57
+ params[input.name] = input.value as string;
58
+ });
59
+
60
+ dataTable.requestParams = params;
61
+ dataTable.refresh();
62
+ }
63
+ }
64
+
65
+ connectedCallback() {
66
+ super.connectedCallback();
67
+ const button: HTMLElement | null = this.querySelector('zn-button[submit]');
68
+ if (button) {
69
+ this.hasSubmitButton = true;
70
+ button.addEventListener('click', this.handleSubmit);
71
+ }
72
+ }
73
+
74
+ private renderDefaultButton() {
75
+ return html`
76
+ <zn-button part="search-button"
77
+ class="filter-wrapper__submit"
78
+ type="submit"
79
+ @click="${this.handleSubmit}">
80
+ ${this.button}
81
+ </zn-button>
82
+ `;
83
+ }
84
+
85
+ render() {
86
+ return html`
87
+ <slot></slot>
88
+ ${this.hasSubmitButton ? '' : this.renderDefaultButton()}
89
+ `;
90
+ }
91
+ }
@@ -0,0 +1,11 @@
1
+ @use "../../wc";
2
+
3
+ :host {
4
+ display: block;
5
+ }
6
+
7
+ .filter-wrapper {
8
+ &__submit {
9
+ margin-top: var(--zn-spacing-medium);
10
+ }
11
+ }
@@ -0,0 +1,10 @@
1
+ import '../../../dist/zn.min.js';
2
+ import { expect, fixture, html } from '@open-wc/testing';
3
+
4
+ describe('<zn-filter-wrapper>', () => {
5
+ it('should render a component', async () => {
6
+ const el = await fixture(html` <zn-filter-wrapper></zn-filter-wrapper> `);
7
+
8
+ expect(el).to.exist;
9
+ });
10
+ });
@@ -0,0 +1,12 @@
1
+ import ZnFilterWrapper from './filter-wrapper.component';
2
+
3
+ export * from './filter-wrapper.component';
4
+ export default ZnFilterWrapper;
5
+
6
+ ZnFilterWrapper.define('zn-filter-wrapper');
7
+
8
+ declare global {
9
+ interface HTMLElementTagNameMap {
10
+ 'zn-filter-wrapper': ZnFilterWrapper;
11
+ }
12
+ }
@@ -141,7 +141,7 @@ export default class ZnHeader extends ZincElement {
141
141
  ${hasPreviousPath ? html`
142
142
  <a href="${this.previousPath}" class="caption__back"
143
143
  data-target="${this.previousTarget ? this.previousTarget : ''}">
144
- <zn-button size="content" icon="arrow_back" icon-size="24" color="transparent"></zn-buttonicon>
144
+ <zn-button size="content" icon="arrow_back" icon-size="24" color="transparent"></zn-button>
145
145
  </a>` : null}
146
146
 
147
147
  ${hasDefaultSlot ? html`
@@ -21,6 +21,9 @@
21
21
  font-size: var(--zn-font-size-large);
22
22
  color: rgba(var(--zn-text-panel-title), 100%);
23
23
  margin: 0;
24
+ overflow: hidden;
25
+ white-space: nowrap;
26
+ text-overflow: ellipsis;
24
27
  }
25
28
 
26
29
  &--has-breadcrumb {
@@ -110,6 +113,7 @@
110
113
  display: flex;
111
114
  flex-wrap: wrap;
112
115
  width: 100%;
116
+ max-width: 100%;
113
117
  height: fit-content;
114
118
  gap: 10px;
115
119
  margin: 0 auto;
@@ -123,13 +127,15 @@
123
127
  flex-direction: column;
124
128
  gap: 1px;
125
129
  min-height: 43px;
126
- flex-shrink: 0;
130
+ flex-shrink: 1;
131
+ max-width: 100%;
127
132
  }
128
133
 
129
134
  &__right {
130
135
  flex-grow: 1;
131
136
  flex-shrink: 1;
132
137
  overflow: hidden;
138
+ min-width: 20px;
133
139
  }
134
140
 
135
141
  &__description {
@@ -180,6 +186,7 @@
180
186
  display: flex;
181
187
  align-items: center;
182
188
  gap: 10px;
189
+ max-width: 100%;
183
190
 
184
191
  a {
185
192
  display: flex;