@zeyos/zx 4.4.0 → 5.2.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 +447 -0
- package/README.md +44 -11
- package/dist/types/components/account-menu/account-menu.d.ts +8 -0
- package/dist/types/components/activity-list/activity-list.d.ts +31 -1
- package/dist/types/components/app-icon/app-icon.d.ts +14 -2
- package/dist/types/components/app-sidebar/app-sidebar.d.ts +293 -17
- package/dist/types/components/avatar/avatar.d.ts +46 -7
- package/dist/types/components/badge/badge.d.ts +21 -1
- package/dist/types/components/button/button.d.ts +15 -0
- package/dist/types/components/calendar/calendar.d.ts +67 -5
- package/dist/types/components/card-view/card-view.d.ts +7 -4
- package/dist/types/components/card-view/record-card.d.ts +11 -0
- package/dist/types/components/chart/chart.d.ts +10 -0
- package/dist/types/components/checklist/checklist.d.ts +9 -0
- package/dist/types/components/code-editor/code-editor.d.ts +6 -17
- package/dist/types/components/context-menu/context-menu.d.ts +6 -2
- package/dist/types/components/data-filter/data-filter.d.ts +4 -4
- package/dist/types/components/datebox/date-range-box.d.ts +5 -1
- package/dist/types/components/datebox/datebox.d.ts +7 -2
- package/dist/types/components/dialog/dialog.d.ts +46 -6
- package/dist/types/components/dropdown/dropdown.d.ts +24 -9
- package/dist/types/components/entity-ref/entity-ref.d.ts +2 -2
- package/dist/types/components/field/field.d.ts +54 -2
- package/dist/types/components/fieldset/external-adapter.d.ts +83 -0
- package/dist/types/components/fieldset/fieldset.d.ts +26 -1
- package/dist/types/components/file-item/file-item.d.ts +34 -6
- package/dist/types/components/file-list/file-list.d.ts +35 -3
- package/dist/types/components/filter/filter.d.ts +127 -3
- package/dist/types/components/filter-panel/filter-panel.d.ts +36 -7
- package/dist/types/components/form/form.d.ts +12 -1
- package/dist/types/components/kanban-view/kanban-card.d.ts +8 -0
- package/dist/types/components/launcher/launcher.d.ts +268 -15
- package/dist/types/components/list-toolbar/list-toolbar.d.ts +16 -7
- package/dist/types/components/menu-button/menu-button.d.ts +39 -5
- package/dist/types/components/message/message.d.ts +132 -17
- package/dist/types/components/modal/modal.d.ts +43 -2
- package/dist/types/components/module-bar/module-bar.d.ts +395 -0
- package/dist/types/components/pagination/pagination.d.ts +17 -3
- package/dist/types/components/select/color.d.ts +12 -0
- package/dist/types/components/select/glyphs.d.ts +124 -0
- package/dist/types/components/select/select.d.ts +17 -3
- package/dist/types/components/sheet/sheet.d.ts +15 -0
- package/dist/types/components/stat-tile/stat-tile.d.ts +16 -5
- package/dist/types/components/tabbox/tabbox.d.ts +9 -0
- package/dist/types/components/table/table.d.ts +311 -18
- package/dist/types/components/tag-picker/tag-picker.d.ts +21 -4
- package/dist/types/components/tree/tree.d.ts +13 -0
- package/dist/types/components/view/record-view.d.ts +59 -2
- package/dist/types/components/view-settings/view-settings.d.ts +879 -0
- package/dist/types/components/workspace-switcher/workspace-switcher.d.ts +327 -0
- package/dist/types/core/breakpoint.d.ts +1 -1
- package/dist/types/core/component.d.ts +12 -2
- package/dist/types/core/i18n.d.ts +27 -3
- package/dist/types/core/icons.d.ts +23 -25
- package/dist/types/core/keyboard.d.ts +98 -1
- package/dist/types/core/messages.d.ts +382 -0
- package/dist/types/core/motion.d.ts +59 -0
- package/dist/types/core/overlay-host.d.ts +42 -1
- package/dist/types/core/overlay-stack.d.ts +260 -0
- package/dist/types/index.d.ts +10 -5
- package/dist/types/internal/app-rail.d.ts +38 -0
- package/dist/types/internal/menu-items.d.ts +71 -3
- package/dist/types/zeyos/connect.d.ts +6 -0
- package/dist/types/zeyos/form.d.ts +50 -9
- package/dist/types/zeyos/index.d.ts +2 -1
- package/dist/types/zeyos/launcher.d.ts +9 -0
- package/dist/types/zeyos/module-bar.d.ts +176 -0
- package/dist/types/zeyos/query.d.ts +110 -5
- package/dist/types/zeyos/schema.d.ts +24 -1
- package/dist/types/zeyos/table.d.ts +345 -22
- package/dist/types/zeyos/view.d.ts +26 -2
- package/dist/zx-zeyos.esm.js +6178 -1008
- package/dist/zx-zeyos.esm.min.js +53 -5
- package/dist/zx.css +2861 -827
- package/dist/zx.esm.js +8909 -1480
- package/dist/zx.esm.min.js +55 -7
- package/dist/zx.global.js +8911 -1482
- package/dist/zx.global.min.js +55 -7
- package/dist/zx.min.css +1 -1
- package/docs/api.json +1079 -117
- package/docs/llms.md +956 -154
- package/docs/llms.txt +9 -5
- package/package.json +1 -1
- package/src/components/account-menu/account-menu.css +35 -10
- package/src/components/account-menu/account-menu.js +12 -0
- package/src/components/activity-item/activity-item.css +1 -1
- package/src/components/activity-item/activity-item.js +3 -0
- package/src/components/activity-list/activity-list.css +38 -3
- package/src/components/activity-list/activity-list.js +61 -1
- package/src/components/app-icon/app-icon.css +14 -3
- package/src/components/app-icon/app-icon.js +11 -1
- package/src/components/app-rail/app-rail.css +59 -79
- package/src/components/app-sidebar/app-sidebar.css +304 -168
- package/src/components/app-sidebar/app-sidebar.js +667 -46
- package/src/components/aurora/aurora.css +5 -3
- package/src/components/avatar/avatar.css +32 -7
- package/src/components/avatar/avatar.js +72 -8
- package/src/components/badge/badge.css +54 -2
- package/src/components/badge/badge.js +29 -2
- package/src/components/breadcrumb/breadcrumb.css +1 -1
- package/src/components/button/button.css +67 -9
- package/src/components/button/button.js +38 -0
- package/src/components/calendar/calendar.css +47 -47
- package/src/components/calendar/calendar.js +26 -52
- package/src/components/card/card.css +4 -4
- package/src/components/card-view/card-view.css +14 -12
- package/src/components/card-view/card-view.js +13 -9
- package/src/components/card-view/record-card.js +14 -3
- package/src/components/chart/chart.css +4 -1
- package/src/components/chart/chart.js +12 -0
- package/src/components/check-button/check-button.css +10 -2
- package/src/components/checklist/checklist.css +9 -2
- package/src/components/checklist/checklist.js +11 -5
- package/src/components/checklist/field-adapter.js +3 -1
- package/src/components/code-editor/code-editor.css +7 -6
- package/src/components/code-editor/code-editor.js +19 -1
- package/src/components/code-editor/field-adapter.js +9 -2
- package/src/components/context-menu/context-menu.css +9 -4
- package/src/components/context-menu/context-menu.js +8 -2
- package/src/components/copy/copy-button.css +6 -0
- package/src/components/copy/copy-input.css +9 -4
- package/src/components/data-filter/data-filter.css +5 -4
- package/src/components/data-filter/data-filter.js +2 -2
- package/src/components/date-picker/date-picker.css +6 -6
- package/src/components/date-picker/date-range-picker.css +3 -3
- package/src/components/date-picker/time-picker.css +3 -3
- package/src/components/datebox/date-range-box.css +79 -2
- package/src/components/datebox/date-range-box.js +13 -2
- package/src/components/datebox/datebox.css +79 -2
- package/src/components/datebox/datebox.js +13 -2
- package/src/components/dialog/dialog.css +26 -0
- package/src/components/dialog/dialog.js +99 -17
- package/src/components/dock/dock.css +5 -4
- package/src/components/dropdown/dropdown.css +1 -1
- package/src/components/dropdown/dropdown.js +159 -72
- package/src/components/empty-state/empty-state.css +2 -2
- package/src/components/entity-ref/entity-ref.css +1 -1
- package/src/components/entity-ref/entity-ref.js +1 -1
- package/src/components/field/field.css +28 -9
- package/src/components/field/field.js +101 -29
- package/src/components/field-upload/field-upload.css +1 -1
- package/src/components/fieldset/external-adapter.js +363 -0
- package/src/components/fieldset/fieldset.css +5 -3
- package/src/components/fieldset/fieldset.js +38 -64
- package/src/components/file-item/file-item.js +144 -10
- package/src/components/file-list/file-list.js +144 -21
- package/src/components/filter/filter.css +86 -2
- package/src/components/filter/filter.js +307 -11
- package/src/components/filter-panel/filter-panel.css +1 -1
- package/src/components/filter-panel/filter-panel.js +149 -32
- package/src/components/finder/finder.css +16 -14
- package/src/components/form/form.css +5 -4
- package/src/components/form/form.js +11 -2
- package/src/components/grid/grid.css +1 -1
- package/src/components/groupbox/groupbox.css +1 -1
- package/src/components/kanban-view/kanban-card.js +11 -3
- package/src/components/kanban-view/kanban-view.css +42 -18
- package/src/components/kanban-view/kanban-view.js +9 -6
- package/src/components/launcher/launcher.css +108 -26
- package/src/components/launcher/launcher.js +530 -42
- package/src/components/list-toolbar/list-toolbar.css +13 -8
- package/src/components/list-toolbar/list-toolbar.js +40 -14
- package/src/components/master-panel/master-panel.css +2 -0
- package/src/components/master-panel/master-panel.js +0 -1
- package/src/components/menu-button/menu-button.css +72 -4
- package/src/components/menu-button/menu-button.js +160 -18
- package/src/components/message/message.css +33 -3
- package/src/components/message/message.js +264 -22
- package/src/components/modal/modal.css +1 -1
- package/src/components/modal/modal.js +83 -15
- package/src/components/module-bar/module-bar.css +486 -0
- package/src/components/module-bar/module-bar.js +1074 -0
- package/src/components/multi-value-editor/multi-value-editor.css +1 -1
- package/src/components/navigation-bar/navigation-bar.css +18 -9
- package/src/components/number-field/field-adapter.js +3 -1
- package/src/components/number-field/number-field.css +70 -0
- package/src/components/number-field/number-field.js +2 -0
- package/src/components/pagination/pagination.css +13 -11
- package/src/components/pagination/pagination.js +20 -4
- package/src/components/panel/panel.css +4 -3
- package/src/components/questionnaire/questionnaire.css +4 -4
- package/src/components/rating/field-adapter.js +2 -1
- package/src/components/rating/rating.css +8 -1
- package/src/components/search/search.css +4 -1
- package/src/components/select/color.js +22 -0
- package/src/components/select/field-adapter.js +2 -0
- package/src/components/select/glyphs.js +165 -0
- package/src/components/select/select.css +138 -45
- package/src/components/select/select.js +92 -47
- package/src/components/sheet/sheet.css +12 -9
- package/src/components/sheet/sheet.js +74 -32
- package/src/components/slider/field-adapter.js +6 -1
- package/src/components/slider/slider.css +18 -4
- package/src/components/slider/slider.js +1 -1
- package/src/components/sort-control/sort-control.css +4 -1
- package/src/components/split-view/split-view.css +1 -1
- package/src/components/stat-tile/stat-tile.css +42 -47
- package/src/components/stat-tile/stat-tile.js +17 -6
- package/src/components/stepper/stepper.css +1 -1
- package/src/components/tabbox/tabbox.css +41 -32
- package/src/components/tabbox/tabbox.js +5 -1
- package/src/components/table/table.css +187 -37
- package/src/components/table/table.js +718 -73
- package/src/components/tag-picker/field-adapter.js +2 -1
- package/src/components/tag-picker/tag-picker.css +83 -5
- package/src/components/tag-picker/tag-picker.js +25 -8
- package/src/components/timebox/timebox.css +22 -2
- package/src/components/toggle/toggle.css +12 -1
- package/src/components/toolbar/toolbar.js +2 -2
- package/src/components/tooltip/tooltip.css +4 -0
- package/src/components/tooltip/tooltip.js +44 -19
- package/src/components/tree/tree.css +26 -17
- package/src/components/tree/tree.js +31 -0
- package/src/components/value-list/value-list.css +3 -3
- package/src/components/view/record-view.css +1 -1
- package/src/components/view/record-view.js +178 -18
- package/src/components/view-settings/view-settings.css +285 -0
- package/src/components/view-settings/view-settings.js +1830 -0
- package/src/components/workspace-switcher/workspace-switcher.css +188 -0
- package/src/components/workspace-switcher/workspace-switcher.js +463 -0
- package/src/core/breakpoint.js +1 -1
- package/src/core/component.js +88 -17
- package/src/core/fontawesome.js +5 -1
- package/src/core/i18n.js +47 -4
- package/src/core/icons.js +204 -61
- package/src/core/keyboard.js +206 -11
- package/src/core/messages.js +427 -0
- package/src/core/motion.js +147 -0
- package/src/core/overlay-host.js +77 -3
- package/src/core/overlay-stack.js +487 -0
- package/src/core/position.js +22 -3
- package/src/index.js +10 -5
- package/src/internal/app-rail.js +135 -55
- package/src/internal/menu-items.js +61 -3
- package/src/zeyos/connect.js +6 -2
- package/src/zeyos/form.js +69 -27
- package/src/zeyos/index.js +4 -1
- package/src/zeyos/launcher.js +8 -3
- package/src/zeyos/module-bar.js +181 -0
- package/src/zeyos/query.js +197 -13
- package/src/zeyos/schema.js +144 -27
- package/src/zeyos/table.js +287 -84
- package/src/zeyos/view.js +49 -93
- package/styles/base.css +72 -1
- package/styles/icons.css +11 -1
- package/styles/print.css +1 -1
- package/styles/tokens/dark.css +117 -37
- package/styles/tokens/global.css +121 -27
- package/styles/tokens/semantic.css +140 -43
- package/styles/tokens/themes.css +7 -6
- package/styles/zx.css +3 -1
- package/styles/tokens/density.css +0 -9
|
@@ -29,7 +29,8 @@ export function registerTagPickerFieldAdapter() {
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
focus: () => picker.focus(),
|
|
32
|
-
setDisabled: (value) => (value ? picker.disable() : picker.enable())
|
|
32
|
+
setDisabled: (value) => (value ? picker.disable() : picker.enable()),
|
|
33
|
+
setReadonly: (value) => { picker.setReadonly(value); }
|
|
33
34
|
};
|
|
34
35
|
});
|
|
35
36
|
}
|
|
@@ -32,6 +32,12 @@
|
|
|
32
32
|
cursor: default;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/* Read-only, the picker is its tags: nothing to type into and no list to open, so no input and no
|
|
36
|
+
chevron — and a full row of tags does not wrap them onto an empty second line. */
|
|
37
|
+
.zx-tag-picker[data-readonly] :is(.zx-tag-picker__input, .zx-tag-picker__toggle) {
|
|
38
|
+
display: none;
|
|
39
|
+
}
|
|
40
|
+
|
|
35
41
|
.zx-tag-picker__tags {
|
|
36
42
|
display: contents;
|
|
37
43
|
}
|
|
@@ -65,6 +71,38 @@
|
|
|
65
71
|
color: var(--zx-tag-color, var(--zx-color-accent));
|
|
66
72
|
}
|
|
67
73
|
|
|
74
|
+
/* A categorical tone: the tag takes the Badge tone palette — the tone's tint as fill, its ink as
|
|
75
|
+
text, no border — and an icon tile the same pair, so a label keeps one colour everywhere. */
|
|
76
|
+
.zx-tag-picker__tag[data-tone] {
|
|
77
|
+
border-color: transparent;
|
|
78
|
+
background: var(--zx-tag-tone-bg);
|
|
79
|
+
color: var(--zx-tag-tone-fg);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.zx-tag-picker__visual[data-tone] {
|
|
83
|
+
background: var(--zx-tag-tone-bg);
|
|
84
|
+
color: var(--zx-tag-tone-fg);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.zx-tag-picker .zx-tag-picker__tag[data-tone] .zx-tag-picker__remove {
|
|
88
|
+
color: inherit;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.zx-tag-picker .zx-tag-picker__tag[data-tone] .zx-tag-picker__remove:hover {
|
|
92
|
+
background: color-mix(in srgb, currentColor 14%, transparent);
|
|
93
|
+
color: inherit;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
:is(.zx-tag-picker__tag, .zx-tag-picker__visual)[data-tone="blue"] { --zx-tag-tone-bg: var(--zx-color-tone-blue-bg); --zx-tag-tone-fg: var(--zx-color-tone-blue-fg); }
|
|
97
|
+
:is(.zx-tag-picker__tag, .zx-tag-picker__visual)[data-tone="teal"] { --zx-tag-tone-bg: var(--zx-color-tone-teal-bg); --zx-tag-tone-fg: var(--zx-color-tone-teal-fg); }
|
|
98
|
+
:is(.zx-tag-picker__tag, .zx-tag-picker__visual)[data-tone="green"] { --zx-tag-tone-bg: var(--zx-color-tone-green-bg); --zx-tag-tone-fg: var(--zx-color-tone-green-fg); }
|
|
99
|
+
:is(.zx-tag-picker__tag, .zx-tag-picker__visual)[data-tone="amber"] { --zx-tag-tone-bg: var(--zx-color-tone-amber-bg); --zx-tag-tone-fg: var(--zx-color-tone-amber-fg); }
|
|
100
|
+
:is(.zx-tag-picker__tag, .zx-tag-picker__visual)[data-tone="orange"] { --zx-tag-tone-bg: var(--zx-color-tone-orange-bg); --zx-tag-tone-fg: var(--zx-color-tone-orange-fg); }
|
|
101
|
+
:is(.zx-tag-picker__tag, .zx-tag-picker__visual)[data-tone="red"] { --zx-tag-tone-bg: var(--zx-color-tone-red-bg); --zx-tag-tone-fg: var(--zx-color-tone-red-fg); }
|
|
102
|
+
:is(.zx-tag-picker__tag, .zx-tag-picker__visual)[data-tone="pink"] { --zx-tag-tone-bg: var(--zx-color-tone-pink-bg); --zx-tag-tone-fg: var(--zx-color-tone-pink-fg); }
|
|
103
|
+
:is(.zx-tag-picker__tag, .zx-tag-picker__visual)[data-tone="violet"] { --zx-tag-tone-bg: var(--zx-color-tone-violet-bg); --zx-tag-tone-fg: var(--zx-color-tone-violet-fg); }
|
|
104
|
+
:is(.zx-tag-picker__tag, .zx-tag-picker__visual)[data-tone="slate"] { --zx-tag-tone-bg: var(--zx-color-tone-slate-bg); --zx-tag-tone-fg: var(--zx-color-tone-slate-fg); }
|
|
105
|
+
|
|
68
106
|
.zx-tag-picker__tag:not(:has(.zx-tag-picker__remove)) {
|
|
69
107
|
padding-inline-end: var(--zx-space-2);
|
|
70
108
|
}
|
|
@@ -125,7 +163,7 @@
|
|
|
125
163
|
max-inline-size: calc(100vw - var(--zx-space-4));
|
|
126
164
|
overflow: hidden;
|
|
127
165
|
border: 1px solid var(--zx-color-overlay-border);
|
|
128
|
-
border-radius: var(--zx-radius-
|
|
166
|
+
border-radius: var(--zx-radius-lg);
|
|
129
167
|
background-color: var(--zx-color-overlay-surface);
|
|
130
168
|
background-image: var(--zx-overlay-surface-image);
|
|
131
169
|
background-clip: padding-box;
|
|
@@ -156,8 +194,11 @@
|
|
|
156
194
|
display: flex;
|
|
157
195
|
align-items: center;
|
|
158
196
|
gap: var(--zx-space-2);
|
|
159
|
-
|
|
160
|
-
|
|
197
|
+
/* The same row as a Select option and a menu item. */
|
|
198
|
+
min-block-size: calc(var(--zx-control-height) - 2px);
|
|
199
|
+
padding: var(--zx-space-1) var(--zx-space-2);
|
|
200
|
+
border-radius: var(--zx-radius-sm);
|
|
201
|
+
line-height: 1.35;
|
|
161
202
|
cursor: pointer;
|
|
162
203
|
}
|
|
163
204
|
|
|
@@ -165,9 +206,9 @@
|
|
|
165
206
|
background: var(--zx-color-overlay-hover);
|
|
166
207
|
}
|
|
167
208
|
|
|
209
|
+
/* A chosen tag keeps its check mark; the row itself stays in the text colour. */
|
|
168
210
|
.zx-tag-picker__option[aria-selected="true"] {
|
|
169
|
-
color: var(--zx-color-
|
|
170
|
-
font-weight: 550;
|
|
211
|
+
color: var(--zx-color-text);
|
|
171
212
|
}
|
|
172
213
|
|
|
173
214
|
.zx-tag-picker__option[aria-disabled="true"] {
|
|
@@ -202,3 +243,40 @@
|
|
|
202
243
|
font-size: var(--zx-text-sm);
|
|
203
244
|
text-align: center;
|
|
204
245
|
}
|
|
246
|
+
|
|
247
|
+
/*
|
|
248
|
+
* Quiet fields. Inside `[data-zx-fields="quiet"]` the tags read as the value: no border, no fill,
|
|
249
|
+
* no chevron. Hover brings the hover fill and the chevron back; focus or an open list brings back
|
|
250
|
+
* the border, the control fill and the focus ring. Disabled and read-only pickers never light up.
|
|
251
|
+
*/
|
|
252
|
+
[data-zx-fields="quiet"] .zx-tag-picker__control {
|
|
253
|
+
border-color: transparent;
|
|
254
|
+
background: transparent;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
[data-zx-fields="quiet"] .zx-tag-picker__toggle {
|
|
258
|
+
opacity: 0;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
[data-zx-fields="quiet"] .zx-tag-picker:not([data-disabled], [data-readonly]):hover .zx-tag-picker__control {
|
|
262
|
+
background: var(--zx-color-bg-hover);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
[data-zx-fields="quiet"] .zx-tag-picker:not([data-disabled], [data-readonly]):is(:hover, [data-focus], [data-state="open"]) .zx-tag-picker__toggle {
|
|
266
|
+
opacity: 1;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
[data-zx-fields="quiet"] .zx-tag-picker:not([data-disabled], [data-readonly]):is([data-focus], [data-state="open"]) .zx-tag-picker__control {
|
|
270
|
+
border-color: var(--zx-color-border-control);
|
|
271
|
+
background: var(--zx-color-bg-control);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
275
|
+
[data-zx-fields="quiet"] .zx-tag-picker__control {
|
|
276
|
+
transition: background-color var(--zx-dur-fast) var(--zx-ease), border-color var(--zx-dur-fast) var(--zx-ease);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
[data-zx-fields="quiet"] .zx-tag-picker__toggle {
|
|
280
|
+
transition: opacity var(--zx-dur-fast) var(--zx-ease);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
@@ -2,7 +2,9 @@ import { Component } from '../../core/component.js';
|
|
|
2
2
|
import { h, restoreTarget, snapshotTarget } from '../../core/dom.js';
|
|
3
3
|
import { icon } from '../../core/icons.js';
|
|
4
4
|
import { position } from '../../core/position.js';
|
|
5
|
-
import {
|
|
5
|
+
import { uid } from '../../core/util.js';
|
|
6
|
+
import { normalizeBadgeTone } from '../badge/badge.js';
|
|
7
|
+
import { itemColor } from '../select/color.js';
|
|
6
8
|
import { matchItems } from '../select/filter.js';
|
|
7
9
|
|
|
8
10
|
/** @typedef {Record<string, any>|string|number} TagItem */
|
|
@@ -15,7 +17,12 @@ import { matchItems } from '../select/filter.js';
|
|
|
15
17
|
* @property {TagValueReader} [valueKey='ID'] Item ID property or reader.
|
|
16
18
|
* @property {TagLabelReader} [labelKey='name'] Item label property or reader.
|
|
17
19
|
* @property {TagValueReader} [iconKey='icon'] Optional item icon property or reader.
|
|
18
|
-
* @property {TagValueReader} [colorKey='color'] Optional item colour property or reader
|
|
20
|
+
* @property {TagValueReader} [colorKey='color'] Optional item colour property or reader: a CSS colour
|
|
21
|
+
* or a token reference such as `var(--zx-color-tone-blue-fg)`.
|
|
22
|
+
* @property {TagValueReader} [toneKey='tone'] Optional item tone property or reader: a categorical
|
|
23
|
+
* tone name from the Badge palette (`blue`, `teal`, `green`, `amber`, `orange`, `red`, `pink`,
|
|
24
|
+
* `violet`, `slate`). A toned tag takes the palette's fill and ink, as a Badge with that `tone`
|
|
25
|
+
* does; a tone wins over a colour, and unknown names are ignored.
|
|
19
26
|
* @property {Array<TagValueReader>|null} [searchKeys=null] Fields searched by local filtering.
|
|
20
27
|
* @property {'local'|((query: string) => Promise<TagItem[]>|TagItem[])} [filter='local'] Filtering mode.
|
|
21
28
|
* @property {number} [minQuery=0] Minimum async query length.
|
|
@@ -26,7 +33,8 @@ import { matchItems } from '../select/filter.js';
|
|
|
26
33
|
* @property {string} [placeholder=''] Empty-state input text.
|
|
27
34
|
* @property {number} [listHeight=260] Maximum list height in pixels.
|
|
28
35
|
* @property {boolean} [disabled=false] Whether interaction is disabled.
|
|
29
|
-
* @property {boolean} [readonly=false]
|
|
36
|
+
* @property {boolean} [readonly=false] When true the picker shows only its tags — no input, chevron, or
|
|
37
|
+
* remove buttons.
|
|
30
38
|
* @property {((item: TagItem) => Node|string)|null} [renderItem=null] Option renderer.
|
|
31
39
|
* @property {((item: TagItem) => Node|string)|null} [renderTag=null] Tag-label renderer.
|
|
32
40
|
* @property {Record<string, string>|Record<string, Record<string, string>>} [msg] Localized messages.
|
|
@@ -69,6 +77,7 @@ export class TagPicker extends Component {
|
|
|
69
77
|
labelKey: 'name',
|
|
70
78
|
iconKey: 'icon',
|
|
71
79
|
colorKey: 'color',
|
|
80
|
+
toneKey: 'tone',
|
|
72
81
|
searchKeys: null,
|
|
73
82
|
filter: 'local',
|
|
74
83
|
minQuery: 0,
|
|
@@ -415,12 +424,13 @@ export class TagPicker extends Component {
|
|
|
415
424
|
_renderTags() {
|
|
416
425
|
const tags = this._selected.map((item) => {
|
|
417
426
|
const label = this._labelOf(item);
|
|
418
|
-
const
|
|
427
|
+
const tone = this._toneOf(item);
|
|
428
|
+
const color = tone ? null : this._colorOf(item);
|
|
419
429
|
const content = this.options.renderTag ? this.options.renderTag(item)
|
|
420
430
|
: [this._iconOf(item), h('span', { class: 'zx-tag-picker__tag-label' }, label)];
|
|
421
431
|
const tag = h('span', {
|
|
422
432
|
class: 'zx-tag-picker__tag',
|
|
423
|
-
dataset: { colored: String(Boolean(color)) },
|
|
433
|
+
dataset: { colored: String(Boolean(color)), tone: tone ?? undefined },
|
|
424
434
|
style: color ? { '--zx-tag-color': color } : null
|
|
425
435
|
}, content);
|
|
426
436
|
if (!this._readonly && !this._disabled) {
|
|
@@ -790,17 +800,24 @@ export class TagPicker extends Component {
|
|
|
790
800
|
? /** @type {Node} */ (value).cloneNode(true)
|
|
791
801
|
: typeof value === 'string' && value.trim() ? icon(value, { size: 12 }) : null;
|
|
792
802
|
if (!visual) return null;
|
|
803
|
+
const tone = this._toneOf(item);
|
|
804
|
+
const color = tone ? null : this._colorOf(item);
|
|
793
805
|
return h('span', {
|
|
794
806
|
class: 'zx-tag-picker__visual',
|
|
795
|
-
|
|
807
|
+
dataset: { tone: tone ?? undefined },
|
|
808
|
+
style: color ? { '--zx-tag-color': color } : null,
|
|
796
809
|
ariaHidden: 'true'
|
|
797
810
|
}, visual);
|
|
798
811
|
}
|
|
799
812
|
|
|
800
813
|
/** @param {unknown} item @returns {string|null} */
|
|
801
814
|
_colorOf(item) {
|
|
802
|
-
|
|
803
|
-
|
|
815
|
+
return itemColor(this._readItem(item, this.options.colorKey));
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/** @param {unknown} item @returns {string|null} */
|
|
819
|
+
_toneOf(item) {
|
|
820
|
+
return normalizeBadgeTone(this._readItem(item, this.options.toneKey));
|
|
804
821
|
}
|
|
805
822
|
|
|
806
823
|
/** @param {unknown} item @param {unknown} reader @returns {unknown} */
|
|
@@ -28,14 +28,14 @@
|
|
|
28
28
|
|
|
29
29
|
.zx-timebox__separator {
|
|
30
30
|
color: var(--zx-color-text-muted);
|
|
31
|
-
font-weight:
|
|
31
|
+
font-weight: var(--zx-weight-medium);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
.zx-timebox__sign {
|
|
35
35
|
min-inline-size: var(--zx-control-height);
|
|
36
36
|
padding: 0;
|
|
37
37
|
border-color: var(--zx-color-border-control);
|
|
38
|
-
font-weight:
|
|
38
|
+
font-weight: var(--zx-weight-semibold);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
.zx-timebox__sign[data-state="positive"] {
|
|
@@ -49,3 +49,23 @@
|
|
|
49
49
|
background: var(--zx-color-danger-bg);
|
|
50
50
|
color: var(--zx-color-danger);
|
|
51
51
|
}
|
|
52
|
+
|
|
53
|
+
/*
|
|
54
|
+
* Quiet fields. The hour and minute segments are native inputs, which the base quiet-fields rule
|
|
55
|
+
* already quiets. The sign button follows them: no border and no fill until hover or focus, its
|
|
56
|
+
* glyph keeping the colour that says which way the duration runs.
|
|
57
|
+
*/
|
|
58
|
+
[data-zx-fields="quiet"] .zx-timebox__sign,
|
|
59
|
+
[data-zx-fields="quiet"] .zx-timebox__sign[data-state] {
|
|
60
|
+
border-color: transparent;
|
|
61
|
+
background: transparent;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
[data-zx-fields="quiet"] .zx-timebox:not([aria-disabled="true"]) .zx-timebox__sign:hover {
|
|
65
|
+
background: var(--zx-color-bg-hover);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
[data-zx-fields="quiet"] .zx-timebox__sign:focus-visible {
|
|
69
|
+
border-color: var(--zx-color-border-control);
|
|
70
|
+
background: var(--zx-color-bg-control);
|
|
71
|
+
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
/* A label reads like text beside the switch: start-aligned, wrapping within the available width,
|
|
2
|
+
with the track level with its first line. A one-line toggle is still a control's height tall,
|
|
3
|
+
its track and its text centred in it. */
|
|
1
4
|
.zx-toggle {
|
|
2
5
|
display: inline-flex;
|
|
3
|
-
align-items:
|
|
6
|
+
align-items: flex-start;
|
|
4
7
|
gap: var(--zx-space-2);
|
|
8
|
+
max-inline-size: 100%;
|
|
5
9
|
min-block-size: var(--zx-control-height);
|
|
6
10
|
border: 0;
|
|
7
11
|
background: none;
|
|
@@ -9,6 +13,7 @@
|
|
|
9
13
|
padding: 0;
|
|
10
14
|
font: inherit;
|
|
11
15
|
font-size: var(--zx-control-font-size);
|
|
16
|
+
text-align: start;
|
|
12
17
|
cursor: pointer;
|
|
13
18
|
}
|
|
14
19
|
|
|
@@ -31,12 +36,18 @@
|
|
|
31
36
|
flex: none;
|
|
32
37
|
inline-size: 34px;
|
|
33
38
|
block-size: 20px;
|
|
39
|
+
margin-block-start: max(0px, (var(--zx-control-height) - 20px) / 2);
|
|
34
40
|
border: 1px solid var(--zx-color-border-strong);
|
|
35
41
|
border-radius: var(--zx-radius-full);
|
|
36
42
|
background: var(--zx-color-bg-control);
|
|
37
43
|
padding: 2px;
|
|
38
44
|
}
|
|
39
45
|
|
|
46
|
+
.zx-toggle__label {
|
|
47
|
+
min-inline-size: 0;
|
|
48
|
+
padding-block: max(0px, (var(--zx-control-height) - 1lh) / 2);
|
|
49
|
+
}
|
|
50
|
+
|
|
40
51
|
.zx-toggle__thumb {
|
|
41
52
|
display: block;
|
|
42
53
|
inline-size: 14px;
|
|
@@ -80,8 +80,8 @@ export class Toolbar extends Component {
|
|
|
80
80
|
/** Inline size of the last completed measure pass; `-1` forces the next one. */
|
|
81
81
|
#lastWidth = -1;
|
|
82
82
|
/**
|
|
83
|
-
* Block size of the last completed measure pass.
|
|
84
|
-
* changing the row width, so the height belongs in the cache key.
|
|
83
|
+
* Block size of the last completed measure pass. A theme change (control height, spacing unit)
|
|
84
|
+
* resizes the controls without changing the row width, so the height belongs in the cache key.
|
|
85
85
|
*/
|
|
86
86
|
#lastHeight = -1;
|
|
87
87
|
/** Handle of the frame a pending observer-driven measure pass is scheduled in; `0` if none. */
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
.zx-tooltip {
|
|
8
|
+
/* As wide as its text up to the maximum, never narrower: squeezed into too little room beside its
|
|
9
|
+
anchor, the bubble overflows instead of wrapping word by word, which is what makes the
|
|
10
|
+
position fall back to the other side, or above or below. */
|
|
11
|
+
inline-size: max-content;
|
|
8
12
|
max-inline-size: var(--zx-tooltip-max-inline-size, 260px);
|
|
9
13
|
border: 1px solid var(--zx-color-overlay-border);
|
|
10
14
|
border-radius: var(--zx-radius-md);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Component } from '../../core/component.js';
|
|
2
2
|
import { h, resolveElement } from '../../core/dom.js';
|
|
3
|
-
import { overlayHost } from '../../core/overlay-host.js';
|
|
3
|
+
import { connectedOverlayHost, overlayHost } from '../../core/overlay-host.js';
|
|
4
|
+
import { pushOverlay } from '../../core/overlay-stack.js';
|
|
4
5
|
import { position } from '../../core/position.js';
|
|
5
6
|
import { uid } from '../../core/util.js';
|
|
6
7
|
|
|
@@ -82,6 +83,10 @@ export class Tooltip extends Component {
|
|
|
82
83
|
#closeTimer = 0;
|
|
83
84
|
/** True between `pointerdown` and `pointerup`, so a click-induced focus cannot re-open. */
|
|
84
85
|
#pointerActive = false;
|
|
86
|
+
/** Whether the tooltip dismisses itself (every trigger but `manual`). */
|
|
87
|
+
#dismissible = false;
|
|
88
|
+
/** @type {import('../../core/overlay-stack.js').OverlayHandle|null} */
|
|
89
|
+
#overlay = null;
|
|
85
90
|
#disabled = false;
|
|
86
91
|
#destroyed = false;
|
|
87
92
|
|
|
@@ -96,7 +101,8 @@ export class Tooltip extends Component {
|
|
|
96
101
|
super(null, options);
|
|
97
102
|
|
|
98
103
|
this.#anchor = resolved;
|
|
99
|
-
|
|
104
|
+
// A detached anchor has no theme scope yet: the bubble waits and finds its host in show().
|
|
105
|
+
connectedOverlayHost(resolved, { dialog: false })?.append(this.el);
|
|
100
106
|
this.#content = this.options.content;
|
|
101
107
|
this.#disabled = Boolean(this.options.disabled);
|
|
102
108
|
this.#describedBy = resolved.getAttribute('aria-describedby');
|
|
@@ -104,6 +110,7 @@ export class Tooltip extends Component {
|
|
|
104
110
|
|
|
105
111
|
const trigger = TRIGGERS.has(this.options.trigger) ? this.options.trigger : 'both';
|
|
106
112
|
if (trigger === 'manual') return;
|
|
113
|
+
this.#dismissible = true;
|
|
107
114
|
|
|
108
115
|
if (trigger === 'hover' || trigger === 'both') {
|
|
109
116
|
this.listen(this.#anchor, 'pointerenter', (event) => {
|
|
@@ -123,26 +130,18 @@ export class Tooltip extends Component {
|
|
|
123
130
|
this.listen(this.#anchor, 'focusout', () => this.#scheduleHide(Number(this.options.hideDelay)));
|
|
124
131
|
}
|
|
125
132
|
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
this.hide();
|
|
132
|
-
});
|
|
133
|
-
this.listen(document, 'pointerdown', () => {
|
|
133
|
+
// A press on the anchor closes the bubble and cancels a pending open, and the focus that
|
|
134
|
+
// arrives with it is not a request for one. Presses elsewhere, Escape, and focus moving away
|
|
135
|
+
// reach an open bubble through the overlay stack, so a closed tooltip listens to nothing
|
|
136
|
+
// outside its own anchor.
|
|
137
|
+
this.listen(this.#anchor, 'pointerdown', () => {
|
|
134
138
|
this.#pointerActive = true;
|
|
135
139
|
this.#cancelTimers();
|
|
136
140
|
this.hide();
|
|
137
|
-
}, { capture: true });
|
|
138
|
-
this.listen(document, 'pointerup', () => { this.#pointerActive = false; }, { capture: true });
|
|
139
|
-
this.listen(document, 'pointercancel', () => { this.#pointerActive = false; }, { capture: true });
|
|
140
|
-
this.listen(document, 'focusin', (event) => {
|
|
141
|
-
if (!this.isOpen()) return;
|
|
142
|
-
const path = event.composedPath();
|
|
143
|
-
if (path.includes(this.#anchor)) return;
|
|
144
|
-
this.hide();
|
|
145
141
|
});
|
|
142
|
+
for (const type of ['pointerup', 'pointercancel', 'pointerleave']) {
|
|
143
|
+
this.listen(this.#anchor, type, () => { this.#pointerActive = false; });
|
|
144
|
+
}
|
|
146
145
|
}
|
|
147
146
|
|
|
148
147
|
/**
|
|
@@ -174,13 +173,36 @@ export class Tooltip extends Component {
|
|
|
174
173
|
if (node === null) return this;
|
|
175
174
|
|
|
176
175
|
this.el.replaceChildren(node);
|
|
176
|
+
const placement = PLACEMENTS.has(this.options.placement) ? this.options.placement : 'top';
|
|
177
177
|
this.#position = position(this.#anchor, /** @type {HTMLElement} */ (this.el), {
|
|
178
|
-
placement
|
|
178
|
+
placement,
|
|
179
179
|
offset: Number(this.options.offset),
|
|
180
180
|
flip: true
|
|
181
181
|
});
|
|
182
|
+
// A bubble beside its anchor that fits on neither side goes above or below it instead. Only
|
|
183
|
+
// the anchor-positioned path sets fallbacks; the script fallback clamps into the viewport.
|
|
184
|
+
if (/^(left|right)/.test(placement) && this.el.style.getPropertyValue('position-try-fallbacks')) {
|
|
185
|
+
this.el.style.setProperty('position-try-fallbacks', 'flip-inline, top span-all, bottom span-all');
|
|
186
|
+
}
|
|
182
187
|
this.el.dataset.state = 'open';
|
|
183
188
|
this.#anchor.setAttribute('aria-describedby', appendToken(this.#describedBy, this.el.id));
|
|
189
|
+
/*
|
|
190
|
+
* On the stack even when manual, so the order is shared and a closing parent takes the bubble
|
|
191
|
+
* with it; only a dismissible tooltip takes Escape (WCAG 1.4.13), presses, and focus. Escape
|
|
192
|
+
* reaches it only while it is the topmost layer that takes Escape, so one press never closes
|
|
193
|
+
* both a tooltip and the menu beneath it.
|
|
194
|
+
*/
|
|
195
|
+
this.#overlay = pushOverlay({
|
|
196
|
+
kind: 'tooltip',
|
|
197
|
+
root: this.el,
|
|
198
|
+
owner: this,
|
|
199
|
+
anchor: this.#anchor,
|
|
200
|
+
inside: [this.#anchor],
|
|
201
|
+
onEscape: this.#dismissible ? () => { this.hide(); } : undefined,
|
|
202
|
+
onOutsidePointer: this.#dismissible ? () => this.hide() : undefined,
|
|
203
|
+
onFocusOutside: this.#dismissible ? () => this.hide() : undefined,
|
|
204
|
+
onParentClose: () => this.hide()
|
|
205
|
+
});
|
|
184
206
|
this.emit('open');
|
|
185
207
|
return this;
|
|
186
208
|
}
|
|
@@ -198,6 +220,9 @@ export class Tooltip extends Component {
|
|
|
198
220
|
this.el.dataset.state = 'closed';
|
|
199
221
|
this.el.replaceChildren();
|
|
200
222
|
this.#restoreDescribedBy();
|
|
223
|
+
const overlay = this.#overlay;
|
|
224
|
+
this.#overlay = null;
|
|
225
|
+
overlay?.release();
|
|
201
226
|
this.emit('close');
|
|
202
227
|
return this;
|
|
203
228
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
.zx-tree {
|
|
2
|
-
|
|
2
|
+
/* One step per level: enough to read the nesting, not so much that a deep branch walks off the
|
|
3
|
+
edge of a sidebar. */
|
|
4
|
+
--zx-tree-indent: var(--zx-space-3);
|
|
3
5
|
display: block;
|
|
4
6
|
min-inline-size: 0;
|
|
5
7
|
color: var(--zx-color-text);
|
|
@@ -10,10 +12,12 @@
|
|
|
10
12
|
display: flex;
|
|
11
13
|
align-items: center;
|
|
12
14
|
gap: var(--zx-space-2);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
/* The same row as a Finder column: a space-1 margin round one line of text. */
|
|
16
|
+
min-block-size: calc(var(--zx-control-height) - var(--zx-space-1));
|
|
17
|
+
padding: var(--zx-space-1) var(--zx-space-2);
|
|
15
18
|
padding-inline-start: calc(var(--zx-space-2) + var(--zx-tree-level, 0) * var(--zx-tree-indent));
|
|
16
|
-
border-radius: var(--zx-radius-
|
|
19
|
+
border-radius: var(--zx-radius-sm);
|
|
20
|
+
line-height: 1.25;
|
|
17
21
|
cursor: pointer;
|
|
18
22
|
}
|
|
19
23
|
|
|
@@ -21,14 +25,22 @@
|
|
|
21
25
|
background: var(--zx-color-bg-hover);
|
|
22
26
|
}
|
|
23
27
|
|
|
28
|
+
/* The selected node of a single-selection tree is where you are, not something you picked: the
|
|
29
|
+
neutral current fill, the full text colour and a heavier label. A multi-selection is a set of
|
|
30
|
+
picks and keeps the accent tint, so the two never read as the same thing. */
|
|
24
31
|
.zx-tree__row[aria-selected="true"] {
|
|
32
|
+
background: var(--zx-color-bg-current);
|
|
33
|
+
color: var(--zx-color-text);
|
|
34
|
+
font-weight: var(--zx-weight-semibold);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.zx-tree[aria-multiselectable="true"] .zx-tree__row[aria-selected="true"] {
|
|
25
38
|
background: var(--zx-color-bg-selected);
|
|
26
|
-
|
|
27
|
-
font-weight: 550;
|
|
39
|
+
font-weight: inherit;
|
|
28
40
|
}
|
|
29
41
|
|
|
30
42
|
.zx-tree__row:focus-visible {
|
|
31
|
-
outline:
|
|
43
|
+
outline-color: transparent;
|
|
32
44
|
box-shadow: var(--zx-focus-ring);
|
|
33
45
|
}
|
|
34
46
|
|
|
@@ -38,7 +50,7 @@
|
|
|
38
50
|
inline-size: 14px;
|
|
39
51
|
block-size: 14px;
|
|
40
52
|
flex: none;
|
|
41
|
-
color: var(--zx-color-text-
|
|
53
|
+
color: var(--zx-color-text-subtle);
|
|
42
54
|
}
|
|
43
55
|
|
|
44
56
|
.zx-tree__row[aria-expanded="true"] .zx-tree__twisty {
|
|
@@ -60,19 +72,17 @@
|
|
|
60
72
|
margin: 0;
|
|
61
73
|
}
|
|
62
74
|
|
|
75
|
+
/* Icons are quieter than labels, folders included: a branch is told apart by its glyph and its
|
|
76
|
+
twisty, not by borrowing a status colour. The current row's icon takes the text colour. */
|
|
63
77
|
.zx-tree__icon {
|
|
64
78
|
display: inline-grid;
|
|
65
79
|
place-items: center;
|
|
66
80
|
flex: none;
|
|
67
|
-
color: var(--zx-color-text-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.zx-tree__row[data-branch] .zx-tree__icon {
|
|
71
|
-
color: var(--zx-color-warning);
|
|
81
|
+
color: var(--zx-color-text-subtle);
|
|
72
82
|
}
|
|
73
83
|
|
|
74
84
|
.zx-tree__row[aria-selected="true"] .zx-tree__icon {
|
|
75
|
-
color:
|
|
85
|
+
color: var(--zx-color-text);
|
|
76
86
|
}
|
|
77
87
|
|
|
78
88
|
.zx-tree__label {
|
|
@@ -83,11 +93,10 @@
|
|
|
83
93
|
|
|
84
94
|
.zx-tree__badge {
|
|
85
95
|
margin-inline-start: auto;
|
|
86
|
-
padding-inline: var(--zx-space-
|
|
87
|
-
border-radius: var(--zx-radius-full);
|
|
88
|
-
background: var(--zx-color-bg-muted);
|
|
96
|
+
padding-inline: var(--zx-space-1);
|
|
89
97
|
color: var(--zx-color-text-muted);
|
|
90
98
|
font-size: var(--zx-text-xs);
|
|
99
|
+
font-weight: var(--zx-weight-medium);
|
|
91
100
|
font-variant-numeric: tabular-nums;
|
|
92
101
|
}
|
|
93
102
|
|
|
@@ -611,6 +611,11 @@ export class TreeView extends Component {
|
|
|
611
611
|
this._expandSiblings(row);
|
|
612
612
|
return;
|
|
613
613
|
default:
|
|
614
|
+
// A printable key typed on a row belongs to the type-ahead: claimed, so the browser's
|
|
615
|
+
// find-as-you-type and the page's single-key shortcuts do not act on it as well. Typing
|
|
616
|
+
// into a control that `renderLabel` placed in a row stays that control's.
|
|
617
|
+
if (!isTreeTypeaheadKey(event) || isTextEntry(event.target)) return;
|
|
618
|
+
event.preventDefault();
|
|
614
619
|
this._handleTypeahead(event);
|
|
615
620
|
}
|
|
616
621
|
}
|
|
@@ -782,3 +787,29 @@ function cloneNodes(nodes) {
|
|
|
782
787
|
function toIterable(value) {
|
|
783
788
|
return Array.isArray(value) ? value : [];
|
|
784
789
|
}
|
|
790
|
+
|
|
791
|
+
/**
|
|
792
|
+
* Whether a key press is one the type-ahead consumes: a single printable character, not a space
|
|
793
|
+
* (Space selects), with no Ctrl, Meta, or Alt (those are shortcuts). Shift is allowed, since it
|
|
794
|
+
* only changes the letter's case.
|
|
795
|
+
* @param {{key?: string, ctrlKey?: boolean, metaKey?: boolean, altKey?: boolean}} event Key event.
|
|
796
|
+
* @returns {boolean}
|
|
797
|
+
*/
|
|
798
|
+
export function isTreeTypeaheadKey(event) {
|
|
799
|
+
if (!event || event.ctrlKey || event.metaKey || event.altKey) return false;
|
|
800
|
+
const key = typeof event.key === 'string' ? event.key : '';
|
|
801
|
+
// The same test the shared type-ahead applies, so a key is claimed exactly when it is used.
|
|
802
|
+
return key.length === 1 && !/\s/.test(key);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
/** @param {EventTarget|null} target @returns {boolean} Whether typing into the target edits text. */
|
|
806
|
+
function isTextEntry(target) {
|
|
807
|
+
const element = /** @type {HTMLElement|null} */ (target && /** @type {Node} */ (target).nodeType === 1
|
|
808
|
+
? target : null);
|
|
809
|
+
if (!element) return false;
|
|
810
|
+
if (element.isContentEditable) return true;
|
|
811
|
+
if (element.localName === 'textarea' || element.localName === 'select') return true;
|
|
812
|
+
if (element.localName !== 'input') return false;
|
|
813
|
+
return !['checkbox', 'radio', 'button', 'submit', 'reset', 'image', 'range', 'color', 'file']
|
|
814
|
+
.includes(/** @type {HTMLInputElement} */ (element).type);
|
|
815
|
+
}
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
max-inline-size: 100%;
|
|
30
30
|
padding-inline: var(--zx-space-2);
|
|
31
31
|
border: 1px solid var(--zx-color-border);
|
|
32
|
-
border-radius: var(--zx-radius-
|
|
33
|
-
background: var(--zx-color-bg-
|
|
32
|
+
border-radius: var(--zx-radius-md);
|
|
33
|
+
background: var(--zx-color-bg-muted);
|
|
34
34
|
color: var(--zx-color-text);
|
|
35
35
|
cursor: grab;
|
|
36
36
|
}
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
place-items: center;
|
|
51
51
|
min-inline-size: 1.25rem;
|
|
52
52
|
min-block-size: 1.25rem;
|
|
53
|
-
border-radius: var(--zx-radius-
|
|
53
|
+
border-radius: var(--zx-radius-sm);
|
|
54
54
|
color: var(--zx-color-text-muted);
|
|
55
55
|
cursor: pointer;
|
|
56
56
|
}
|