@kubex/zinc 1.0.111 → 1.0.113
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 +119 -74
- package/dist/vscode.html-custom-data.json +12 -11
- package/dist/web-types.json +28 -23
- package/dist/zn.d.ts +29 -0
- package/dist/zn.min.js +291 -289
- package/package.json +1 -1
- package/src/components/chart/builders.ts +2 -1
- package/src/components/inline-edit/inline-edit.component.ts +14 -6
- package/src/components/navbar/navbar.component.ts +36 -8
- package/src/components/navbar/navbar.test.ts +52 -1
- package/src/components/select/select.component.ts +3 -28
- package/src/components/simple-chart/simple-chart.component.ts +1 -0
- package/src/internal/conditional.ts +88 -0
package/package.json
CHANGED
|
@@ -45,6 +45,7 @@ function commonOption(props: BuilderProps): EChartsOption {
|
|
|
45
45
|
textStyle: { color: textColor },
|
|
46
46
|
tooltip: {
|
|
47
47
|
trigger: 'axis',
|
|
48
|
+
appendTo: 'body',
|
|
48
49
|
valueFormatter: props.yAxisAppend
|
|
49
50
|
? (v: number | string) => `${v}${props.yAxisAppend}`
|
|
50
51
|
: undefined,
|
|
@@ -201,7 +202,7 @@ export function buildSankeyOption(props: BuilderProps): EChartsOption {
|
|
|
201
202
|
animationEasing: 'cubicOut',
|
|
202
203
|
...(props.colors ? { color: props.colors } : {}),
|
|
203
204
|
textStyle: { color: textColor },
|
|
204
|
-
tooltip: { trigger: 'item' },
|
|
205
|
+
tooltip: { trigger: 'item', appendTo: 'body' },
|
|
205
206
|
series: [{
|
|
206
207
|
type: 'sankey',
|
|
207
208
|
name: first.name,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { classMap } from "lit/directives/class-map.js";
|
|
2
|
+
import { ConditionalController } from "../../internal/conditional";
|
|
2
3
|
import { type CSSResultGroup, html, type HTMLTemplateResult, type PropertyValues, unsafeCSS } from 'lit';
|
|
3
4
|
import { defaultValue } from "../../internal/default-value";
|
|
4
5
|
import { FormControlController } from "../../internal/form";
|
|
@@ -47,6 +48,7 @@ export default class ZnInlineEdit extends ZincElement implements ZincFormControl
|
|
|
47
48
|
},
|
|
48
49
|
});
|
|
49
50
|
private readonly hasSlotController = new HasSlotController(this, 'help-text', '[default]');
|
|
51
|
+
private readonly conditionalController = new ConditionalController(this);
|
|
50
52
|
|
|
51
53
|
@property() value: string | string[] = '';
|
|
52
54
|
|
|
@@ -56,6 +58,8 @@ export default class ZnInlineEdit extends ZincElement implements ZincFormControl
|
|
|
56
58
|
|
|
57
59
|
@property({ attribute: 'edit-text' }) editText: string;
|
|
58
60
|
|
|
61
|
+
@property() conditional = '';
|
|
62
|
+
|
|
59
63
|
@property({ type: Boolean }) disabled: boolean
|
|
60
64
|
|
|
61
65
|
@property({ type: Boolean }) inline: boolean
|
|
@@ -171,6 +175,7 @@ export default class ZnInlineEdit extends ZincElement implements ZincFormControl
|
|
|
171
175
|
async firstUpdated() {
|
|
172
176
|
await this.updateComplete;
|
|
173
177
|
this.input.addEventListener('onclick', this.handleEditClick);
|
|
178
|
+
this.conditionalController.setup();
|
|
174
179
|
}
|
|
175
180
|
|
|
176
181
|
protected willUpdate(changedProperties: PropertyValues) {
|
|
@@ -195,6 +200,7 @@ export default class ZnInlineEdit extends ZincElement implements ZincFormControl
|
|
|
195
200
|
if (this.input instanceof ZnSelect && !this.isEditing) {
|
|
196
201
|
await this.input.hide();
|
|
197
202
|
}
|
|
203
|
+
this.conditionalController.check();
|
|
198
204
|
}
|
|
199
205
|
|
|
200
206
|
mouseEventHandler = (e: MouseEvent) => {
|
|
@@ -468,16 +474,18 @@ export default class ZnInlineEdit extends ZincElement implements ZincFormControl
|
|
|
468
474
|
protected _getDataSelectInput(): HTMLTemplateResult {
|
|
469
475
|
return html`
|
|
470
476
|
<zn-data-select class="ai__input"
|
|
471
|
-
|
|
472
|
-
|
|
477
|
+
clearable=${ifDefined(this.isEditing ? this.clearable : undefined)}
|
|
478
|
+
dir="${this.dir}"
|
|
473
479
|
icon-position="${ifDefined(this.iconPosition)}"
|
|
474
|
-
|
|
480
|
+
multiple=${ifDefined(this.multiple)}
|
|
481
|
+
name="${this.name}"
|
|
475
482
|
provider="${this.selectProvider}"
|
|
476
|
-
clearable=${ifDefined(this.isEditing ? this.clearable : undefined)}
|
|
477
483
|
required=${ifDefined(this.required)}
|
|
478
|
-
|
|
484
|
+
size="${this.size}"
|
|
485
|
+
value="${this.value}"
|
|
486
|
+
@zn-blur="${this.handleBlur}"
|
|
479
487
|
@zn-input="${this.handleInput}"
|
|
480
|
-
|
|
488
|
+
>
|
|
481
489
|
</zn-data-select>`;
|
|
482
490
|
}
|
|
483
491
|
}
|
|
@@ -69,12 +69,12 @@ export default class ZnNavbar extends ZincElement {
|
|
|
69
69
|
private _navItemsGap: number = 0;
|
|
70
70
|
private _expandableMargin: number = 0;
|
|
71
71
|
private _totalItemWidth: number = 0;
|
|
72
|
+
private _itemsObserver: MutationObserver | null = null;
|
|
72
73
|
|
|
73
74
|
protected _store: Store;
|
|
74
75
|
|
|
75
76
|
appendItem(item: Element) {
|
|
76
|
-
this._appended = this._appended || [];
|
|
77
|
-
this._appended.push(item);
|
|
77
|
+
this._appended = [...(this._appended || []), item];
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
connectedCallback() {
|
|
@@ -97,6 +97,27 @@ export default class ZnNavbar extends ZincElement {
|
|
|
97
97
|
this._store = new Store(this.localStorage ? window.localStorage : window.sessionStorage, "znnav:", this.storeTtl);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
disconnectedCallback() {
|
|
101
|
+
super.disconnectedCallback();
|
|
102
|
+
this._itemsObserver?.disconnect();
|
|
103
|
+
this._itemsObserver = null;
|
|
104
|
+
this.resizeObserver?.disconnect();
|
|
105
|
+
this.resizeObserver = null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private _updateVisibility = () => {
|
|
109
|
+
if (this._expanding.length > 0) {
|
|
110
|
+
this.style.display = '';
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const items = this._navItems?.querySelectorAll(':scope > li:not(.more):not(#dropdown-item)') || [];
|
|
114
|
+
const itemCount = items.length;
|
|
115
|
+
if (itemCount === 0 || (itemCount < 2 && this.hideOne)) {
|
|
116
|
+
this.style.display = 'none';
|
|
117
|
+
} else {
|
|
118
|
+
this.style.display = '';
|
|
119
|
+
}
|
|
120
|
+
};
|
|
100
121
|
|
|
101
122
|
handleResize = () => {
|
|
102
123
|
if (this._totalItemWidth === 0 || this._extendedMenu === null || this.iconBar || this.stacked) {
|
|
@@ -204,6 +225,12 @@ export default class ZnNavbar extends ZincElement {
|
|
|
204
225
|
// Load persisted tabs before calculating widths
|
|
205
226
|
this._loadStoredTabs();
|
|
206
227
|
|
|
228
|
+
if (this._navItems) {
|
|
229
|
+
this._itemsObserver = new MutationObserver(this._updateVisibility);
|
|
230
|
+
this._itemsObserver.observe(this._navItems, {childList: true});
|
|
231
|
+
}
|
|
232
|
+
this._updateVisibility();
|
|
233
|
+
|
|
207
234
|
setTimeout(() => {
|
|
208
235
|
const items = this._navItems?.querySelectorAll('li') || [];
|
|
209
236
|
for (const item of items) {
|
|
@@ -297,16 +324,17 @@ export default class ZnNavbar extends ZincElement {
|
|
|
297
324
|
}
|
|
298
325
|
};
|
|
299
326
|
|
|
327
|
+
protected updated(_changedProperties: PropertyValues) {
|
|
328
|
+
super.updated(_changedProperties);
|
|
329
|
+
if (_changedProperties.has('hideOne') || _changedProperties.has('navigation') || _changedProperties.has('_appended')) {
|
|
330
|
+
this._updateVisibility();
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
300
334
|
render() {
|
|
301
335
|
if (!this.navigation) {
|
|
302
336
|
this.navigation = [];
|
|
303
337
|
}
|
|
304
|
-
const itemCount = this.navigation?.length + this._preItems?.length + this._postItems?.length;
|
|
305
|
-
if (this._expanding.length === 0) {
|
|
306
|
-
if (itemCount === 0 || (itemCount < 2 && this.hideOne)) {
|
|
307
|
-
this.style.display = 'none';
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
338
|
|
|
311
339
|
return html`
|
|
312
340
|
<div class="${classMap({
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import '../../../dist/zn.min.js';
|
|
2
|
-
import { expect, fixture, html
|
|
2
|
+
import {aTimeout, expect, fixture, html} from '@open-wc/testing';
|
|
3
|
+
import type ZnNavbar from './navbar.component';
|
|
3
4
|
|
|
4
5
|
describe('<zn-navbar>', () => {
|
|
5
6
|
it('should render a component', async () => {
|
|
@@ -7,4 +8,54 @@ describe('<zn-navbar>', () => {
|
|
|
7
8
|
|
|
8
9
|
expect(el).to.exist;
|
|
9
10
|
});
|
|
11
|
+
|
|
12
|
+
describe('hide-one', () => {
|
|
13
|
+
it('hides when only one item is present', async () => {
|
|
14
|
+
const el = await fixture<ZnNavbar>(html`
|
|
15
|
+
<zn-navbar hide-one>
|
|
16
|
+
<li>Only</li>
|
|
17
|
+
</zn-navbar>
|
|
18
|
+
`);
|
|
19
|
+
await aTimeout(0);
|
|
20
|
+
|
|
21
|
+
expect(getComputedStyle(el).display).to.equal('none');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('reveals when a second item is added dynamically', async () => {
|
|
25
|
+
const el = await fixture<ZnNavbar>(html`
|
|
26
|
+
<zn-navbar hide-one>
|
|
27
|
+
<li>First</li>
|
|
28
|
+
</zn-navbar>
|
|
29
|
+
`);
|
|
30
|
+
await aTimeout(0);
|
|
31
|
+
expect(getComputedStyle(el).display).to.equal('none');
|
|
32
|
+
|
|
33
|
+
const li = document.createElement('li');
|
|
34
|
+
li.setAttribute('tab-uri', '/two');
|
|
35
|
+
li.textContent = 'Second';
|
|
36
|
+
el.addItem(li, false);
|
|
37
|
+
await aTimeout(0);
|
|
38
|
+
|
|
39
|
+
expect(getComputedStyle(el).display).to.not.equal('none');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('hides again when items drop back to one', async () => {
|
|
43
|
+
const el = await fixture<ZnNavbar>(html`
|
|
44
|
+
<zn-navbar hide-one>
|
|
45
|
+
<li>First</li>
|
|
46
|
+
</zn-navbar>
|
|
47
|
+
`);
|
|
48
|
+
const second = document.createElement('li');
|
|
49
|
+
second.setAttribute('tab-uri', '/two');
|
|
50
|
+
second.textContent = 'Second';
|
|
51
|
+
el.addItem(second, false);
|
|
52
|
+
await aTimeout(0);
|
|
53
|
+
expect(getComputedStyle(el).display).to.not.equal('none');
|
|
54
|
+
|
|
55
|
+
second.remove();
|
|
56
|
+
await aTimeout(0);
|
|
57
|
+
|
|
58
|
+
expect(getComputedStyle(el).display).to.equal('none');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
10
61
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {animateTo, stopAnimations} from '../../internal/animate.js';
|
|
2
2
|
import {classMap} from "lit/directives/class-map.js";
|
|
3
|
-
import {
|
|
3
|
+
import {ConditionalController} from "../../internal/conditional";
|
|
4
4
|
import {FormControlController} from "../../internal/form";
|
|
5
5
|
import {getAnimation, setDefaultAnimation} from "../../utilities/animation-registry";
|
|
6
6
|
import {HasSlotController} from "../../internal/slot";
|
|
@@ -89,6 +89,7 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
|
|
|
89
89
|
protected readonly formControlController = new FormControlController(this, {
|
|
90
90
|
assumeInteractionOn: ['zn-blur', 'zn-input']
|
|
91
91
|
});
|
|
92
|
+
private readonly conditionalController = new ConditionalController(this);
|
|
92
93
|
private readonly hasSlotController = new HasSlotController(this, 'help-text', 'label');
|
|
93
94
|
private readonly localize = new LocalizeController(this);
|
|
94
95
|
private typeToSelectString = '';
|
|
@@ -1131,33 +1132,7 @@ export default class ZnSelect extends ZincElement implements ZincFormControl {
|
|
|
1131
1132
|
|
|
1132
1133
|
}
|
|
1133
1134
|
|
|
1134
|
-
|
|
1135
|
-
const ids = this.conditional.split(',').map(id => id.trim());
|
|
1136
|
-
const conditionals: ZnSelect[] = [];
|
|
1137
|
-
|
|
1138
|
-
ids.forEach(id => {
|
|
1139
|
-
const elements = deepQuerySelectorAll(`#${id}`, document.documentElement, '') as ZnSelect[];
|
|
1140
|
-
conditionals.push(...elements);
|
|
1141
|
-
});
|
|
1142
|
-
|
|
1143
|
-
const initiallyDisabled = this.disabled;
|
|
1144
|
-
const checkConditionals = () => {
|
|
1145
|
-
const shouldDisable = conditionals.some(select => {
|
|
1146
|
-
let linkedValues = Array.isArray(select.value) ? select.value : [select.value];
|
|
1147
|
-
linkedValues = linkedValues.filter(v => v !== '');
|
|
1148
|
-
return linkedValues.length > 0;
|
|
1149
|
-
});
|
|
1150
|
-
this.disabled = initiallyDisabled || shouldDisable;
|
|
1151
|
-
};
|
|
1152
|
-
|
|
1153
|
-
conditionals.forEach(select => {
|
|
1154
|
-
select.addEventListener('zn-change', checkConditionals);
|
|
1155
|
-
select.addEventListener('zn-input', checkConditionals);
|
|
1156
|
-
});
|
|
1157
|
-
|
|
1158
|
-
// trigger the check once to initialize
|
|
1159
|
-
checkConditionals();
|
|
1160
|
-
}
|
|
1135
|
+
this.conditionalController.setup();
|
|
1161
1136
|
|
|
1162
1137
|
if (this.dataUri && !this.searchOnly) {
|
|
1163
1138
|
this.fetchOptions().then();
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import {deepQuerySelectorAll} from '../utilities/query';
|
|
2
|
+
import type {ReactiveController, ReactiveControllerHost} from 'lit';
|
|
3
|
+
|
|
4
|
+
export interface ConditionalHost {
|
|
5
|
+
conditional: string;
|
|
6
|
+
disabled: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** A reactive controller that disables the host when linked selects have a value. */
|
|
10
|
+
export class ConditionalController implements ReactiveController {
|
|
11
|
+
host: ReactiveControllerHost & Element & ConditionalHost;
|
|
12
|
+
private conditionals: (Element & { value: string | string[] })[] = [];
|
|
13
|
+
private initiallyDisabled = false;
|
|
14
|
+
private readonly handleChange = () => this.checkConditionals();
|
|
15
|
+
|
|
16
|
+
constructor(host: ReactiveControllerHost & Element & ConditionalHost) {
|
|
17
|
+
(this.host = host).addController(this);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Call from the host's `firstUpdated()` to parse IDs, find elements, attach listeners, and run the initial check. */
|
|
21
|
+
setup() {
|
|
22
|
+
if (this.host.conditional === '') {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const ids = this.host.conditional.split(',').map(id => id.trim());
|
|
27
|
+
|
|
28
|
+
ids.forEach(id => {
|
|
29
|
+
const byId = deepQuerySelectorAll(`#${id}`, document.documentElement, '') as (Element & {
|
|
30
|
+
value: string | string[];
|
|
31
|
+
})[];
|
|
32
|
+
const byName = deepQuerySelectorAll(`[name="${id}"]`, document.documentElement, '') as (Element & {
|
|
33
|
+
value: string | string[];
|
|
34
|
+
})[];
|
|
35
|
+
|
|
36
|
+
// de-duplicate in case the same element matches both id and name
|
|
37
|
+
const seen = new Set<Element>();
|
|
38
|
+
[...byId, ...byName].forEach(el => {
|
|
39
|
+
if (!seen.has(el)) {
|
|
40
|
+
seen.add(el);
|
|
41
|
+
this.conditionals.push(el);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
this.initiallyDisabled = this.host.disabled;
|
|
47
|
+
|
|
48
|
+
if (ids.length === 0) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this.conditionals.forEach(select => {
|
|
53
|
+
select.addEventListener('zn-change', this.handleChange);
|
|
54
|
+
select.addEventListener('zn-input', this.handleChange);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// trigger the check once to initialize
|
|
58
|
+
this.checkConditionals();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
hostConnected() {
|
|
62
|
+
// No-op; setup is deferred to setup() which the host calls from firstUpdated()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
hostDisconnected() {
|
|
66
|
+
this.conditionals.forEach(select => {
|
|
67
|
+
select.removeEventListener('zn-change', this.handleChange);
|
|
68
|
+
// select.removeEventListener('zn-input', this.handleChange);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
this.conditionals = [];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Re-evaluate the conditional state. Call from the host when needed. */
|
|
75
|
+
check() {
|
|
76
|
+
this.checkConditionals();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private checkConditionals() {
|
|
80
|
+
const shouldDisable = this.conditionals.some(select => {
|
|
81
|
+
let linkedValues = Array.isArray(select.value) ? select.value : [select.value];
|
|
82
|
+
linkedValues = linkedValues.filter(v => (v !== '' && v !== "0"));
|
|
83
|
+
return linkedValues.length > 0;
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
this.host.disabled = this.initiallyDisabled || shouldDisable;
|
|
87
|
+
}
|
|
88
|
+
}
|