@kubex/zinc 1.1.140 → 1.1.142
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 +337 -80
- package/dist/vscode.html-custom-data.json +44 -14
- package/dist/web-types.json +101 -28
- package/dist/zn.d.ts +560 -527
- package/dist/zn.min.js +1091 -1063
- package/package.json +1 -1
- package/src/components/form-group/form-group.scss +11 -1
- package/src/components/form-group/form-group.test.ts +16 -0
- package/src/components/linked-select/linked-select.component.ts +37 -5
- package/src/components/linked-select/linked-select.test.ts +95 -9
- package/src/components/opt-group/opt-group.component.ts +19 -0
- package/src/components/opt-group/opt-group.scss +1 -1
- package/src/components/page-builder/page-builder.component.ts +56 -2
- package/src/components/page-builder/page-builder.scss +41 -0
- package/src/components/page-builder/page-builder.test.ts +210 -0
- package/src/components/remarkd-editor/remarkd-editor.component.ts +2 -0
- package/src/components/remarkd-editor/remarkd-editor.test.ts +35 -7
- package/src/components/select/select.component.ts +15 -0
- package/src/components/select/select.test.ts +10 -0
- package/src/components/sp/sp.scss +6 -0
- package/src/components/sp/sp.test.ts +31 -0
- package/src/components/translations/translations.component.ts +33 -2
- package/src/components/translations/translations.test.ts +41 -0
package/package.json
CHANGED
|
@@ -102,8 +102,18 @@
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
// The 70px is the gutter between the label column and the fields. Once zn-cols
|
|
106
|
+
// wraps them into one column it is dead space above the fields instead, so it
|
|
107
|
+
// only applies at the width the two columns actually fit — the same 670px the
|
|
108
|
+
// sticky label uses.
|
|
105
109
|
zn-cols::part(base) {
|
|
106
|
-
gap:
|
|
110
|
+
gap: var(--zn-gap);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@container (min-width: 670px) {
|
|
114
|
+
zn-cols::part(base) {
|
|
115
|
+
gap: 70px;
|
|
116
|
+
}
|
|
107
117
|
}
|
|
108
118
|
|
|
109
119
|
|
|
@@ -126,4 +126,20 @@ describe('<zn-form-group>', () => {
|
|
|
126
126
|
expect(after).to.be.closeTo(before, 4);
|
|
127
127
|
});
|
|
128
128
|
});
|
|
129
|
+
|
|
130
|
+
it('should gutter the label column only while it sits beside the fields', async () => {
|
|
131
|
+
const wide = await fixture<HTMLElement>(html`
|
|
132
|
+
<div style="width: 900px; container-type: inline-size;">
|
|
133
|
+
<zn-form-group label="Wide"><div>Field</div></zn-form-group>
|
|
134
|
+
</div>`);
|
|
135
|
+
const wideCols = wide.querySelector('zn-form-group')!.shadowRoot!.querySelector('zn-cols')!;
|
|
136
|
+
expect(getComputedStyle(wideCols.shadowRoot!.querySelector('.cols')!).columnGap).to.equal('70px');
|
|
137
|
+
|
|
138
|
+
const narrow = await fixture<HTMLElement>(html`
|
|
139
|
+
<div style="width: 400px; container-type: inline-size;">
|
|
140
|
+
<zn-form-group label="Narrow"><div>Field</div></zn-form-group>
|
|
141
|
+
</div>`);
|
|
142
|
+
const narrowCols = narrow.querySelector('zn-form-group')!.shadowRoot!.querySelector('zn-cols')!;
|
|
143
|
+
expect(getComputedStyle(narrowCols.shadowRoot!.querySelector('.cols')!).rowGap).to.not.equal('70px');
|
|
144
|
+
});
|
|
129
145
|
});
|
|
@@ -39,10 +39,10 @@ export default class ZnLinkedSelect extends ZincElement implements ZincFormContr
|
|
|
39
39
|
static styles: CSSResultGroup = unsafeCSS(styles);
|
|
40
40
|
|
|
41
41
|
@property() name: string = "";
|
|
42
|
-
@property() value: string;
|
|
42
|
+
@property() value: string | string[] = '';
|
|
43
43
|
|
|
44
44
|
/** The default value of the form control. Primarily used for resetting the form control. */
|
|
45
|
-
@defaultValue() defaultValue: string = '';
|
|
45
|
+
@defaultValue() defaultValue: string | string[] = '';
|
|
46
46
|
|
|
47
47
|
@property({type: Boolean, reflect: true}) checked = false;
|
|
48
48
|
@property({type: Array}) options: linkedSelectOptions;
|
|
@@ -54,6 +54,14 @@ export default class ZnLinkedSelect extends ZincElement implements ZincFormContr
|
|
|
54
54
|
/** Automatically select the first option of the linked group when no value is set. */
|
|
55
55
|
@property({attribute: 'select-first', type: Boolean}) selectFirst = false;
|
|
56
56
|
|
|
57
|
+
/** Allows more than one option of the linked group to be selected. */
|
|
58
|
+
@property({type: Boolean, reflect: true}) multiple = false;
|
|
59
|
+
|
|
60
|
+
@property() placeholder = '';
|
|
61
|
+
@property({type: Boolean}) clearable = false;
|
|
62
|
+
@property({type: Boolean}) search = false;
|
|
63
|
+
@property({attribute: 'help-text'}) helpText = '';
|
|
64
|
+
|
|
57
65
|
@query('zn-select') input: ZnSelect;
|
|
58
66
|
|
|
59
67
|
private linkedSelectElement: HTMLSelectElement | ZnSelect;
|
|
@@ -100,6 +108,15 @@ export default class ZnLinkedSelect extends ZincElement implements ZincFormContr
|
|
|
100
108
|
}
|
|
101
109
|
}
|
|
102
110
|
|
|
111
|
+
protected willUpdate(_changedProperties: PropertyValues) {
|
|
112
|
+
super.willUpdate(_changedProperties);
|
|
113
|
+
// An unset value is the empty string, which the inner select would read as a
|
|
114
|
+
// single selection of "".
|
|
115
|
+
if (this.multiple && !Array.isArray(this.value)) {
|
|
116
|
+
this.value = this.value ? this.value.split(' ') : [];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
103
120
|
protected firstUpdated(_changedProperties: PropertyValues) {
|
|
104
121
|
this.linkedSelectElement?.addEventListener('zn-change', this.handleLinkedSelectChange);
|
|
105
122
|
this.input.addEventListener('zn-change', this.handleChange);
|
|
@@ -131,21 +148,31 @@ export default class ZnLinkedSelect extends ZincElement implements ZincFormContr
|
|
|
131
148
|
}
|
|
132
149
|
|
|
133
150
|
public handleLinkedSelectChange = () => {
|
|
151
|
+
const previous = this.serialisedValue();
|
|
134
152
|
// The inner select only auto-selects on slotchange, which lit skips when it
|
|
135
153
|
// can reuse the option elements of the outgoing group, so the first option of
|
|
136
154
|
// the new group is resolved here rather than left to the select.
|
|
137
|
-
this.value = this.selectFirst ? Object.keys(this.currentOptions())[0] ?? "" : "";
|
|
155
|
+
this.value = this.multiple ? [] : this.selectFirst ? Object.keys(this.currentOptions())[0] ?? "" : "";
|
|
138
156
|
this.requestUpdate();
|
|
139
157
|
this.formControlController.updateValidity();
|
|
158
|
+
// A host reading the value off change events would otherwise keep the
|
|
159
|
+
// selection made against the previous group.
|
|
160
|
+
if (previous !== this.serialisedValue()) {
|
|
161
|
+
this.emit('zn-change');
|
|
162
|
+
}
|
|
140
163
|
};
|
|
141
164
|
|
|
165
|
+
private serialisedValue(): string {
|
|
166
|
+
return Array.isArray(this.value) ? this.value.join(' ') : this.value;
|
|
167
|
+
}
|
|
168
|
+
|
|
142
169
|
public handleChange(e: Event) {
|
|
143
170
|
this.value = (e.target as HTMLSelectElement).value;
|
|
144
171
|
this.formControlController.updateValidity();
|
|
145
172
|
}
|
|
146
173
|
|
|
147
174
|
handleSelectChange = (e: ZnSelectEvent) => {
|
|
148
|
-
this.value = (e.target as ZnSelect).value
|
|
175
|
+
this.value = (e.target as ZnSelect).value;
|
|
149
176
|
}
|
|
150
177
|
|
|
151
178
|
/** The options of the group the linked select currently points at. */
|
|
@@ -171,7 +198,12 @@ export default class ZnLinkedSelect extends ZincElement implements ZincFormContr
|
|
|
171
198
|
id="main-input"
|
|
172
199
|
cache-key="${this.cacheKey}"
|
|
173
200
|
?select-first="${this.selectFirst}"
|
|
174
|
-
|
|
201
|
+
?multiple="${this.multiple}"
|
|
202
|
+
?clearable="${this.clearable}"
|
|
203
|
+
?search="${this.search}"
|
|
204
|
+
placeholder="${this.placeholder}"
|
|
205
|
+
help-text="${this.helpText}"
|
|
206
|
+
.value="${this.value}"
|
|
175
207
|
@zn-change=${this.handleSelectChange}
|
|
176
208
|
label="${this.label}">
|
|
177
209
|
${options && Object.entries(options).map(([key, value]) => html`
|
|
@@ -1,17 +1,103 @@
|
|
|
1
1
|
import '../../../dist/zn.min.js';
|
|
2
|
-
import { expect, fixture, html } from '@open-wc/testing';
|
|
2
|
+
import { expect, fixture, html, oneEvent, waitUntil } from '@open-wc/testing';
|
|
3
|
+
import type ZnLinkedSelect from './linked-select.component';
|
|
4
|
+
import type ZnSelect from '../select';
|
|
5
|
+
|
|
6
|
+
const options = {
|
|
7
|
+
'': {},
|
|
8
|
+
'cat-1': { 'cat-1-a': 'Disputes', 'cat-1-b': 'Refunds' },
|
|
9
|
+
'cat-2': { 'cat-2-a': 'Delivery' },
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
async function group(multiple = false) {
|
|
13
|
+
const wrapper = await fixture<HTMLDivElement>(html`
|
|
14
|
+
<div>
|
|
15
|
+
<zn-select id="parent" name="parent">
|
|
16
|
+
<zn-option value="cat-1">Billing</zn-option>
|
|
17
|
+
<zn-option value="cat-2">Orders</zn-option>
|
|
18
|
+
</zn-select>
|
|
19
|
+
<zn-linked-select linked-select="parent" name="child"
|
|
20
|
+
?multiple=${multiple} .options=${options}></zn-linked-select>
|
|
21
|
+
</div>`);
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
parent: wrapper.querySelector<ZnSelect>('zn-select')!,
|
|
25
|
+
child: wrapper.querySelector<ZnLinkedSelect>('zn-linked-select')!,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function childOptions(child: ZnLinkedSelect): string[] {
|
|
30
|
+
return [...child.shadowRoot!.querySelectorAll('zn-option')].map(option => option.getAttribute('value')!);
|
|
31
|
+
}
|
|
3
32
|
|
|
4
33
|
describe('<zn-linked-select>', () => {
|
|
5
34
|
it('should render a component', async () => {
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
35
|
+
const { child } = await group();
|
|
36
|
+
expect(child).to.exist;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should only offer the options of the linked select group', async () => {
|
|
40
|
+
const { parent, child } = await group();
|
|
41
|
+
|
|
42
|
+
parent.value = 'cat-1';
|
|
43
|
+
parent.emit('zn-change');
|
|
44
|
+
await waitUntil(() => childOptions(child).length === 2);
|
|
45
|
+
|
|
46
|
+
expect(childOptions(child)).to.deep.equal(['cat-1-a', 'cat-1-b']);
|
|
47
|
+
|
|
48
|
+
parent.value = 'cat-2';
|
|
49
|
+
parent.emit('zn-change');
|
|
50
|
+
await waitUntil(() => childOptions(child).length === 1);
|
|
51
|
+
|
|
52
|
+
expect(childOptions(child)).to.deep.equal(['cat-2-a']);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should offer no options until the linked select has a value', async () => {
|
|
56
|
+
const { child } = await group();
|
|
57
|
+
expect(childOptions(child)).to.deep.equal([]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should keep an array value when multiple', async () => {
|
|
61
|
+
const { parent, child } = await group(true);
|
|
62
|
+
parent.value = 'cat-1';
|
|
63
|
+
parent.emit('zn-change');
|
|
64
|
+
await waitUntil(() => childOptions(child).length === 2);
|
|
65
|
+
|
|
66
|
+
child.value = ['cat-1-a', 'cat-1-b'];
|
|
67
|
+
await child.updateComplete;
|
|
68
|
+
|
|
69
|
+
expect(child.input.multiple).to.be.true;
|
|
70
|
+
expect(child.input.value).to.deep.equal(['cat-1-a', 'cat-1-b']);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should start a multiple select with no selection', async () => {
|
|
74
|
+
const { child } = await group(true);
|
|
75
|
+
expect(child.value).to.deep.equal([]);
|
|
76
|
+
expect(child.input.value).to.deep.equal([]);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should clear a multiple selection when the linked select changes', async () => {
|
|
80
|
+
const { parent, child } = await group(true);
|
|
81
|
+
child.value = ['cat-1-a'];
|
|
82
|
+
await child.updateComplete;
|
|
83
|
+
|
|
84
|
+
parent.value = 'cat-2';
|
|
85
|
+
const changed = oneEvent(child, 'zn-change');
|
|
86
|
+
parent.emit('zn-change');
|
|
87
|
+
await changed;
|
|
88
|
+
|
|
89
|
+
expect(child.value).to.deep.equal([]);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should not announce a change when the value was already empty', async () => {
|
|
93
|
+
const { parent, child } = await group(true);
|
|
94
|
+
let changes = 0;
|
|
95
|
+
child.addEventListener('zn-change', () => changes++);
|
|
10
96
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
97
|
+
parent.value = 'cat-2';
|
|
98
|
+
parent.emit('zn-change');
|
|
99
|
+
await child.updateComplete;
|
|
14
100
|
|
|
15
|
-
expect(
|
|
101
|
+
expect(changes).to.equal(0);
|
|
16
102
|
});
|
|
17
103
|
});
|
|
@@ -47,6 +47,25 @@ export default class ZnOptGroup extends ZincElement {
|
|
|
47
47
|
this.hidden = options.length > 0 && options.every(option => option.hidden);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* @internal - Marks the group as the first visible one so it doesn't draw a separator against the top of the
|
|
52
|
+
* listbox. Structural `:first-child` can't see that earlier siblings were hidden by a search filter.
|
|
53
|
+
*/
|
|
54
|
+
updateSeparator() {
|
|
55
|
+
let previous = this.previousElementSibling;
|
|
56
|
+
while (previous && !ZnOptGroup.isRendered(previous)) {
|
|
57
|
+
previous = previous.previousElementSibling;
|
|
58
|
+
}
|
|
59
|
+
this.toggleAttribute('data-first-visible', previous === null);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private static isRendered(el: Element): boolean {
|
|
63
|
+
if (el instanceof HTMLSlotElement) {
|
|
64
|
+
return el.assignedElements().some(assigned => ZnOptGroup.isRendered(assigned));
|
|
65
|
+
}
|
|
66
|
+
return !(el instanceof HTMLElement) || !el.hidden;
|
|
67
|
+
}
|
|
68
|
+
|
|
50
69
|
render() {
|
|
51
70
|
return html`
|
|
52
71
|
<div part="base" class="opt-group">
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
display: none !important;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
:host(:not(:first-child)) {
|
|
11
|
+
:host(:not(:first-child):not([data-first-visible])) {
|
|
12
12
|
border-block-start: solid var(--zn-panel-border-width) var(--zn-panel-border-color);
|
|
13
13
|
margin-block-start: var(--zn-spacing-2x-small);
|
|
14
14
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CSSResultGroup, html, type PropertyValues, unsafeCSS } from 'lit';
|
|
1
|
+
import { type CSSResultGroup, html, nothing, type PropertyValues, unsafeCSS } from 'lit';
|
|
2
2
|
import {
|
|
3
3
|
emptyDragImage,
|
|
4
4
|
emptyPageState,
|
|
@@ -35,6 +35,12 @@ const MAX_SECTIONS = 500;
|
|
|
35
35
|
/** Builder width below which the palette auto-collapses — keep in sync with the @container query in page-builder.scss. */
|
|
36
36
|
const NARROW_WIDTH = 768;
|
|
37
37
|
|
|
38
|
+
// 300 matches the narrow-container floor in the stylesheet: below it the
|
|
39
|
+
// inspector's toggle rows wrap their switch under the label.
|
|
40
|
+
const MIN_INSPECTOR_WIDTH = 300;
|
|
41
|
+
const MIN_CANVAS_WIDTH = 200;
|
|
42
|
+
const RESIZE_STEP = 20;
|
|
43
|
+
|
|
38
44
|
const AUTO_SAVE_DEFAULT_MINUTES = 5;
|
|
39
45
|
const AUTO_SAVE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
40
46
|
|
|
@@ -158,6 +164,8 @@ export default class ZnPageBuilder extends ZincElement {
|
|
|
158
164
|
@state() private _slotPicker: { containerId: string; index: number } | null = null;
|
|
159
165
|
/** The stamped config form for the selected section; rebuilt on selection change. */
|
|
160
166
|
@state() private _form: HTMLDivElement | null = null;
|
|
167
|
+
@state() private _inspectorWidth: number | null = null;
|
|
168
|
+
@state() private _inspectorWide = false;
|
|
161
169
|
|
|
162
170
|
private readonly _hasSlot = new HasSlotController(this, 'header-left', 'header-right');
|
|
163
171
|
|
|
@@ -1301,6 +1309,7 @@ export default class ZnPageBuilder extends ZincElement {
|
|
|
1301
1309
|
// A content-free template stamps no controls — leave the form null so the
|
|
1302
1310
|
// inspector shows its "no settings" hint rather than a blank gap.
|
|
1303
1311
|
this._form = form.childElementCount ? form : null;
|
|
1312
|
+
this._inspectorWide = Boolean(this._form?.querySelector('zn-remarkd-editor, [input-type="remarkd"]'));
|
|
1304
1313
|
}
|
|
1305
1314
|
|
|
1306
1315
|
private _isBooleanControl(control: HTMLElement, value: unknown): boolean {
|
|
@@ -1336,6 +1345,41 @@ export default class ZnPageBuilder extends ZincElement {
|
|
|
1336
1345
|
this._commit({ sections: this._patchSection(id, s => ({ ...s, label: label || undefined })) });
|
|
1337
1346
|
}
|
|
1338
1347
|
|
|
1348
|
+
/** Width the inspector may be dragged to, against the builder's own width. */
|
|
1349
|
+
private _clampInspector(width: number): number {
|
|
1350
|
+
const room = this.getBoundingClientRect().width - MIN_CANVAS_WIDTH;
|
|
1351
|
+
return Math.round(Math.min(Math.max(width, MIN_INSPECTOR_WIDTH), Math.max(room, MIN_INSPECTOR_WIDTH)));
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
private _inspectorRect(): number {
|
|
1355
|
+
return this.shadowRoot?.querySelector('.inspector')?.getBoundingClientRect().width ?? MIN_INSPECTOR_WIDTH;
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
private _onResizeStart = (e: PointerEvent) => {
|
|
1359
|
+
e.preventDefault();
|
|
1360
|
+
const startX = e.clientX;
|
|
1361
|
+
const startWidth = this._inspectorWidth ?? this._inspectorRect();
|
|
1362
|
+
// The handle is on the inspector's left edge, so dragging left widens it.
|
|
1363
|
+
const move = (ev: PointerEvent) => {
|
|
1364
|
+
this._inspectorWidth = this._clampInspector(startWidth + startX - ev.clientX);
|
|
1365
|
+
};
|
|
1366
|
+
const stop = () => {
|
|
1367
|
+
window.removeEventListener('pointermove', move);
|
|
1368
|
+
window.removeEventListener('pointerup', stop);
|
|
1369
|
+
window.removeEventListener('pointercancel', stop);
|
|
1370
|
+
};
|
|
1371
|
+
window.addEventListener('pointermove', move);
|
|
1372
|
+
window.addEventListener('pointerup', stop);
|
|
1373
|
+
window.addEventListener('pointercancel', stop);
|
|
1374
|
+
};
|
|
1375
|
+
|
|
1376
|
+
private _onResizeKey = (e: KeyboardEvent) => {
|
|
1377
|
+
const step = e.key === 'ArrowLeft' ? RESIZE_STEP : e.key === 'ArrowRight' ? -RESIZE_STEP : 0;
|
|
1378
|
+
if (!step) return;
|
|
1379
|
+
e.preventDefault();
|
|
1380
|
+
this._inspectorWidth = this._clampInspector((this._inspectorWidth ?? this._inspectorRect()) + step);
|
|
1381
|
+
};
|
|
1382
|
+
|
|
1339
1383
|
private _renderInspector() {
|
|
1340
1384
|
const section = this._selectedSection();
|
|
1341
1385
|
if (!section) return html``;
|
|
@@ -1345,6 +1389,15 @@ export default class ZnPageBuilder extends ZincElement {
|
|
|
1345
1389
|
const typeLabel = type?.label ?? section.type;
|
|
1346
1390
|
return html`
|
|
1347
1391
|
<aside part="inspector" class="inspector">
|
|
1392
|
+
<div
|
|
1393
|
+
part="inspector-resize"
|
|
1394
|
+
class="inspector-resize"
|
|
1395
|
+
role="separator"
|
|
1396
|
+
aria-orientation="vertical"
|
|
1397
|
+
aria-label="Resize section settings"
|
|
1398
|
+
tabindex="0"
|
|
1399
|
+
@pointerdown="${this._onResizeStart}"
|
|
1400
|
+
@keydown="${this._onResizeKey}"></div>
|
|
1348
1401
|
<div part="inspector-header" class="inspector-head">
|
|
1349
1402
|
<span
|
|
1350
1403
|
class="inspector-head__icon"
|
|
@@ -1401,7 +1454,8 @@ export default class ZnPageBuilder extends ZincElement {
|
|
|
1401
1454
|
return html`
|
|
1402
1455
|
<div
|
|
1403
1456
|
part="base"
|
|
1404
|
-
class="builder ${this._selectedId ? 'builder--inspecting' : ''} ${this.paletteCollapsed ? 'builder--palette-collapsed' : ''} ${this.inspectorCollapsed ? 'builder--inspector-collapsed' : ''}"
|
|
1457
|
+
class="builder ${this._selectedId ? 'builder--inspecting' : ''} ${this.paletteCollapsed ? 'builder--palette-collapsed' : ''} ${this.inspectorCollapsed ? 'builder--inspector-collapsed' : ''} ${this._inspectorWide ? 'builder--inspector-wide' : ''}"
|
|
1458
|
+
style="${this._inspectorWidth === null || this.inspectorCollapsed ? nothing : `--inspector-col: ${this._inspectorWidth}px`}"
|
|
1405
1459
|
@dragend="${() => {
|
|
1406
1460
|
this._dragOverIndex = null;
|
|
1407
1461
|
this._slotDragOver = null;
|
|
@@ -39,6 +39,13 @@
|
|
|
39
39
|
|
|
40
40
|
// Side panels tuck away via the canvas-edge chevrons (flow-builder pattern).
|
|
41
41
|
// Their border would floor the width above zero, so it collapses too.
|
|
42
|
+
// A section whose settings are mostly a remarkd editor needs a writing
|
|
43
|
+
// measure, not a form column. Declared before the collapsed rules so tucking
|
|
44
|
+
// the panel away still wins.
|
|
45
|
+
&--inspector-wide {
|
|
46
|
+
--inspector-col: 520px;
|
|
47
|
+
}
|
|
48
|
+
|
|
42
49
|
&--palette-collapsed {
|
|
43
50
|
--palette-col: 0px;
|
|
44
51
|
|
|
@@ -254,6 +261,7 @@ zn-page-palette-item {
|
|
|
254
261
|
// Right column — anatomy shared with flow-builder's inspector (icon tile +
|
|
255
262
|
// title/type head over a scrolling body), so the two builders read alike.
|
|
256
263
|
.inspector {
|
|
264
|
+
position: relative;
|
|
257
265
|
display: flex;
|
|
258
266
|
flex-direction: column;
|
|
259
267
|
border-left: 1px solid rgb(var(--zn-border-color));
|
|
@@ -328,6 +336,10 @@ zn-page-palette-item {
|
|
|
328
336
|
flex: 1;
|
|
329
337
|
min-height: 0;
|
|
330
338
|
overflow-y: auto;
|
|
339
|
+
// Fields inside a narrow panel have to answer to its width, not the whole
|
|
340
|
+
// builder's — the host is the only container otherwise, and a form group
|
|
341
|
+
// would lay out as if it had the canvas to spread into.
|
|
342
|
+
container-type: inline-size;
|
|
331
343
|
// Extra bottom padding so the last field isn't flush against the scroll end.
|
|
332
344
|
padding: 18px 16px 24px;
|
|
333
345
|
gap: var(--pb-field-gap);
|
|
@@ -391,6 +403,35 @@ zn-page-palette-item {
|
|
|
391
403
|
}
|
|
392
404
|
}
|
|
393
405
|
|
|
406
|
+
// Straddles the inspector's left border so the grab area is wider than the 1px
|
|
407
|
+
// line it appears to be.
|
|
408
|
+
.inspector-resize {
|
|
409
|
+
position: absolute;
|
|
410
|
+
top: 0;
|
|
411
|
+
bottom: 0;
|
|
412
|
+
left: -3px;
|
|
413
|
+
z-index: 5;
|
|
414
|
+
width: 7px;
|
|
415
|
+
cursor: col-resize;
|
|
416
|
+
|
|
417
|
+
&::after {
|
|
418
|
+
content: '';
|
|
419
|
+
position: absolute;
|
|
420
|
+
inset: 0 3px;
|
|
421
|
+
background: transparent;
|
|
422
|
+
transition: background 0.15s ease;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
&:hover::after,
|
|
426
|
+
&:focus-visible::after {
|
|
427
|
+
background: rgb(var(--zn-color-primary));
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
&:focus-visible {
|
|
431
|
+
outline: none;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
394
435
|
.inspector-close {
|
|
395
436
|
display: flex;
|
|
396
437
|
align-items: center;
|