@kubex/zinc 1.1.28 → 1.1.31

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 (52) hide show
  1. package/custom-elements-manifest.config.js +2 -2
  2. package/dist/custom-elements.json +1910 -362
  3. package/dist/vscode.html-custom-data.json +55 -14
  4. package/dist/web-types.json +185 -32
  5. package/dist/zn.d.ts +684 -16
  6. package/dist/zn.min.js +1325 -929
  7. package/docs/pages/components/flow-builder-troubleshooter-demo.njk +106 -78
  8. package/docs/pages/components/flow-builder.md +422 -66
  9. package/docs/pages/components/page-builder.md +167 -0
  10. package/docs/pages/components/settings-container.md +37 -2
  11. package/package.json +1 -1
  12. package/src/components/datepicker/datepicker.scss +0 -10
  13. package/src/components/flow-builder/flow-builder.component.ts +377 -16
  14. package/src/components/flow-builder/flow-builder.scss +398 -250
  15. package/src/components/flow-builder/flow-builder.test.ts +241 -4
  16. package/src/components/flow-builder/flow-layout.ts +42 -17
  17. package/src/components/flow-builder/flow.types.ts +168 -43
  18. package/src/components/flow-builder/modules/flow-branch-conditions/flow-branch-conditions.component.ts +300 -0
  19. package/src/components/flow-builder/modules/flow-branch-conditions/flow-branch-conditions.scss +222 -0
  20. package/src/components/flow-builder/modules/flow-branch-conditions/flow-branch-conditions.test.ts +125 -0
  21. package/src/components/flow-builder/modules/flow-branch-conditions/index.ts +12 -0
  22. package/src/components/flow-builder/modules/flow-canvas/flow-canvas.component.ts +184 -26
  23. package/src/components/flow-builder/modules/flow-canvas/flow-canvas.scss +170 -120
  24. package/src/components/flow-builder/modules/flow-node/flow-node.scss +42 -42
  25. package/src/components/flow-builder/modules/flow-step/flow-step.component.ts +2 -1
  26. package/src/components/flow-builder/modules/flow-step/flow-step.scss +25 -17
  27. package/src/components/header/header.scss +3 -1
  28. package/src/components/icon-picker/icon-picker.component.ts +20 -37
  29. package/src/components/icon-picker/icon-picker.scss +5 -45
  30. package/src/components/page-builder/index.ts +14 -0
  31. package/src/components/page-builder/modules/page-palette-item/index.ts +12 -0
  32. package/src/components/page-builder/modules/page-palette-item/page-palette-item.component.ts +71 -0
  33. package/src/components/page-builder/modules/page-palette-item/page-palette-item.scss +70 -0
  34. package/src/components/page-builder/modules/page-palette-item/page-palette-item.test.ts +20 -0
  35. package/src/components/page-builder/modules/page-section-card/index.ts +12 -0
  36. package/src/components/page-builder/modules/page-section-card/page-section-card.component.ts +93 -0
  37. package/src/components/page-builder/modules/page-section-card/page-section-card.scss +92 -0
  38. package/src/components/page-builder/modules/page-section-card/page-section-card.test.ts +50 -0
  39. package/src/components/page-builder/page-builder.component.ts +1053 -0
  40. package/src/components/page-builder/page-builder.scss +494 -0
  41. package/src/components/page-builder/page-builder.test.ts +464 -0
  42. package/src/components/page-builder/page-registry.ts +48 -0
  43. package/src/components/page-builder/page.types.ts +75 -0
  44. package/src/components/panel/panel.scss +1 -0
  45. package/src/components/settings-container/settings-container.component.ts +74 -9
  46. package/src/components/settings-container/settings-container.scss +75 -0
  47. package/src/components/settings-container/settings-container.test.ts +35 -0
  48. package/src/events/events.ts +2 -0
  49. package/src/events/zn-page-change.ts +9 -0
  50. package/src/events/zn-page-selection-change.ts +7 -0
  51. package/src/zinc.ts +4 -0
  52. package/web-test-runner.config.js +6 -1
