@kubex/zinc 1.0.113 → 1.0.115
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/.github/workflows/eleventy_build.yml +5 -5
- package/.github/workflows/js_build_and_deploy.yaml +1 -1
- package/dist/custom-elements.json +2422 -190
- package/dist/vscode.html-custom-data.json +86 -5
- package/dist/web-types.json +251 -9
- package/dist/zn.d.ts +518 -340
- package/dist/zn.min.css +1 -1
- package/dist/zn.min.js +960 -882
- package/docs/eleventy.config.cjs +4 -2
- package/docs/pages/components/header.md +13 -0
- package/docs/pages/components/inline-edit.md +20 -0
- package/docs/pages/components/item.md +12 -1
- package/docs/pages/components/page.md +149 -0
- package/docs/pages/components/progress-bar.md +16 -0
- package/docs/pages/components/select.md +25 -0
- package/docs/pages/components/split-pane.md +6 -7
- package/docs/pages/components/tabs.md +59 -9
- package/package.json +8 -5
- package/scripts/build.js +40 -19
- package/scss/_global-spacing.scss +12 -1
- package/scss/_root.scss +34 -2
- package/scss/mixins/_spacing-mixins.scss +1 -1
- package/scss/shared/layout.scss +15 -2
- package/scss/themes/_light.scss +1 -1
- package/src/components/absolute-container/absolute-container.component.ts +9 -25
- package/src/components/animated-button/animated-button.test.ts +8 -8
- package/src/components/button/button.component.ts +3 -1
- package/src/components/button/button.scss +5 -0
- package/src/components/button-menu/button-menu.component.ts +36 -21
- package/src/components/button-menu/button-menu.test.ts +55 -1
- package/src/components/chart/chart.component.ts +7 -7
- package/src/components/collapsible/collapsible.component.ts +7 -14
- package/src/components/cols/cols.scss +1 -1
- package/src/components/content-block/content-block.component.ts +11 -33
- package/src/components/data-select/data-select.component.ts +7 -11
- package/src/components/data-select/data-select.scss +1 -0
- package/src/components/data-table/data-table.component.ts +10 -14
- package/src/components/dialog/dialog.scss +4 -0
- package/src/components/editor/modules/toolbar/toolbar.component.ts +5 -9
- package/src/components/expanding-action/expanding-action.component.ts +37 -43
- package/src/components/form-group/form-group.component.ts +32 -27
- package/src/components/form-group/form-group.scss +1 -0
- package/src/components/header/header.component.ts +6 -5
- package/src/components/header/header.scss +28 -26
- package/src/components/inline-edit/inline-edit.component.ts +13 -1
- package/src/components/inline-edit/inline-edit.test.ts +50 -0
- package/src/components/input/input.test.ts +77 -0
- package/src/components/input-group/input-group.test.ts +2 -10
- package/src/components/item/item.component.ts +12 -6
- package/src/components/item/item.scss +1 -1
- package/src/components/item/item.test.ts +8 -0
- package/src/components/navbar/navbar.component.ts +222 -48
- package/src/components/navbar/navbar.scss +134 -21
- package/src/components/navbar/navbar.test.ts +114 -9
- package/src/components/option/option.scss +5 -7
- package/src/components/option/option.test.ts +30 -0
- package/src/components/page/index.ts +13 -0
- package/src/components/page/page.component.ts +406 -0
- package/src/components/page/page.scss +325 -0
- package/src/components/page/page.test.ts +397 -0
- package/src/components/page-nav/page-nav.scss +7 -5
- package/src/components/pane/pane.component.ts +2 -2
- package/src/components/pane/pane.scss +0 -1
- package/src/components/pane/pane.test.ts +31 -0
- package/src/components/panel/panel.scss +5 -16
- package/src/components/progress-bar/progress-bar.component.ts +5 -2
- package/src/components/progress-bar/progress-bar.scss +17 -1
- package/src/components/progress-bar/progress-bar.test.ts +12 -0
- package/src/components/scroll-container/scroll-container.component.ts +22 -21
- package/src/components/select/select.component.ts +243 -39
- package/src/components/select/select.scss +36 -5
- package/src/components/select/select.test.ts +533 -0
- package/src/components/settings-container/settings-container.component.ts +15 -19
- package/src/components/settings-container/settings-container.scss +8 -8
- package/src/components/sidebar/sidebar.component.ts +11 -11
- package/src/components/simple-chart/simple-chart.component.ts +6 -7
- package/src/components/sp/sp.scss +46 -15
- package/src/components/sp/sp.test.ts +15 -0
- package/src/components/split-pane/split-pane.component.ts +153 -26
- package/src/components/split-pane/split-pane.scss +89 -13
- package/src/components/split-pane/split-pane.test.ts +187 -0
- package/src/components/style/style.component.ts +8 -0
- package/src/components/tab/index.ts +13 -0
- package/src/components/tab/tab.component.ts +25 -0
- package/src/components/tab/tab.scss +7 -0
- package/src/components/table/table.component.ts +7 -2
- package/src/components/table/table.scss +1 -0
- package/src/components/tabs/tabs.component.ts +75 -70
- package/src/components/tabs/tabs.scss +1 -1
- package/src/components/textarea/textarea.component.ts +5 -8
- package/src/components/tile/tile.scss +2 -2
- package/src/components/translation-group/translation-group.component.ts +15 -14
- package/src/components/translations/translations.component.ts +18 -17
- package/src/components/translations/translations.scss +1 -0
- package/src/components/translations/translations.test.ts +3 -2
- package/src/internal/form.ts +234 -0
- package/src/internal/theme.ts +26 -46
- package/src/internal/zinc-element.ts +12 -7
- package/src/utilities/form.ts +1 -0
- package/src/wc.scss +1 -1
- package/src/zinc.ts +3 -0
|
@@ -3,6 +3,7 @@ import {type CSSResultGroup, html, nothing, type TemplateResult, unsafeCSS} from
|
|
|
3
3
|
import {HasSlotController} from "../../internal/slot";
|
|
4
4
|
import {ifDefined} from "lit/directives/if-defined.js";
|
|
5
5
|
import {property, query} from 'lit/decorators.js';
|
|
6
|
+
import {ResizeController} from '@lit-labs/observers/resize-controller.js';
|
|
6
7
|
import {ref} from "lit/directives/ref.js";
|
|
7
8
|
import {Task} from "@lit/task";
|
|
8
9
|
import {unsafeHTML} from "lit/directives/unsafe-html.js";
|
|
@@ -222,7 +223,14 @@ export default class ZnDataTable extends ZincElement {
|
|
|
222
223
|
private _initialLoad = true;
|
|
223
224
|
private _lastTableContent: TemplateResult = html``;
|
|
224
225
|
|
|
225
|
-
private resizeObserver
|
|
226
|
+
private readonly resizeObserver = new ResizeController(this, {
|
|
227
|
+
target: null,
|
|
228
|
+
callback: () => {
|
|
229
|
+
if (this.tableContainer) {
|
|
230
|
+
this.tableContainer.scrollIntoView({behavior: 'smooth', block: 'nearest'});
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
});
|
|
226
234
|
|
|
227
235
|
private itemsPerPage: number = DEFAULT_PER_PAGE;
|
|
228
236
|
private page: number = DEFAULT_PAGE;
|
|
@@ -384,22 +392,12 @@ export default class ZnDataTable extends ZincElement {
|
|
|
384
392
|
|
|
385
393
|
connectedCallback() {
|
|
386
394
|
super.connectedCallback();
|
|
387
|
-
|
|
388
|
-
this.resizeObserver = new ResizeObserver(() => {
|
|
389
|
-
if (this.tableContainer) {
|
|
390
|
-
this.tableContainer.scrollIntoView({behavior: 'smooth', block: 'nearest'});
|
|
391
|
-
}
|
|
392
|
-
});
|
|
393
|
-
|
|
394
395
|
this.addEventListener('zn-filter-change', this.filterChangeListener);
|
|
395
396
|
this.addEventListener('zn-search-change', this.searchChangeListener);
|
|
396
397
|
}
|
|
397
398
|
|
|
398
399
|
disconnectedCallback() {
|
|
399
400
|
super.disconnectedCallback();
|
|
400
|
-
if (this.resizeObserver) {
|
|
401
|
-
this.resizeObserver.disconnect();
|
|
402
|
-
}
|
|
403
401
|
this.removeEventListener('zn-filter-change', this.filterChangeListener);
|
|
404
402
|
this.removeEventListener('zn-search-change', this.searchChangeListener);
|
|
405
403
|
}
|
|
@@ -796,9 +794,7 @@ export default class ZnDataTable extends ZincElement {
|
|
|
796
794
|
this.numberOfRowsSelected = 0;
|
|
797
795
|
this._dataTask.run().then(r => r);
|
|
798
796
|
|
|
799
|
-
|
|
800
|
-
this.resizeObserver.observe(this);
|
|
801
|
-
}
|
|
797
|
+
this.resizeObserver.observe(this);
|
|
802
798
|
}
|
|
803
799
|
|
|
804
800
|
goToFirstPage() {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {colorDataProvider} from "../../../data-select/providers/color-data-provider";
|
|
2
2
|
import {type CSSResultGroup, html, type PropertyValues, unsafeCSS} from "lit";
|
|
3
3
|
import {property, query, queryAll} from "lit/decorators.js";
|
|
4
|
+
import {ResizeController} from '@lit-labs/observers/resize-controller.js';
|
|
4
5
|
import ZincElement from "../../../../internal/zinc-element";
|
|
5
6
|
import ZnButton from "../../../button";
|
|
6
7
|
import ZnEditorTool from "./tool";
|
|
@@ -24,30 +25,25 @@ export default class ToolbarComponent extends ZincElement {
|
|
|
24
25
|
@query('.toolbar__group--overflow') private _overflowGroup!: HTMLElement;
|
|
25
26
|
|
|
26
27
|
private _featureConfig: EditorFeatureConfig = {};
|
|
27
|
-
private _resizeObserver: ResizeObserver | null = null;
|
|
28
28
|
private _resizeId: number | null = null;
|
|
29
29
|
|
|
30
|
+
private readonly _resizeObserver = new ResizeController(this, {
|
|
31
|
+
callback: () => this.handleResize(),
|
|
32
|
+
});
|
|
33
|
+
|
|
30
34
|
// Tracks DOM nodes (e.g. emoji/date pickers) temporarily moved into the overflow submenu so we can restore them
|
|
31
35
|
private _movedContent: Map<HTMLElement, { placeholder: Comment; originalParent: HTMLElement }> = new Map();
|
|
32
36
|
|
|
33
37
|
connectedCallback() {
|
|
34
38
|
super.connectedCallback();
|
|
35
39
|
this.containerWidth = this.offsetWidth;
|
|
36
|
-
|
|
37
|
-
this._resizeObserver = new ResizeObserver(this.handleResize.bind(this));
|
|
38
40
|
if (this.parentElement) {
|
|
39
41
|
this._resizeObserver.observe(this.parentElement);
|
|
40
42
|
}
|
|
41
|
-
this._resizeObserver.observe(this as HTMLElement);
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
disconnectedCallback() {
|
|
45
46
|
super.disconnectedCallback();
|
|
46
|
-
|
|
47
|
-
if (this._resizeObserver) {
|
|
48
|
-
this._resizeObserver.disconnect();
|
|
49
|
-
this._resizeObserver = null;
|
|
50
|
-
}
|
|
51
47
|
if (this._resizeId !== null) {
|
|
52
48
|
cancelAnimationFrame(this._resizeId);
|
|
53
49
|
this._resizeId = null;
|
|
@@ -2,6 +2,7 @@ import {classMap} from "lit/directives/class-map.js";
|
|
|
2
2
|
import {type CSSResultGroup, html, nothing, type PropertyValues, unsafeCSS} from 'lit';
|
|
3
3
|
import {deepQuerySelectorAll} from "../../utilities/query";
|
|
4
4
|
import {md5} from "../../utilities/md5";
|
|
5
|
+
import {MutationController} from '@lit-labs/observers/mutation-controller.js';
|
|
5
6
|
import {property} from 'lit/decorators.js';
|
|
6
7
|
import {styleMap} from "lit/directives/style-map.js";
|
|
7
8
|
import ZincElement from '../../internal/zinc-element';
|
|
@@ -54,8 +55,36 @@ export default class ZnExpandingAction extends ZincElement {
|
|
|
54
55
|
private _knownUri: Map<string, string> = new Map<string, string>();
|
|
55
56
|
private _actions: HTMLElement[] = [];
|
|
56
57
|
private _preload = true;
|
|
57
|
-
private
|
|
58
|
-
|
|
58
|
+
private _metaObserved = false;
|
|
59
|
+
|
|
60
|
+
private readonly _countObserver = new MutationController(this, {
|
|
61
|
+
target: null,
|
|
62
|
+
config: {subtree: true, attributes: true, attributeFilter: ['content'], childList: true},
|
|
63
|
+
callback: () => {
|
|
64
|
+
const appContent = deepQuerySelectorAll('app-content', this, '')[0];
|
|
65
|
+
const metaCount = appContent?.shadowRoot?.querySelector('meta[name="count"]');
|
|
66
|
+
if (!metaCount) return;
|
|
67
|
+
const count = metaCount.getAttribute('content');
|
|
68
|
+
const notification = this.shadowRoot?.querySelector('.expanding-action__dropdown zn-button');
|
|
69
|
+
if (count && notification) {
|
|
70
|
+
notification.setAttribute('notification', count);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
private readonly _colorObserver = new MutationController(this, {
|
|
76
|
+
target: null,
|
|
77
|
+
config: {subtree: true, attributes: true, attributeFilter: ['content'], childList: true},
|
|
78
|
+
callback: () => {
|
|
79
|
+
const appContent = deepQuerySelectorAll('app-content', this, '')[0];
|
|
80
|
+
const metaColor = appContent?.shadowRoot?.querySelector('meta[name="color"]');
|
|
81
|
+
if (!metaColor) return;
|
|
82
|
+
const color = metaColor.getAttribute('content');
|
|
83
|
+
if (color) {
|
|
84
|
+
this.color = color;
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
});
|
|
59
88
|
|
|
60
89
|
constructor() {
|
|
61
90
|
super();
|
|
@@ -75,12 +104,6 @@ export default class ZnExpandingAction extends ZincElement {
|
|
|
75
104
|
this._panel = this.shadowRoot?.querySelector('#content');
|
|
76
105
|
}
|
|
77
106
|
|
|
78
|
-
disconnectedCallback() {
|
|
79
|
-
super.disconnectedCallback();
|
|
80
|
-
this._countObserver?.disconnect();
|
|
81
|
-
this._colorObserver?.disconnect();
|
|
82
|
-
}
|
|
83
|
-
|
|
84
107
|
firstUpdated(_changedProperties: PropertyValues) {
|
|
85
108
|
super.firstUpdated(_changedProperties);
|
|
86
109
|
|
|
@@ -97,43 +120,14 @@ export default class ZnExpandingAction extends ZincElement {
|
|
|
97
120
|
}
|
|
98
121
|
|
|
99
122
|
_observeMetaData() {
|
|
123
|
+
if (this._metaObserved) return;
|
|
100
124
|
const appContent = deepQuerySelectorAll('app-content', this, '')[0];
|
|
125
|
+
const root = appContent?.shadowRoot;
|
|
126
|
+
if (!root) return;
|
|
101
127
|
|
|
102
|
-
this._countObserver
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
const count = metaCount.getAttribute('content');
|
|
108
|
-
const notification = this.shadowRoot?.querySelector('.expanding-action__dropdown zn-button');
|
|
109
|
-
if (count && notification) {
|
|
110
|
-
notification.setAttribute('notification', count);
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
this._colorObserver = new MutationObserver(() => {
|
|
115
|
-
const metaColor = appContent?.shadowRoot?.querySelector('meta[name="color"]');
|
|
116
|
-
if (!metaColor) {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
const color = metaColor.getAttribute('content');
|
|
120
|
-
if (color) {
|
|
121
|
-
this.color = color;
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
const root = appContent.shadowRoot;
|
|
126
|
-
if (root) {
|
|
127
|
-
const options: MutationObserverInit = {
|
|
128
|
-
subtree: true,
|
|
129
|
-
attributes: true,
|
|
130
|
-
attributeFilter: ['content'],
|
|
131
|
-
childList: true,
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
this._countObserver.observe(root, options);
|
|
135
|
-
this._colorObserver.observe(root, options);
|
|
136
|
-
}
|
|
128
|
+
this._countObserver.observe(root as unknown as Element);
|
|
129
|
+
this._colorObserver.observe(root as unknown as Element);
|
|
130
|
+
this._metaObserved = true;
|
|
137
131
|
}
|
|
138
132
|
|
|
139
133
|
_registerActions() {
|
|
@@ -34,6 +34,8 @@ export default class ZnFormGroup extends ZincElement {
|
|
|
34
34
|
|
|
35
35
|
/** The form groups help text. If you need to display HTML, use the `help-text` slot instead. */
|
|
36
36
|
@property({attribute: 'help-text'}) helpText = '';
|
|
37
|
+
@property({attribute: 'cols', type: Boolean}) forceCols = false;
|
|
38
|
+
@property({attribute: 'layout', type: String}) layout = "1,2";
|
|
37
39
|
|
|
38
40
|
render() {
|
|
39
41
|
const hasLabelSlot = this.hasSlotController.test('label');
|
|
@@ -46,42 +48,45 @@ export default class ZnFormGroup extends ZincElement {
|
|
|
46
48
|
return html`
|
|
47
49
|
<fieldset
|
|
48
50
|
part="form-control"
|
|
49
|
-
class
|
|
51
|
+
class="${classMap({
|
|
50
52
|
'form-control': true,
|
|
51
53
|
'form-control--has-label': hasLabel,
|
|
52
54
|
'form-control--has-label-tooltip': hasLabelTooltip,
|
|
53
55
|
'form-control--has-help-text': hasHelpText
|
|
54
|
-
})}
|
|
56
|
+
})}"
|
|
55
57
|
aria-labelledby="label"
|
|
56
58
|
aria-describedby="help-text">
|
|
57
59
|
|
|
58
|
-
<zn-cols layout="
|
|
59
|
-
${hasLabel ? html`
|
|
60
|
+
<zn-cols layout="${this.layout}" part="form-control-container" class="form-control__container">
|
|
61
|
+
${hasLabel || hasHelpText || this.forceCols ? html`
|
|
60
62
|
<div>
|
|
61
|
-
<label
|
|
62
|
-
part="form-control-label"
|
|
63
|
-
id="label"
|
|
64
|
-
class="form-control__label"
|
|
65
|
-
aria-hidden=${hasLabel ? 'false' : 'true'}>
|
|
66
|
-
<slot name="label">${this.label}</slot>
|
|
67
|
-
${hasLabelTooltip
|
|
68
|
-
? html`
|
|
69
|
-
<zn-tooltip class="form-control--label-tooltip">
|
|
70
|
-
<div slot="content">
|
|
71
|
-
<slot name="label-tooltip">${this.labelTooltip}</slot>
|
|
72
|
-
</div>
|
|
73
|
-
<zn-icon src="info"></zn-icon>
|
|
74
|
-
</zn-tooltip>`
|
|
75
|
-
: ''}
|
|
76
|
-
</label>
|
|
77
|
-
</div>` : html``}
|
|
78
63
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
64
|
+
${hasLabel ? html`
|
|
65
|
+
<label
|
|
66
|
+
part="form-control-label"
|
|
67
|
+
id="label"
|
|
68
|
+
class="form-control__label"
|
|
69
|
+
aria-hidden="${hasLabel ? 'false' : 'true'}">
|
|
70
|
+
<slot name="label">${this.label}</slot>
|
|
71
|
+
${hasLabelTooltip
|
|
72
|
+
? html`
|
|
73
|
+
<zn-tooltip class="form-control--label-tooltip">
|
|
74
|
+
<div slot="content">
|
|
75
|
+
<slot name="label-tooltip">${this.labelTooltip}</slot>
|
|
76
|
+
</div>
|
|
77
|
+
<zn-icon src="info"></zn-icon>
|
|
78
|
+
</zn-tooltip>`
|
|
79
|
+
: ''}
|
|
80
|
+
</label>` : html``}
|
|
81
|
+
|
|
82
|
+
${hasHelpText ? html`
|
|
83
|
+
<div
|
|
84
|
+
part="form-control-help-text"
|
|
85
|
+
id="help-text"
|
|
86
|
+
class="form-control__help-text">
|
|
87
|
+
<slot name="help-text">${this.helpText}</slot>
|
|
88
|
+
</div>` : html``}
|
|
89
|
+
|
|
85
90
|
</div>` : html``}
|
|
86
91
|
|
|
87
92
|
<div part="form-control-input" class="form-control-input">
|
|
@@ -4,7 +4,7 @@ import {HasSlotController} from "../../internal/slot";
|
|
|
4
4
|
import {property} from 'lit/decorators.js';
|
|
5
5
|
import {watch} from "../../internal/watch";
|
|
6
6
|
import ZincElement from '../../internal/zinc-element';
|
|
7
|
-
import
|
|
7
|
+
import ZnNavbar from "../navbar";
|
|
8
8
|
|
|
9
9
|
import styles from './header.scss';
|
|
10
10
|
|
|
@@ -51,6 +51,8 @@ export default class ZnHeader extends ZincElement {
|
|
|
51
51
|
|
|
52
52
|
@property({attribute: 'previous-target'}) previousTarget: string;
|
|
53
53
|
|
|
54
|
+
@property({attribute: 'hide-breadcrumb', type: Boolean}) hideBreadcrumb: boolean = false;
|
|
55
|
+
|
|
54
56
|
private navbar: ZnNavbar;
|
|
55
57
|
|
|
56
58
|
// Attach any event listeners you may need
|
|
@@ -106,7 +108,7 @@ export default class ZnHeader extends ZincElement {
|
|
|
106
108
|
const hasPreviousPath = this.previousPath;
|
|
107
109
|
const hasEntityId = this.entityId;
|
|
108
110
|
const hasFullLocation = this.fullLocation;
|
|
109
|
-
const hasBreadcrumb = this.hasSlotController.test('breadcrumb');
|
|
111
|
+
const hasBreadcrumb = !this.hideBreadcrumb && this.hasSlotController.test('breadcrumb');
|
|
110
112
|
|
|
111
113
|
// Do not add formatting within breadcrumb or navigation - css:empty in use
|
|
112
114
|
const header = html`
|
|
@@ -137,9 +139,6 @@ export default class ZnHeader extends ZincElement {
|
|
|
137
139
|
|
|
138
140
|
|
|
139
141
|
<div class="content" part="content">
|
|
140
|
-
${hasBreadcrumb ? html`
|
|
141
|
-
<slot name="breadcrumb" class="breadcrumb"></slot>` : null}
|
|
142
|
-
|
|
143
142
|
${hasPreviousPath ? html`
|
|
144
143
|
<a href="${this.previousPath}" class="caption__back"
|
|
145
144
|
data-target="${this.previousTarget ? this.previousTarget : ''}">
|
|
@@ -156,6 +155,8 @@ export default class ZnHeader extends ZincElement {
|
|
|
156
155
|
<span class="header__caption" part="header-caption">
|
|
157
156
|
${this.icon ? html`
|
|
158
157
|
<zn-icon class="header__icon" src="${this.icon}"></zn-icon>` : null}
|
|
158
|
+
${hasBreadcrumb ? html`
|
|
159
|
+
<slot name="breadcrumb" class="breadcrumb"></slot>` : null}
|
|
159
160
|
<slot name="caption">${this.caption}</slot>
|
|
160
161
|
</span>
|
|
161
162
|
${this.description ? html`
|
|
@@ -14,12 +14,14 @@
|
|
|
14
14
|
justify-content: space-between;
|
|
15
15
|
gap: var(--zn-spacing-2x-small);
|
|
16
16
|
max-width: 100%;
|
|
17
|
+
min-height: 58px;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
&__caption {
|
|
20
21
|
font-weight: var(--zn-font-weight-medium);
|
|
21
|
-
font-size: var(--zn-font-size-
|
|
22
|
+
font-size: var(--zn-font-size-large);
|
|
22
23
|
color: rgba(var(--zn-text-panel-title), 100%);
|
|
24
|
+
line-height: 28px;
|
|
23
25
|
margin: 0;
|
|
24
26
|
overflow: hidden;
|
|
25
27
|
white-space: nowrap;
|
|
@@ -30,17 +32,15 @@
|
|
|
30
32
|
text-wrap: auto;
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
&--has-breadcrumb {
|
|
34
|
-
.caption {
|
|
35
|
-
padding-top: 0;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
35
|
// remove the padding on the nav
|
|
40
36
|
&--has-nav {
|
|
41
37
|
.caption {
|
|
42
38
|
padding-bottom: 0;
|
|
43
39
|
}
|
|
40
|
+
|
|
41
|
+
.content {
|
|
42
|
+
padding-bottom: var(--zn-spacing-x-small);
|
|
43
|
+
}
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -51,10 +51,6 @@
|
|
|
51
51
|
color: inherit;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
.content {
|
|
55
|
-
padding: var(--zn-spacing-x-small) 0;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
54
|
:host([transparent]) > div {
|
|
59
55
|
background-color: transparent;
|
|
60
56
|
}
|
|
@@ -71,6 +67,8 @@
|
|
|
71
67
|
|
|
72
68
|
:host #nav-container {
|
|
73
69
|
gap: 0;
|
|
70
|
+
border-bottom: 1px solid rgb(var(--zn-border-color));
|
|
71
|
+
margin: 0 3px;
|
|
74
72
|
}
|
|
75
73
|
|
|
76
74
|
.alt-overlay {
|
|
@@ -104,14 +102,21 @@
|
|
|
104
102
|
}
|
|
105
103
|
}
|
|
106
104
|
|
|
105
|
+
:host([transparent]) {
|
|
106
|
+
.header {
|
|
107
|
+
margin: 0;
|
|
108
|
+
|
|
109
|
+
&__caption {
|
|
110
|
+
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
107
114
|
|
|
108
115
|
.header {
|
|
109
116
|
display: flex;
|
|
110
117
|
flex-direction: column;
|
|
111
|
-
|
|
112
|
-
// border-top-width: 1px;
|
|
118
|
+
margin: 0;
|
|
113
119
|
overflow: hidden;
|
|
114
|
-
background-color: rgba(var(--zn-panel), var(--zn-panel-opacity));
|
|
115
120
|
|
|
116
121
|
.content {
|
|
117
122
|
display: flex;
|
|
@@ -130,7 +135,7 @@
|
|
|
130
135
|
justify-content: center;
|
|
131
136
|
flex-direction: column;
|
|
132
137
|
gap: 1px;
|
|
133
|
-
min-height:
|
|
138
|
+
min-height: 24px;
|
|
134
139
|
flex-shrink: 1;
|
|
135
140
|
max-width: 100%;
|
|
136
141
|
}
|
|
@@ -158,19 +163,15 @@
|
|
|
158
163
|
}
|
|
159
164
|
|
|
160
165
|
.breadcrumb {
|
|
161
|
-
|
|
162
|
-
font-size: var(--zn-font-size-x-small);
|
|
163
|
-
font-weight: var(--zn-font-weight-semibold);
|
|
164
|
-
color: rgb(var(--zn-text));
|
|
165
|
-
|
|
166
|
-
display: flex;
|
|
166
|
+
display: inline-flex;
|
|
167
167
|
align-items: center;
|
|
168
168
|
gap: var(--zn-spacing-2x-small);
|
|
169
|
+
font: inherit;
|
|
170
|
+
color: inherit;
|
|
169
171
|
|
|
170
172
|
&::slotted(a) {
|
|
171
|
-
font
|
|
173
|
+
font: inherit;
|
|
172
174
|
color: inherit;
|
|
173
|
-
font-weight: var(--zn-font-weight-normal);
|
|
174
175
|
text-decoration: inherit;
|
|
175
176
|
}
|
|
176
177
|
|
|
@@ -178,10 +179,11 @@
|
|
|
178
179
|
color: rgb(var(--zn-primary));
|
|
179
180
|
}
|
|
180
181
|
|
|
181
|
-
&::slotted(a
|
|
182
|
+
&::slotted(a)::after {
|
|
182
183
|
content: '>';
|
|
183
184
|
margin-left: var(--zn-spacing-2x-small);
|
|
184
185
|
color: rgb(var(--zn-text-muted));
|
|
186
|
+
font-weight: var(--zn-font-weight-normal);
|
|
185
187
|
}
|
|
186
188
|
}
|
|
187
189
|
|
|
@@ -211,17 +213,17 @@
|
|
|
211
213
|
|
|
212
214
|
h1 {
|
|
213
215
|
flex-grow: 1;
|
|
214
|
-
font-size: 18px;
|
|
215
216
|
|
|
216
217
|
overflow: hidden;
|
|
217
218
|
text-overflow: ellipsis;
|
|
218
219
|
|
|
219
220
|
color: rgb(var(--zn-text-page-title));
|
|
220
221
|
margin: 0;
|
|
222
|
+
font-size: var(--zn-font-size-medium);
|
|
221
223
|
font-weight: var(--zn-font-weight-medium);
|
|
222
224
|
|
|
223
225
|
@media screen and (min-width: var(--zn-container-lg)) {
|
|
224
|
-
font-size: var(--zn-font-size-
|
|
226
|
+
font-size: var(--zn-font-size-large);
|
|
225
227
|
}
|
|
226
228
|
|
|
227
229
|
&:empty {
|
|
@@ -108,6 +108,12 @@ export default class ZnInlineEdit extends ZincElement implements ZincFormControl
|
|
|
108
108
|
/** Enables search/filtering on select inputs. */
|
|
109
109
|
@property({ type: Boolean }) search: boolean;
|
|
110
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Allows entering values that aren't in the options list on select inputs ("free text"). Setting this implies
|
|
113
|
+
* `input-type="select"` (unless a data `provider` is used) and forwards the behavior to the inner `<zn-select>`.
|
|
114
|
+
*/
|
|
115
|
+
@property({ type: Boolean, attribute: 'free-text' }) freeText: boolean;
|
|
116
|
+
|
|
111
117
|
/** The input's help text. If you need to display HTML, use the `help-text` slot instead. **/
|
|
112
118
|
@property({ attribute: 'help-text' }) helpText: string = '';
|
|
113
119
|
|
|
@@ -315,6 +321,11 @@ export default class ZnInlineEdit extends ZincElement implements ZincFormControl
|
|
|
315
321
|
this.inputType = 'data-select';
|
|
316
322
|
}
|
|
317
323
|
|
|
324
|
+
// Free text is a select capability — imply a select input when it's set (unless a data provider is used)
|
|
325
|
+
if (this.freeText && !this.selectProvider) {
|
|
326
|
+
this.inputType = 'select';
|
|
327
|
+
}
|
|
328
|
+
|
|
318
329
|
let input: HTMLTemplateResult;
|
|
319
330
|
switch (this.inputType) {
|
|
320
331
|
case 'select':
|
|
@@ -457,7 +468,8 @@ export default class ZnInlineEdit extends ZincElement implements ZincFormControl
|
|
|
457
468
|
multiple=${ifDefined(this.multiple)}
|
|
458
469
|
clearable=${ifDefined(this.isEditing ? this.clearable : undefined)}
|
|
459
470
|
?search=${this.search}
|
|
460
|
-
|
|
471
|
+
?free-text=${this.freeText}
|
|
472
|
+
?non-removable=${!this.isEditing}
|
|
461
473
|
data-uri=${ifDefined(this.dataUri)}
|
|
462
474
|
context-data=${ifDefined(this.contextData)}
|
|
463
475
|
@zn-input="${this.handleInput}"
|
|
@@ -309,6 +309,56 @@ describe('<zn-inline-edit>', () => {
|
|
|
309
309
|
expect(formData.get('tags')).to.equal('');
|
|
310
310
|
});
|
|
311
311
|
|
|
312
|
+
// -- Free text --
|
|
313
|
+
|
|
314
|
+
it('should pass free-text to the inner select', async () => {
|
|
315
|
+
const el = await fixture<ZnInlineEdit>(html`
|
|
316
|
+
<zn-inline-edit input-type="select" free-text>
|
|
317
|
+
<zn-option value="a">A</zn-option>
|
|
318
|
+
</zn-inline-edit>
|
|
319
|
+
`);
|
|
320
|
+
await el.updateComplete;
|
|
321
|
+
|
|
322
|
+
const select = el.shadowRoot?.querySelector('zn-select') as ZnSelect;
|
|
323
|
+
expect(select).to.exist;
|
|
324
|
+
expect(select.freeText).to.be.true;
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('should render a free-text select when free-text is set without an input-type', async () => {
|
|
328
|
+
const el = await fixture<ZnInlineEdit>(html`
|
|
329
|
+
<zn-inline-edit free-text></zn-inline-edit>
|
|
330
|
+
`);
|
|
331
|
+
await el.updateComplete;
|
|
332
|
+
|
|
333
|
+
const select = el.shadowRoot?.querySelector('zn-select') as ZnSelect;
|
|
334
|
+
expect(select, 'free-text should imply a select input').to.exist;
|
|
335
|
+
expect(select.freeText).to.be.true;
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it('should make inner select tags removable only while editing', async () => {
|
|
339
|
+
const el = await fixture<ZnInlineEdit>(html`
|
|
340
|
+
<zn-inline-edit free-text multiple value="a">
|
|
341
|
+
<zn-option value="a">A</zn-option>
|
|
342
|
+
</zn-inline-edit>
|
|
343
|
+
`);
|
|
344
|
+
await el.updateComplete;
|
|
345
|
+
|
|
346
|
+
const select = el.shadowRoot?.querySelector('zn-select') as ZnSelect;
|
|
347
|
+
expect(select).to.exist;
|
|
348
|
+
|
|
349
|
+
// Display mode: tags are not removable (no X)
|
|
350
|
+
expect(select.nonRemovable).to.be.true;
|
|
351
|
+
|
|
352
|
+
// Enter edit mode
|
|
353
|
+
const editBtn = el.shadowRoot!.querySelector<HTMLElement>('.button--edit')!;
|
|
354
|
+
editBtn.dispatchEvent(new MouseEvent('click', {bubbles: true, composed: true}));
|
|
355
|
+
await el.updateComplete;
|
|
356
|
+
await select.updateComplete;
|
|
357
|
+
|
|
358
|
+
// Editing: tags become removable (X shows)
|
|
359
|
+
expect(select.nonRemovable).to.be.false;
|
|
360
|
+
});
|
|
361
|
+
|
|
312
362
|
it('should flatten array to string when multiple is not set', async () => {
|
|
313
363
|
const el = await fixture<ZnInlineEdit>(
|
|
314
364
|
html`<zn-inline-edit value="hello"></zn-inline-edit>`
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import '../../../dist/zn.min.js';
|
|
2
2
|
import {expect, fixture, html} from '@open-wc/testing';
|
|
3
|
+
import {clearFormStoreValues} from '../../utilities/form';
|
|
3
4
|
import type ZnInput from './input.component';
|
|
4
5
|
|
|
5
6
|
describe('<zn-input>', () => {
|
|
@@ -40,4 +41,80 @@ describe('<zn-input>', () => {
|
|
|
40
41
|
expect(wrapperEscapes, 'wrapper should not see Escape on press 1').to.equal(0);
|
|
41
42
|
});
|
|
42
43
|
});
|
|
44
|
+
|
|
45
|
+
describe('persisted state', () => {
|
|
46
|
+
const formStoreKey = 'input-test-form-state';
|
|
47
|
+
const elementStoreKey = 'input-test-element-state';
|
|
48
|
+
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
clearFormStoreValues(formStoreKey);
|
|
51
|
+
clearFormStoreValues(elementStoreKey);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
afterEach(() => {
|
|
55
|
+
clearFormStoreValues(formStoreKey);
|
|
56
|
+
clearFormStoreValues(elementStoreKey);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('restores values from a form store-key after refresh', async () => {
|
|
60
|
+
const firstForm = await fixture<HTMLFormElement>(html`
|
|
61
|
+
<form store-key=${formStoreKey}>
|
|
62
|
+
<zn-input name="first_name"></zn-input>
|
|
63
|
+
</form>
|
|
64
|
+
`);
|
|
65
|
+
const firstInput = firstForm.querySelector('zn-input') as ZnInput;
|
|
66
|
+
await firstInput.updateComplete;
|
|
67
|
+
|
|
68
|
+
firstInput.value = 'Ada';
|
|
69
|
+
firstInput.dispatchEvent(new CustomEvent('zn-input', {bubbles: true, composed: true}));
|
|
70
|
+
|
|
71
|
+
const secondForm = await fixture<HTMLFormElement>(html`
|
|
72
|
+
<form store-key=${formStoreKey}>
|
|
73
|
+
<zn-input name="first_name"></zn-input>
|
|
74
|
+
</form>
|
|
75
|
+
`);
|
|
76
|
+
const secondInput = secondForm.querySelector('zn-input') as ZnInput;
|
|
77
|
+
await secondInput.updateComplete;
|
|
78
|
+
|
|
79
|
+
expect(secondInput.value).to.equal('Ada');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('restores values from an element store-key without a form store-key', async () => {
|
|
83
|
+
const firstInput = await fixture<ZnInput>(html`<zn-input store-key=${elementStoreKey}></zn-input>`);
|
|
84
|
+
await firstInput.updateComplete;
|
|
85
|
+
|
|
86
|
+
firstInput.value = 'Lovelace';
|
|
87
|
+
firstInput.dispatchEvent(new CustomEvent('zn-input', {bubbles: true, composed: true}));
|
|
88
|
+
|
|
89
|
+
const secondInput = await fixture<ZnInput>(html`<zn-input store-key=${elementStoreKey}></zn-input>`);
|
|
90
|
+
await secondInput.updateComplete;
|
|
91
|
+
|
|
92
|
+
expect(secondInput.value).to.equal('Lovelace');
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('clears values for a form store-key', async () => {
|
|
96
|
+
const firstForm = await fixture<HTMLFormElement>(html`
|
|
97
|
+
<form store-key=${formStoreKey}>
|
|
98
|
+
<zn-input name="first_name"></zn-input>
|
|
99
|
+
</form>
|
|
100
|
+
`);
|
|
101
|
+
const firstInput = firstForm.querySelector('zn-input') as ZnInput;
|
|
102
|
+
await firstInput.updateComplete;
|
|
103
|
+
|
|
104
|
+
firstInput.value = 'Grace';
|
|
105
|
+
firstInput.dispatchEvent(new CustomEvent('zn-input', {bubbles: true, composed: true}));
|
|
106
|
+
|
|
107
|
+
clearFormStoreValues(firstForm);
|
|
108
|
+
|
|
109
|
+
const secondForm = await fixture<HTMLFormElement>(html`
|
|
110
|
+
<form store-key=${formStoreKey}>
|
|
111
|
+
<zn-input name="first_name"></zn-input>
|
|
112
|
+
</form>
|
|
113
|
+
`);
|
|
114
|
+
const secondInput = secondForm.querySelector('zn-input') as ZnInput;
|
|
115
|
+
await secondInput.updateComplete;
|
|
116
|
+
|
|
117
|
+
expect(secondInput.value).to.equal('');
|
|
118
|
+
});
|
|
119
|
+
});
|
|
43
120
|
});
|