@zeyos/zx 4.0.0 → 4.1.0
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/CHANGELOG.md +44 -0
- package/DESIGN-SYSTEM.md +59 -3
- package/dist/types/components/app-icon/app-icon.d.ts +88 -0
- package/dist/types/components/filter/filter-model.d.ts +87 -0
- package/dist/types/components/filter/filter.d.ts +331 -0
- package/dist/types/components/select/select.d.ts +46 -4
- package/dist/types/components/table/table.d.ts +103 -0
- package/dist/types/components/tag-picker/tag-picker.d.ts +16 -0
- package/dist/types/core/dom.d.ts +1 -1
- package/dist/types/core/util.d.ts +9 -0
- package/dist/types/index.d.ts +4 -1
- package/dist/types/zeyos/icons.d.ts +19 -2
- package/dist/types/zeyos/index.d.ts +1 -1
- package/dist/types/zeyos/select.d.ts +2 -0
- package/dist/zx-zeyos.esm.js +702 -75
- package/dist/zx-zeyos.esm.min.js +1 -1
- package/dist/zx.css +415 -4
- package/dist/zx.esm.js +1568 -115
- package/dist/zx.esm.min.js +3 -3
- package/dist/zx.global.js +1568 -115
- package/dist/zx.global.min.js +3 -3
- package/dist/zx.min.css +1 -1
- package/docs/api.json +379 -0
- package/docs/llms.md +93 -16
- package/docs/llms.txt +11 -9
- package/package.json +1 -1
- package/src/components/app-icon/app-icon.css +105 -0
- package/src/components/app-icon/app-icon.js +134 -0
- package/src/components/filter/filter-model.js +226 -0
- package/src/components/filter/filter.css +147 -0
- package/src/components/filter/filter.js +554 -0
- package/src/components/grid/grid.css +1 -1
- package/src/components/grid/grid.js +4 -1
- package/src/components/message/message.css +36 -3
- package/src/components/select/select.css +17 -0
- package/src/components/select/select.js +105 -24
- package/src/components/table/table.css +85 -0
- package/src/components/table/table.js +418 -24
- package/src/components/tag-picker/tag-picker.css +19 -0
- package/src/components/tag-picker/tag-picker.js +42 -5
- package/src/core/dom.js +1 -1
- package/src/core/util.js +20 -0
- package/src/index.js +7 -1
- package/src/zeyos/icons.js +34 -21
- package/src/zeyos/index.js +1 -1
- package/src/zeyos/select.js +6 -5
- package/styles/tokens/semantic.css +9 -0
- package/styles/tokens/themes.css +2 -2
- package/styles/zx.css +2 -0
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
.zx-select__value-adornment {
|
|
21
21
|
display: inline-flex;
|
|
22
|
+
grid-column: 1;
|
|
22
23
|
align-items: center;
|
|
23
24
|
padding-inline-start: var(--zx-control-pad-x);
|
|
24
25
|
}
|
|
@@ -34,6 +35,7 @@
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
.zx-select__input {
|
|
38
|
+
grid-column: 2;
|
|
37
39
|
inline-size: 100%;
|
|
38
40
|
min-inline-size: 0;
|
|
39
41
|
min-block-size: calc(var(--zx-control-height) - 2px) !important;
|
|
@@ -60,6 +62,11 @@
|
|
|
60
62
|
padding: 0 !important;
|
|
61
63
|
}
|
|
62
64
|
|
|
65
|
+
.zx-select__clear { grid-column: 3; }
|
|
66
|
+
.zx-select__loading { grid-column: 4; justify-self: center; }
|
|
67
|
+
.zx-select__toggle { grid-column: 5; align-self: stretch; }
|
|
68
|
+
.zx-select__toggle > .zx-icon { display: block; }
|
|
69
|
+
|
|
63
70
|
.zx-select__clear:hover,
|
|
64
71
|
.zx-select__toggle:hover {
|
|
65
72
|
color: var(--zx-color-text);
|
|
@@ -198,6 +205,16 @@
|
|
|
198
205
|
gap: var(--zx-space-2);
|
|
199
206
|
}
|
|
200
207
|
|
|
208
|
+
.zx-select__entity-glyph {
|
|
209
|
+
display: inline-grid;
|
|
210
|
+
place-items: center;
|
|
211
|
+
inline-size: 20px;
|
|
212
|
+
block-size: 20px;
|
|
213
|
+
border-radius: var(--zx-radius-sm);
|
|
214
|
+
background: var(--zx-select-entity-color, var(--zx-color-accent-subtle));
|
|
215
|
+
color: var(--zx-color-text-invert);
|
|
216
|
+
}
|
|
217
|
+
|
|
201
218
|
.zx-select__status-copy,
|
|
202
219
|
.zx-select__action-copy {
|
|
203
220
|
display: grid;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Component } from '../../core/component.js';
|
|
2
|
-
import { h } from '../../core/dom.js';
|
|
2
|
+
import { h, restoreTarget, snapshotTarget } from '../../core/dom.js';
|
|
3
3
|
import { icon } from '../../core/icons.js';
|
|
4
4
|
import { typeahead } from '../../core/keyboard.js';
|
|
5
5
|
import { position } from '../../core/position.js';
|
|
6
|
-
import { uid } from '../../core/util.js';
|
|
6
|
+
import { isCssColor, uid } from '../../core/util.js';
|
|
7
7
|
import { matchItems } from './filter.js';
|
|
8
8
|
|
|
9
9
|
/** @typedef {string|number|boolean|symbol|bigint|null|undefined} Primitive */
|
|
@@ -15,6 +15,7 @@ import { matchItems } from './filter.js';
|
|
|
15
15
|
* @typedef {Object} SelectOptions
|
|
16
16
|
* @property {SelectItem[]} [items=[]] Available values.
|
|
17
17
|
* @property {SelectItem[]} [fixedItems=[]] Choices pinned above the list, kept through filtering and async loads.
|
|
18
|
+
* @property {string|null} [fixedLabel=null] Optional heading above pinned choices.
|
|
18
19
|
* @property {SelectValueReader} [valueKey='ID'] Item ID property or reader.
|
|
19
20
|
* @property {SelectLabelReader} [labelKey='name'] Item label property or reader.
|
|
20
21
|
* @property {((item: SelectItem) => Node|string)|null} [renderItem=null] Option renderer.
|
|
@@ -41,6 +42,16 @@ import { matchItems } from './filter.js';
|
|
|
41
42
|
* @property {(event: CustomEvent<SelectLoadedDetail>) => void} [onloaded] Async-loaded listener.
|
|
42
43
|
* @property {(event: CustomEvent<SelectActionDetail>) => void} [onaction] Preventable command-row listener.
|
|
43
44
|
*/
|
|
45
|
+
/**
|
|
46
|
+
* @typedef {Object} EntitySelectOptions
|
|
47
|
+
* @property {SelectItem[]} [recent=[]] Choices pinned above ordinary results.
|
|
48
|
+
* @property {string} [recentLabel='Recent'] Heading above recent choices.
|
|
49
|
+
* @property {boolean|SelectAction} [create=false] Optional create command at the bottom.
|
|
50
|
+
* @property {string|((item: SelectItem)=>unknown)} [iconKey='icon'] Item icon reader.
|
|
51
|
+
* @property {string|((item: SelectItem)=>unknown)} [colorKey='color'] Optional icon colour reader.
|
|
52
|
+
* @property {string|((item: SelectItem)=>unknown)} [subtitleKey='description'] Secondary-text reader.
|
|
53
|
+
* @property {((item: SelectItem, context:{selected:boolean})=>Node|string|null)|null} [renderIcon=null] Entity icon renderer.
|
|
54
|
+
*/
|
|
44
55
|
/** @typedef {{value: unknown, item: SelectItem|null}} SelectChangeDetail */
|
|
45
56
|
/** @typedef {{query: string}} SelectQueryDetail */
|
|
46
57
|
/** @typedef {{items: SelectItem[]}} SelectLoadedDetail */
|
|
@@ -86,6 +97,7 @@ export class Select extends Component {
|
|
|
86
97
|
static defaults = {
|
|
87
98
|
items: [],
|
|
88
99
|
fixedItems: [],
|
|
100
|
+
fixedLabel: null,
|
|
89
101
|
valueKey: 'ID',
|
|
90
102
|
labelKey: 'name',
|
|
91
103
|
renderItem: null,
|
|
@@ -111,15 +123,12 @@ export class Select extends Component {
|
|
|
111
123
|
render() {
|
|
112
124
|
// Instance state initialized here because render() runs inside the base
|
|
113
125
|
// constructor, before class-field initializers would run (and clobber it).
|
|
114
|
-
this._items = []; this._visibleItems = []; this._fixedItems = []; this._visibleFixed = []; this._actions = []; this._selected = null; this._optionEntries = []; this._activeIndex = -1; this._open = false; this._disabled = false; this._loading = false; this._requestSequence = 0; this._queryTimer = null; this._position = null; this._createdRoot = false; this._root = null; this.
|
|
126
|
+
this._items = []; this._visibleItems = []; this._fixedItems = []; this._visibleFixed = []; this._actions = []; this._selected = null; this._optionEntries = []; this._activeIndex = -1; this._open = false; this._disabled = false; this._loading = false; this._requestSequence = 0; this._queryTimer = null; this._position = null; this._createdRoot = false; this._root = null; this._snapshot = null;
|
|
115
127
|
this._createdRoot = this.el === null;
|
|
116
128
|
const root = /** @type {HTMLElement} */ (this.el ?? h('div'));
|
|
117
129
|
this.el = root;
|
|
118
130
|
this._root = root;
|
|
119
|
-
|
|
120
|
-
this._rememberAttribute(root, 'data-state');
|
|
121
|
-
this._rememberAttribute(root, 'data-loading');
|
|
122
|
-
this._rememberAttribute(root, 'aria-disabled');
|
|
131
|
+
this._snapshot = this._createdRoot ? null : snapshotTarget(root);
|
|
123
132
|
|
|
124
133
|
const listId = uid('zx-select-list');
|
|
125
134
|
const input = h('input', {
|
|
@@ -423,6 +432,54 @@ export class Select extends Component {
|
|
|
423
432
|
return select;
|
|
424
433
|
}
|
|
425
434
|
|
|
435
|
+
/**
|
|
436
|
+
* Creates a rich entity picker with optional Recent choices and a create command.
|
|
437
|
+
* @param {Element|string|null} target Component target.
|
|
438
|
+
* @param {SelectOptions & EntitySelectOptions} [options={}] Entity-preset options.
|
|
439
|
+
* @returns {Select}
|
|
440
|
+
*/
|
|
441
|
+
static entity(target, options = {}) {
|
|
442
|
+
const {
|
|
443
|
+
recent = [], recentLabel = 'Recent', create = false, iconKey = 'icon', colorKey = 'color',
|
|
444
|
+
subtitleKey = 'description', renderIcon = null,
|
|
445
|
+
fixedItems = [], actions = [], renderItem = null, renderValueAdornment = null,
|
|
446
|
+
...rest
|
|
447
|
+
} = options;
|
|
448
|
+
const visual = (item, selected = false) => {
|
|
449
|
+
if (typeof renderIcon === 'function') return renderIcon(item, { selected });
|
|
450
|
+
const value = readSelectItem(item, iconKey);
|
|
451
|
+
if (value && typeof value === 'object' && typeof value.nodeType === 'number') return value.cloneNode(true);
|
|
452
|
+
if (typeof value !== 'string' || !value) return null;
|
|
453
|
+
const color = readSelectItem(item, colorKey);
|
|
454
|
+
return h('span', {
|
|
455
|
+
class: 'zx-select__entity-glyph',
|
|
456
|
+
style: isCssColor(color) ? { '--zx-select-entity-color': String(color) } : null,
|
|
457
|
+
ariaHidden: 'true'
|
|
458
|
+
}, icon(value, { size: 14 }));
|
|
459
|
+
};
|
|
460
|
+
const createAction = create ? normalizeEntityCreateAction(create) : null;
|
|
461
|
+
const select = new Select(target, {
|
|
462
|
+
...rest,
|
|
463
|
+
fixedItems: [...(Array.isArray(recent) ? recent : []), ...(Array.isArray(fixedItems) ? fixedItems : [])],
|
|
464
|
+
fixedLabel: Array.isArray(recent) && recent.length ? recentLabel : rest.fixedLabel ?? null,
|
|
465
|
+
actions: [...(Array.isArray(actions) ? actions : []), ...(createAction ? [createAction] : [])],
|
|
466
|
+
renderItem: renderItem ?? ((item) => {
|
|
467
|
+
const decoration = visual(item, false);
|
|
468
|
+
const subtitle = readSelectItem(item, subtitleKey);
|
|
469
|
+
const copy = h('span', { class: 'zx-select__entity-copy' },
|
|
470
|
+
h('span', { class: 'zx-select__entity-label' }, String(readSelectItem(item, rest.labelKey ?? 'name') ?? '')),
|
|
471
|
+
subtitle == null || subtitle === ''
|
|
472
|
+
? null : h('span', { class: 'zx-select__entity-subtitle' }, String(subtitle)));
|
|
473
|
+
return h('span', { class: 'zx-select__entity' },
|
|
474
|
+
decoration ? h('span', { class: 'zx-select__entity-icon', ariaHidden: 'true' }, decoration) : null,
|
|
475
|
+
copy);
|
|
476
|
+
}),
|
|
477
|
+
renderValueAdornment: renderValueAdornment ?? ((item) => visual(item, true))
|
|
478
|
+
});
|
|
479
|
+
select.el.dataset.preset = 'entity';
|
|
480
|
+
return select;
|
|
481
|
+
}
|
|
482
|
+
|
|
426
483
|
/**
|
|
427
484
|
* Creates the record-permission picker: the fixed Private and Public choices above the groups a
|
|
428
485
|
* record can be shared with. The value is the tri-state ZeyOS stores — `false` for private,
|
|
@@ -467,13 +524,7 @@ export class Select extends Component {
|
|
|
467
524
|
this._position?.destroy();
|
|
468
525
|
this._position = null;
|
|
469
526
|
const root = /** @type {HTMLElement} */ (this.el);
|
|
470
|
-
if (!this._createdRoot && root)
|
|
471
|
-
root.replaceChildren(...this._originalChildren);
|
|
472
|
-
for (const [name, value] of this._originalAttributes) {
|
|
473
|
-
if (value === null) root.removeAttribute(name);
|
|
474
|
-
else root.setAttribute(name, value);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
527
|
+
if (!this._createdRoot && root) restoreTarget(root, this._snapshot);
|
|
477
528
|
super.destroy();
|
|
478
529
|
}
|
|
479
530
|
|
|
@@ -606,17 +657,22 @@ export class Select extends Component {
|
|
|
606
657
|
list.replaceChildren();
|
|
607
658
|
this._optionEntries = [];
|
|
608
659
|
let lastGroup = Symbol('initial-group');
|
|
660
|
+
const fixed = this._uniqueItems(this._visibleFixed);
|
|
661
|
+
const items = this._uniqueItems(this._visibleItems, fixed);
|
|
609
662
|
|
|
610
663
|
if (this.options.clearable) {
|
|
611
664
|
this._appendOption(null, true, this.options.noneLabel
|
|
612
665
|
?? this._message('select.none', 'No selection'));
|
|
613
666
|
}
|
|
614
|
-
|
|
667
|
+
if (fixed.length > 0 && this.options.fixedLabel) {
|
|
668
|
+
list.append(h('div', { class: 'zx-select__group', role: 'presentation' }, String(this.options.fixedLabel)));
|
|
669
|
+
}
|
|
670
|
+
for (const item of fixed) this._appendOption(item, false);
|
|
615
671
|
// A group heading already divides the two sections, and a rule right above one reads as a slip.
|
|
616
|
-
if (
|
|
672
|
+
if (fixed.length > 0 && items.length > 0 && !this.options.groupKey) {
|
|
617
673
|
list.append(h('div', { class: 'zx-select__separator', role: 'presentation' }));
|
|
618
674
|
}
|
|
619
|
-
for (const item of
|
|
675
|
+
for (const item of items) {
|
|
620
676
|
if (this.options.groupKey) {
|
|
621
677
|
const group = this._read(item, this.options.groupKey);
|
|
622
678
|
if (!Object.is(group, lastGroup)) {
|
|
@@ -630,7 +686,7 @@ export class Select extends Component {
|
|
|
630
686
|
this._appendOption(item, false);
|
|
631
687
|
}
|
|
632
688
|
if (this._actions.length > 0) {
|
|
633
|
-
if (
|
|
689
|
+
if (fixed.length > 0 || items.length > 0 || this.options.clearable) {
|
|
634
690
|
list.append(h('div', { class: 'zx-select__separator', role: 'presentation' }));
|
|
635
691
|
}
|
|
636
692
|
let actionGroup = Symbol('initial-action-group');
|
|
@@ -645,7 +701,7 @@ export class Select extends Component {
|
|
|
645
701
|
this._appendAction(action);
|
|
646
702
|
}
|
|
647
703
|
}
|
|
648
|
-
if (
|
|
704
|
+
if (items.length === 0 && fixed.length === 0
|
|
649
705
|
&& this._actions.length === 0 && !this._loading) {
|
|
650
706
|
list.append(h('div', {
|
|
651
707
|
class: 'zx-select__empty',
|
|
@@ -851,6 +907,17 @@ export class Select extends Component {
|
|
|
851
907
|
return matchItems(this._fixedItems, query, this._searchKeys());
|
|
852
908
|
}
|
|
853
909
|
|
|
910
|
+
/** De-duplicates choices by public value while preserving caller order. @param {SelectItem[]} items @param {SelectItem[]} [excluded=[]] @returns {SelectItem[]} */
|
|
911
|
+
_uniqueItems(items, excluded = []) {
|
|
912
|
+
const values = excluded.map((item) => this._itemValue(item));
|
|
913
|
+
return items.filter((item) => {
|
|
914
|
+
const value = this._itemValue(item);
|
|
915
|
+
if (values.some((candidate) => Object.is(candidate, value))) return false;
|
|
916
|
+
values.push(value);
|
|
917
|
+
return true;
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
|
|
854
921
|
/** @returns {number} */
|
|
855
922
|
_selectedEntryIndex() {
|
|
856
923
|
if (this._selected === null) return this.options.clearable ? 0 : -1;
|
|
@@ -864,11 +931,6 @@ export class Select extends Component {
|
|
|
864
931
|
return itemIndex + (this.options.clearable ? 1 : 0);
|
|
865
932
|
}
|
|
866
933
|
|
|
867
|
-
/** @param {string} name @returns {void} */
|
|
868
|
-
_rememberAttribute(element, name) {
|
|
869
|
-
this._originalAttributes.set(name, element.getAttribute(name));
|
|
870
|
-
}
|
|
871
|
-
|
|
872
934
|
/** @param {string} key @param {string} fallback @returns {string} */
|
|
873
935
|
_message(key, fallback) {
|
|
874
936
|
const message = this.msg(key);
|
|
@@ -876,6 +938,25 @@ export class Select extends Component {
|
|
|
876
938
|
}
|
|
877
939
|
}
|
|
878
940
|
|
|
941
|
+
/** @param {SelectItem} item @param {unknown} reader @returns {unknown} */
|
|
942
|
+
function readSelectItem(item, reader) {
|
|
943
|
+
if (typeof reader === 'function') return reader(item);
|
|
944
|
+
if (item !== null && typeof item === 'object' && typeof reader === 'string') return item[reader];
|
|
945
|
+
return null;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
/** @param {boolean|SelectAction} value @returns {SelectAction} */
|
|
949
|
+
function normalizeEntityCreateAction(value) {
|
|
950
|
+
const descriptor = value === true ? {} : value;
|
|
951
|
+
return {
|
|
952
|
+
id: descriptor.id ?? 'create', label: descriptor.label ?? 'Create new…',
|
|
953
|
+
description: descriptor.description, group: descriptor.group ?? 'New',
|
|
954
|
+
icon: descriptor.icon ?? 'plus', invoke: descriptor.invoke
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
/** @param {unknown} value @returns {boolean} */
|
|
959
|
+
|
|
879
960
|
/** @param {unknown} rendered @returns {Node|string} */
|
|
880
961
|
function normalizeRenderedContent(rendered) {
|
|
881
962
|
return rendered && typeof rendered === 'object' && 'nodeType' in rendered
|
|
@@ -2,6 +2,87 @@
|
|
|
2
2
|
min-inline-size: 0;
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
+
.zx-table__column-controls {
|
|
6
|
+
position: relative;
|
|
7
|
+
inline-size: max-content;
|
|
8
|
+
margin: 0 0 var(--zx-space-2) auto;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.zx-table__reorder-status {
|
|
12
|
+
position: absolute;
|
|
13
|
+
inline-size: 1px;
|
|
14
|
+
block-size: 1px;
|
|
15
|
+
overflow: hidden;
|
|
16
|
+
clip-path: inset(50%);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.zx-table__column-controls > summary {
|
|
20
|
+
display: inline-flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
gap: var(--zx-space-2);
|
|
23
|
+
list-style: none;
|
|
24
|
+
cursor: pointer;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.zx-table__column-controls > summary::-webkit-details-marker { display: none; }
|
|
28
|
+
|
|
29
|
+
.zx-table__column-list {
|
|
30
|
+
position: absolute;
|
|
31
|
+
z-index: 4;
|
|
32
|
+
inset-block-start: calc(100% + var(--zx-space-1));
|
|
33
|
+
inset-inline-end: 0;
|
|
34
|
+
display: grid;
|
|
35
|
+
min-inline-size: 190px;
|
|
36
|
+
border: 1px solid var(--zx-color-border-strong);
|
|
37
|
+
border-radius: var(--zx-radius-md);
|
|
38
|
+
background: var(--zx-color-bg-raised);
|
|
39
|
+
box-shadow: var(--zx-overlay-shadow);
|
|
40
|
+
padding: var(--zx-space-2);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.zx-table__column-option {
|
|
44
|
+
display: flex;
|
|
45
|
+
align-items: center;
|
|
46
|
+
gap: var(--zx-space-2);
|
|
47
|
+
min-block-size: var(--zx-control-height);
|
|
48
|
+
border-radius: var(--zx-radius-sm);
|
|
49
|
+
padding-inline: var(--zx-space-2);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.zx-table__column-option:hover { background: var(--zx-color-bg-hover); }
|
|
53
|
+
|
|
54
|
+
.zx-table__reorder-column,
|
|
55
|
+
.zx-table__reorder-header,
|
|
56
|
+
.zx-table__reorder-cell {
|
|
57
|
+
inline-size: var(--zx-control-height);
|
|
58
|
+
text-align: center;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.zx-table__row-handle {
|
|
62
|
+
display: inline-grid;
|
|
63
|
+
place-items: center;
|
|
64
|
+
inline-size: 26px;
|
|
65
|
+
block-size: 26px;
|
|
66
|
+
min-block-size: 0;
|
|
67
|
+
border: 0;
|
|
68
|
+
border-radius: var(--zx-radius-sm);
|
|
69
|
+
background: transparent;
|
|
70
|
+
padding: 0;
|
|
71
|
+
color: var(--zx-color-text-muted);
|
|
72
|
+
cursor: grab;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.zx-table__row-handle:hover,
|
|
76
|
+
.zx-table__row-handle[aria-pressed="true"] {
|
|
77
|
+
background: var(--zx-color-bg-hover);
|
|
78
|
+
color: var(--zx-color-text);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.zx-table__row-handle:active { cursor: grabbing; }
|
|
82
|
+
.zx-table__body tr[data-dragging] { opacity: .55; }
|
|
83
|
+
.zx-table__body tr[data-drop="before"] { box-shadow: inset 0 2px 0 var(--zx-color-accent); }
|
|
84
|
+
.zx-table__body tr[data-drop="after"] { box-shadow: inset 0 -2px 0 var(--zx-color-accent); }
|
|
85
|
+
|
|
5
86
|
.zx-table__scroll {
|
|
6
87
|
position: relative;
|
|
7
88
|
max-inline-size: 100%;
|
|
@@ -379,6 +460,10 @@
|
|
|
379
460
|
justify-content: flex-start;
|
|
380
461
|
}
|
|
381
462
|
|
|
463
|
+
.zx-table[data-stacked] .zx-table__reorder-cell {
|
|
464
|
+
justify-content: flex-start;
|
|
465
|
+
}
|
|
466
|
+
|
|
382
467
|
|
|
383
468
|
.zx-table[data-stacked] .zx-table__empty-row {
|
|
384
469
|
display: block;
|