@@ -25,10 +25,13 @@ interface SettingsContainerFilter {
25
25
  *
26
26
  * @dependency zn-example
27
27
  *
28
- * @event zn-event-name - Emitted as an example.
28
+ * @event zn-show - Emitted when the pull tab panel opens.
29
+ * @event zn-hide - Emitted when the pull tab panel closes.
29
30
  *
30
31
  * @slot - The default slot.
31
- * @slot example - An example slot.
32
+ * @slot filter - Filter definitions used to toggle visibility of content.
33
+ * @slot dropdown-content - Custom content for the settings panel.
34
+ * @slot tab - Extra content rendered inside the pull tab next to the chevron.
32
35
  *
33
36
  * @csspart base - The component's base wrapper.
34
37
  *
@@ -43,6 +46,10 @@ export default class ZnSettingsContainer extends ZincElement {
43
46
 
44
47
  @property({attribute: 'store-key'}) storeKey: string;
45
48
  @property({attribute: 'no-scroll'}) noScroll: boolean;
49
+ @property({attribute: 'pull-tab', type: Boolean, reflect: true}) pullTab = false;
50
+ @property({type: Boolean, reflect: true}) open = false;
51
+
52
+ @state() private panelExpanded = false;
46
53
 
47
54
  private readonly _mutationObserver = new MutationController(this, {
48
55
  target: null,
@@ -88,6 +95,40 @@ export default class ZnSettingsContainer extends ZincElement {
88
95
  this._mutationObserver.observe(this);
89
96
  }
90
97
 
98
+ disconnectedCallback() {
99
+ document.removeEventListener('mousedown', this.handleDocumentMouseDown, true);
100
+ super.disconnectedCallback();
101
+ }
102
+
103
+ private handleDocumentMouseDown = (e: MouseEvent) => {
104
+ if (!this.open) return;
105
+ const pullTab = this.shadowRoot?.querySelector('.pull-tab');
106
+ if (pullTab && e.composedPath().includes(pullTab)) return;
107
+ this.hidePullTab();
108
+ };
109
+
110
+ private togglePullTab = () => {
111
+ if (this.open) {
112
+ this.hidePullTab();
113
+ } else {
114
+ this.open = true;
115
+ document.addEventListener('mousedown', this.handleDocumentMouseDown, true);
116
+ this.emit('zn-show');
117
+ }
118
+ };
119
+
120
+ private hidePullTab() {
121
+ this.open = false;
122
+ this.panelExpanded = false;
123
+ document.removeEventListener('mousedown', this.handleDocumentMouseDown, true);
124
+ this.emit('zn-hide');
125
+ }
126
+
127
+ private handlePanelTransitionEnd = (e: TransitionEvent) => {
128
+ if (e.propertyName !== 'grid-template-rows') return;
129
+ this.panelExpanded = this.open;
130
+ };
131
+
91
132
  // Debounced scheduling to avoid excessive updates on rapid DOM mutations
92
133
  private scheduleUpdateFilters() {
93
134
  if (this._updateFiltersScheduled) return;
@@ -221,17 +262,41 @@ export default class ZnSettingsContainer extends ZincElement {
221
262
  <div class="scroll-content">
222
263
  <slot @slotchange="${this.handleContentSlotChange}"></slot>
223
264
  </div>
224
- <zn-dropdown placement="${placement}" class="${classMap({
225
- 'setting-container__dropdown': true,
226
- [`setting-container__dropdown--${this.position}`]: true,
227
- })}">
228
- <zn-icon class="setting-container__toggle-button" slot="trigger" size="24" src="settings" round></zn-icon>
229
- ${this.getDropdownContent()}
230
- </zn-dropdown>
265
+ ${this.pullTab ? this.renderPullTab() : html`
266
+ <zn-dropdown placement="${placement}" class="${classMap({
267
+ 'setting-container__dropdown': true,
268
+ [`setting-container__dropdown--${this.position}`]: true,
269
+ })}">
270
+ <zn-icon class="setting-container__toggle-button" slot="trigger" size="24" src="settings" round></zn-icon>
271
+ ${this.getDropdownContent()}
272
+ </zn-dropdown>`}
231
273
  </div>
232
274
  `;
233
275
  }
234
276
 
277
+ private renderPullTab() {
278
+ return html`
279
+ <div class="${classMap({
280
+ 'pull-tab': true,
281
+ 'pull-tab--open': this.open,
282
+ 'pull-tab--expanded': this.panelExpanded,
283
+ })}">
284
+ <div class="pull-tab__panel" @transitionend="${this.handlePanelTransitionEnd}">
285
+ <div class="pull-tab__panel-content">
286
+ ${this.getDropdownContent()}
287
+ </div>
288
+ </div>
289
+ <button class="pull-tab__tab"
290
+ type="button"
291
+ aria-expanded="${this.open ? 'true' : 'false'}"
292
+ aria-label="Settings"
293
+ @click="${this.togglePullTab}">
294
+ <slot name="tab"></slot>
295
+ <zn-icon src="${this.open ? 'chevron-up@lu' : 'chevron-down@lu'}" size="20"></zn-icon>
296
+ </button>
297
+ </div>`;
298
+ }
299
+
235
300
  private getDropdownContent() {
236
301
  const hasDropdownContent = this.querySelector('[slot="dropdown-content"]');
237
302
  if (hasDropdownContent) {
@@ -84,6 +84,81 @@ zn-button {
84
84
  border-radius: var(--zn-border-radius);
85
85
  }
86
86
 
87
+ .pull-tab {
88
+ position: absolute;
89
+ top: 0;
90
+ right: calc(var(--zn-base-gap) + var(--zn-gutter));
91
+ z-index: 20;
92
+ display: flex;
93
+ flex-direction: column;
94
+ align-items: flex-end;
95
+ max-height: 100%;
96
+
97
+ &__panel {
98
+ display: grid;
99
+ grid-template-rows: 0fr;
100
+ min-height: 0;
101
+ overflow: hidden;
102
+ background-color: rgb(var(--zn-panel));
103
+ border: 1px solid rgb(var(--zn-border-color));
104
+ border-top: none;
105
+ border-bottom-width: 0;
106
+ border-radius: 0 0 0 var(--zn-border-radius);
107
+ transition: grid-template-rows 0.22s ease, border-bottom-width 0s linear 0.22s;
108
+ will-change: grid-template-rows;
109
+ }
110
+
111
+ &--open &__panel {
112
+ grid-template-rows: 1fr;
113
+ border-bottom-width: 1px;
114
+ transition: grid-template-rows 0.22s ease, border-bottom-width 0s linear 0s;
115
+ }
116
+
117
+ &__panel-content {
118
+ min-height: 0;
119
+ overflow: hidden;
120
+
121
+ .settings-container__dropdown-content {
122
+ border: none;
123
+ box-shadow: none;
124
+ border-radius: 0;
125
+ margin-bottom: 0;
126
+ max-width: none;
127
+ width: auto;
128
+ }
129
+ }
130
+
131
+ &--expanded &__panel-content {
132
+ overflow-y: auto;
133
+ }
134
+
135
+ &__tab {
136
+ flex-shrink: 0;
137
+ background-color: rgb(var(--zn-panel));
138
+ color: rgb(var(--zn-text-heading));
139
+ border: 1px solid rgb(var(--zn-border-color));
140
+ border-top: none;
141
+ border-radius: 0 0 10px 10px;
142
+ padding: var(--zn-spacing-x-small);
143
+ cursor: pointer;
144
+ display: inline-flex;
145
+ align-items: center;
146
+ gap: var(--zn-spacing-x-small);
147
+ max-height: 36px;
148
+ overflow: hidden;
149
+ margin-top: -1px;
150
+
151
+ &:hover {
152
+ background-color: rgb(var(--zn-shadow));
153
+ }
154
+
155
+ &:focus-visible {
156
+ outline: 2px solid rgb(var(--zn-primary));
157
+ outline-offset: -2px;
158
+ }
159
+ }
160
+ }
161
+
87
162
  .settings-container__dropdown-content {
88
163
  display: flex;
89
164
  flex-direction: column;
@@ -7,4 +7,39 @@ describe('<zn-settings-container>', () => {
7
7
 
8
8
  expect(el).to.exist;
9
9
  });
10
+
11
+ describe('pull tab', () => {
12
+ it('should render a pull tab instead of the dropdown', async () => {
13
+ const el = await fixture<HTMLElement>(html` <zn-settings-container pull-tab></zn-settings-container> `);
14
+
15
+ expect(el.shadowRoot!.querySelector('.pull-tab')).to.exist;
16
+ expect(el.shadowRoot!.querySelector('zn-dropdown')).to.not.exist;
17
+ });
18
+
19
+ it('should open and close when the tab is clicked', async () => {
20
+ const el = await fixture<HTMLElement>(html` <zn-settings-container pull-tab></zn-settings-container> `);
21
+ const tab = el.shadowRoot!.querySelector<HTMLButtonElement>('.pull-tab__tab')!;
22
+
23
+ tab.click();
24
+ await (el as any).updateComplete;
25
+ expect(el.hasAttribute('open')).to.be.true;
26
+
27
+ tab.click();
28
+ await (el as any).updateComplete;
29
+ expect(el.hasAttribute('open')).to.be.false;
30
+ });
31
+
32
+ it('should close when clicking outside', async () => {
33
+ const el = await fixture<HTMLElement>(html` <zn-settings-container pull-tab></zn-settings-container> `);
34
+ const tab = el.shadowRoot!.querySelector<HTMLButtonElement>('.pull-tab__tab')!;
35
+
36
+ tab.click();
37
+ await (el as any).updateComplete;
38
+ expect(el.hasAttribute('open')).to.be.true;
39
+
40
+ document.body.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, composed: true }));
41
+ await (el as any).updateComplete;
42
+ expect(el.hasAttribute('open')).to.be.false;
43
+ });
44
+ });
10
45
  });
@@ -15,3 +15,5 @@ export type {ZnRejectEvent} from './zn-reject';
15
15
  export type {ZnFlowChangeEvent} from './zn-flow-change';
16
16
  export type {ZnFlowSelectionChangeEvent} from './zn-flow-selection-change';
17
17
  export type {ZnFlowConnectEvent} from './zn-flow-connect';
18
+ export type {ZnPageChangeEvent} from './zn-page-change';
19
+ export type {ZnPageSelectionChangeEvent} from './zn-page-selection-change';
@@ -0,0 +1,9 @@
1
+ import type {PageState} from '../components/page-builder/page.types';
2
+
3
+ export type ZnPageChangeEvent = CustomEvent<{ state: PageState }>;
4
+
5
+ declare global {
6
+ interface GlobalEventHandlersEventMap {
7
+ 'zn-page-change': ZnPageChangeEvent;
8
+ }
9
+ }
@@ -0,0 +1,7 @@
1
+ export type ZnPageSelectionChangeEvent = CustomEvent<{ sectionId: string | null }>;
2
+
3
+ declare global {
4
+ interface GlobalEventHandlersEventMap {
5
+ 'zn-page-selection-change': ZnPageSelectionChangeEvent;
6
+ }
7
+ }
package/src/zinc.ts CHANGED
@@ -104,6 +104,10 @@ export { default as FlowBuilder } from './components/flow-builder';
104
104
  export { default as FlowSteps } from './components/flow-builder/modules/flow-steps';
105
105
  export { default as FlowStepGroup } from './components/flow-builder/modules/flow-step-group';
106
106
  export { default as FlowStep } from './components/flow-builder/modules/flow-step';
107
+ export { default as FlowBranchConditions } from './components/flow-builder/modules/flow-branch-conditions';
108
+ export { default as PageBuilder } from './components/page-builder';
109
+ export { default as PagePaletteItem } from './components/page-builder/modules/page-palette-item';
110
+ export { default as PageSectionCard } from './components/page-builder/modules/page-section-card';
107
111
  /* plop:component */
108
112
 
109
113
  // Base Component
@@ -7,7 +7,12 @@ export default {
7
7
  files: 'src/**/*.test.ts',
8
8
  concurrentBrowsers: 3,
9
9
  plugins: [
10
- vitePlugin()
10
+ vitePlugin({
11
+ // Vite's dep optimizer rewrites the /__web-dev-server__web-socket.js dynamic
12
+ // import to a relative path the plugin's externaliser can't match — keep the
13
+ // packages that import it out of pre-bundling.
14
+ optimizeDeps: {exclude: ['@open-wc/testing', '@web/test-runner-commands']}
15
+ })
11
16
  ],
12
17
  filterBrowserLogs: removeViteLogging,
13
18
  browsers: [