@kubex/zinc 1.1.29 → 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.
- 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 +125 -109
- package/docs/pages/components/settings-container.md +37 -2
- package/package.json +1 -1
- package/src/components/header/header.scss +3 -1
- package/src/components/panel/panel.scss +1 -0
- 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
|
@@ -132,6 +132,41 @@ for example by adding item-selector="zn-inline-edit" only the inline edit elemen
|
|
|
132
132
|
</div>
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
###
|
|
135
|
+
### Pull Tab
|
|
136
136
|
|
|
137
|
-
|
|
137
|
+
Add the `pull-tab` attribute to replace the settings dropdown with a pull tab anchored to the top right
|
|
138
|
+
of the container. Clicking the tab slides down a panel containing the settings options. Optional content
|
|
139
|
+
can be placed in the `tab` slot to render alongside the chevron.
|
|
140
|
+
|
|
141
|
+
```html:preview
|
|
142
|
+
|
|
143
|
+
<div style="width: 100%; height: 300px; border: 1px solid #ccc;">
|
|
144
|
+
<zn-settings-container pull-tab store-key="example-pull-tab-filters">
|
|
145
|
+
|
|
146
|
+
<zn-tile private caption="Leslie Alexander" description="Leslie.alexander@example.com" href="https://google.com">
|
|
147
|
+
<zn-icon slot="image" size="40" src="https://i.pravatar.cc/60?img=70" round></zn-icon>
|
|
148
|
+
<div slot="actions">
|
|
149
|
+
<zn-button href="#">Action</zn-button>
|
|
150
|
+
</div>
|
|
151
|
+
</zn-tile>
|
|
152
|
+
|
|
153
|
+
<zn-tile private caption="Leslie Alexander" description="Leslie.alexander@example.com" href="https://google.com">
|
|
154
|
+
<zn-icon slot="image" size="40" src="https://i.pravatar.cc/60?img=70" round></zn-icon>
|
|
155
|
+
<div slot="actions">
|
|
156
|
+
<zn-button href="#">Action</zn-button>
|
|
157
|
+
</div>
|
|
158
|
+
</zn-tile>
|
|
159
|
+
|
|
160
|
+
<zn-tile original caption="Leslie Alexander" description="Leslie.alexander@example.com" href="https://google.com">
|
|
161
|
+
<zn-icon slot="image" size="40" src="https://i.pravatar.cc/60?img=70" round></zn-icon>
|
|
162
|
+
<div slot="actions">
|
|
163
|
+
<zn-button href="#">Action</zn-button>
|
|
164
|
+
</div>
|
|
165
|
+
</zn-tile>
|
|
166
|
+
|
|
167
|
+
<div slot="filter" attribute="private" default="true">Toggle Private Messages</div>
|
|
168
|
+
<div slot="filter" attribute="original" default="true">Toggle Original Messages</div>
|
|
169
|
+
|
|
170
|
+
</zn-settings-container>
|
|
171
|
+
</div>
|
|
172
|
+
```
|
package/package.json
CHANGED
|
@@ -127,7 +127,8 @@
|
|
|
127
127
|
&__right {
|
|
128
128
|
flex-grow: 1;
|
|
129
129
|
flex-shrink: 1;
|
|
130
|
-
overflow:
|
|
130
|
+
overflow-x: clip;
|
|
131
|
+
overflow-y: visible;
|
|
131
132
|
min-width: 20px;
|
|
132
133
|
}
|
|
133
134
|
|
|
@@ -225,6 +226,7 @@
|
|
|
225
226
|
slot[name="actions"] {
|
|
226
227
|
justify-content: end;
|
|
227
228
|
flex-wrap: nowrap;
|
|
229
|
+
height: var(--zn-icon-size, 20px);
|
|
228
230
|
}
|
|
229
231
|
|
|
230
232
|
slot[name="actions"]::slotted(zn-button-menu) {
|
|
@@ -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
|
});
|