@kubex/zinc 1.1.29 → 1.1.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/custom-elements.json +161 -79
- package/dist/vscode.html-custom-data.json +15 -13
- package/dist/web-types.json +62 -30
- package/dist/zn.d.ts +14 -2
- package/dist/zn.min.js +1182 -1185
- package/docs/pages/components/settings-container.md +37 -2
- package/package.json +1 -1
- package/src/components/editor/editor.component.ts +1 -2
- package/src/components/header/header.scss +3 -1
- package/src/components/icon-picker/material-icons.ts +530 -10442
- package/src/components/panel/panel.scss +1 -0
- package/src/components/rating/rating.component.ts +1 -2
- package/src/components/settings-container/settings-container.component.ts +74 -9
- package/src/components/settings-container/settings-container.scss +75 -0
- package/src/components/settings-container/settings-container.test.ts +35 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {clamp} from "lodash";
|
|
2
1
|
import {classMap} from "lit/directives/class-map.js";
|
|
3
2
|
import {type CSSResultGroup, html, unsafeCSS} from 'lit';
|
|
4
3
|
import {FormControlController, validValidityState} from "../../internal/form";
|
|
@@ -98,7 +97,7 @@ export default class ZnRating extends ZincElement implements ZincFormControl {
|
|
|
98
97
|
const {left, width} = this.rating.getBoundingClientRect();
|
|
99
98
|
const value = this._roundToPrecision(((coordinate - left) / width) * this.max, this.precision);
|
|
100
99
|
|
|
101
|
-
return
|
|
100
|
+
return Math.min(Math.max(value, 0), this.max);
|
|
102
101
|
}
|
|
103
102
|
|
|
104
103
|
private _getValueFromMousePosition(event: MouseEvent): number {
|
|
@@ -25,10 +25,13 @@ interface SettingsContainerFilter {
|
|
|
25
25
|
*
|
|
26
26
|
* @dependency zn-example
|
|
27
27
|
*
|
|
28
|
-
* @event zn-
|
|
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
|
|
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
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
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
|
});
|