@zeyos/zx 5.0.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 +164 -0
- package/README.md +2 -1
- package/dist/types/components/account-menu/account-menu.d.ts +8 -0
- package/dist/types/components/activity-list/activity-list.d.ts +9 -1
- package/dist/types/components/app-icon/app-icon.d.ts +14 -2
- package/dist/types/components/app-sidebar/app-sidebar.d.ts +288 -14
- 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/context-menu/context-menu.d.ts +6 -2
- package/dist/types/components/data-filter/data-filter.d.ts +4 -4
- package/dist/types/components/dropdown/dropdown.d.ts +22 -7
- package/dist/types/components/field/field.d.ts +30 -0
- package/dist/types/components/fieldset/external-adapter.d.ts +83 -0
- package/dist/types/components/fieldset/fieldset.d.ts +7 -0
- 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/launcher/launcher.d.ts +8 -0
- package/dist/types/components/list-toolbar/list-toolbar.d.ts +15 -6
- package/dist/types/components/menu-button/menu-button.d.ts +6 -0
- package/dist/types/components/message/message.d.ts +14 -1
- package/dist/types/components/modal/modal.d.ts +30 -0
- 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/select.d.ts +6 -0
- package/dist/types/components/sheet/sheet.d.ts +15 -0
- package/dist/types/components/table/table.d.ts +265 -17
- 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/component.d.ts +12 -2
- package/dist/types/core/i18n.d.ts +27 -3
- package/dist/types/core/keyboard.d.ts +98 -1
- package/dist/types/core/messages.d.ts +382 -0
- package/dist/types/core/overlay-host.d.ts +28 -1
- package/dist/types/core/overlay-stack.d.ts +260 -0
- package/dist/types/index.d.ts +5 -2
- package/dist/types/internal/app-rail.d.ts +38 -0
- package/dist/types/internal/menu-items.d.ts +71 -3
- package/dist/types/zeyos/index.d.ts +1 -0
- 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 +31 -5
- package/dist/types/zeyos/table.d.ts +245 -8
- package/dist/types/zeyos/view.d.ts +16 -2
- package/dist/zx-zeyos.esm.js +4422 -430
- package/dist/zx-zeyos.esm.min.js +5 -5
- package/dist/zx.css +1417 -134
- package/dist/zx.esm.js +6986 -830
- package/dist/zx.esm.min.js +8 -8
- package/dist/zx.global.js +6986 -830
- package/dist/zx.global.min.js +8 -8
- package/dist/zx.min.css +1 -1
- package/docs/api.json +794 -17
- package/docs/llms.md +503 -63
- package/docs/llms.txt +6 -2
- package/package.json +1 -1
- package/src/components/account-menu/account-menu.js +12 -0
- package/src/components/activity-list/activity-list.js +27 -1
- package/src/components/app-icon/app-icon.css +13 -2
- package/src/components/app-icon/app-icon.js +11 -1
- package/src/components/app-rail/app-rail.css +19 -0
- package/src/components/app-sidebar/app-sidebar.css +204 -3
- package/src/components/app-sidebar/app-sidebar.js +646 -40
- package/src/components/breadcrumb/breadcrumb.css +1 -1
- package/src/components/calendar/calendar.css +1 -1
- package/src/components/calendar/calendar.js +26 -52
- package/src/components/card/card.css +2 -2
- package/src/components/card-view/card-view.css +5 -5
- package/src/components/card-view/card-view.js +13 -9
- package/src/components/card-view/record-card.js +14 -3
- package/src/components/code-editor/code-editor.css +1 -1
- package/src/components/code-editor/field-adapter.js +9 -2
- package/src/components/context-menu/context-menu.js +8 -2
- package/src/components/copy/copy-input.css +1 -1
- package/src/components/data-filter/data-filter.js +2 -2
- package/src/components/date-picker/time-picker.css +2 -2
- package/src/components/dock/dock.css +5 -4
- package/src/components/dropdown/dropdown.js +157 -72
- package/src/components/field/field.js +33 -3
- package/src/components/fieldset/external-adapter.js +363 -0
- package/src/components/fieldset/fieldset.js +10 -59
- package/src/components/file-list/file-list.js +144 -21
- package/src/components/filter/filter.css +86 -2
- package/src/components/filter/filter.js +300 -8
- package/src/components/filter-panel/filter-panel.js +149 -32
- package/src/components/finder/finder.css +1 -1
- package/src/components/kanban-view/kanban-view.css +3 -3
- package/src/components/kanban-view/kanban-view.js +5 -2
- package/src/components/launcher/launcher.css +1 -1
- package/src/components/launcher/launcher.js +29 -3
- package/src/components/list-toolbar/list-toolbar.js +39 -13
- package/src/components/master-panel/master-panel.js +0 -1
- package/src/components/menu-button/menu-button.css +63 -0
- package/src/components/menu-button/menu-button.js +97 -11
- package/src/components/message/message.js +60 -20
- package/src/components/modal/modal.css +1 -1
- package/src/components/modal/modal.js +66 -13
- 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/number-field/field-adapter.js +2 -1
- package/src/components/pagination/pagination.css +5 -5
- package/src/components/pagination/pagination.js +20 -4
- package/src/components/panel/panel.css +3 -2
- package/src/components/questionnaire/questionnaire.css +4 -4
- package/src/components/rating/field-adapter.js +2 -1
- package/src/components/rating/rating.css +1 -1
- package/src/components/search/search.css +4 -1
- package/src/components/select/select.js +9 -0
- package/src/components/sheet/sheet.css +1 -1
- package/src/components/sheet/sheet.js +74 -32
- package/src/components/slider/field-adapter.js +6 -1
- package/src/components/slider/slider.css +2 -2
- package/src/components/split-view/split-view.css +1 -1
- package/src/components/stat-tile/stat-tile.css +1 -1
- package/src/components/stepper/stepper.css +1 -1
- package/src/components/tabbox/tabbox.css +9 -5
- package/src/components/table/table.css +86 -11
- package/src/components/table/table.js +628 -57
- package/src/components/tag-picker/field-adapter.js +2 -1
- package/src/components/tooltip/tooltip.js +35 -17
- package/src/components/tree/tree.css +1 -1
- 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/component.js +88 -17
- package/src/core/fontawesome.js +5 -1
- package/src/core/i18n.js +47 -4
- package/src/core/icons.js +12 -2
- package/src/core/keyboard.js +206 -11
- package/src/core/messages.js +427 -0
- package/src/core/overlay-host.js +64 -9
- package/src/core/overlay-stack.js +487 -0
- package/src/core/position.js +22 -3
- package/src/index.js +5 -2
- package/src/internal/app-rail.js +134 -53
- package/src/internal/menu-items.js +61 -3
- package/src/zeyos/form.js +5 -3
- package/src/zeyos/index.js +3 -0
- package/src/zeyos/launcher.js +8 -3
- package/src/zeyos/module-bar.js +181 -0
- package/src/zeyos/query.js +44 -13
- package/src/zeyos/table.js +220 -80
- package/src/zeyos/view.js +43 -93
- package/styles/base.css +16 -1
- package/styles/print.css +1 -1
- package/styles/tokens/dark.css +4 -0
- package/styles/tokens/semantic.css +56 -28
- package/styles/zx.css +3 -0
|
@@ -47,7 +47,9 @@ import {
|
|
|
47
47
|
* @property {CalendarReader} [eventEditable='editable'] Per-event move reader.
|
|
48
48
|
* @property {CalendarReader} [eventDurationEditable='durationEditable'] Per-event resize reader.
|
|
49
49
|
* @property {'milliseconds'|'seconds'} [dateUnit='milliseconds'] Unit for numeric event dates.
|
|
50
|
-
* @property {Record<string, string>} [msg]
|
|
50
|
+
* @property {Record<string, string>} [msg] Per-instance messages, keyed `calendar.*` (`calendar.today`,
|
|
51
|
+
* `calendar.next`, …). The bare keys of earlier versions (`today`, `next`) are still read, after the
|
|
52
|
+
* namespaced key, until the next major version.
|
|
51
53
|
* @property {(event: CalendarEvent) => Node|string|null} [renderEvent] Optional safe event-content renderer.
|
|
52
54
|
* @property {(event: CustomEvent<{events: CalendarEvent[]}>) => void} [oneventschange] Programmatic event-data listener.
|
|
53
55
|
* @property {(event: CustomEvent<{view: CalendarView, oldView: CalendarView}>) => void} [onviewchange] View listener.
|
|
@@ -73,31 +75,6 @@ import {
|
|
|
73
75
|
|
|
74
76
|
/** @typedef {{silent?: boolean}} CalendarSetOptions */
|
|
75
77
|
|
|
76
|
-
const DEFAULT_MESSAGES = {
|
|
77
|
-
today: 'Today',
|
|
78
|
-
new: 'New',
|
|
79
|
-
agenda: 'Agenda',
|
|
80
|
-
day: 'Day',
|
|
81
|
-
week: 'Week',
|
|
82
|
-
month: 'Month',
|
|
83
|
-
year: 'Year',
|
|
84
|
-
previous: 'Previous period',
|
|
85
|
-
next: 'Next period',
|
|
86
|
-
allDay: 'All day',
|
|
87
|
-
noEvents: 'No events',
|
|
88
|
-
more: '+%1 more',
|
|
89
|
-
loading: 'Loading calendar…',
|
|
90
|
-
move: 'Move %1',
|
|
91
|
-
resize: 'Resize %1',
|
|
92
|
-
moveStarted: 'Moving %1. Use arrow keys, Space to drop, or Escape to cancel.',
|
|
93
|
-
resizeStarted: 'Resizing %1. Use arrow keys, Space to drop, or Escape to cancel.',
|
|
94
|
-
editPreview: '%1, %2 to %3',
|
|
95
|
-
editCancelled: 'Calendar edit cancelled.',
|
|
96
|
-
editCommitted: '%1 updated.',
|
|
97
|
-
calendar: 'Calendar',
|
|
98
|
-
weekNumber: 'Week %1'
|
|
99
|
-
};
|
|
100
|
-
|
|
101
78
|
/**
|
|
102
79
|
* Accessible, dependency-free agenda/day/week/month/year scheduling surface.
|
|
103
80
|
* @fires Calendar#viewchange
|
|
@@ -147,8 +124,7 @@ export class Calendar extends Component {
|
|
|
147
124
|
eventLocation: 'location',
|
|
148
125
|
eventEditable: 'editable',
|
|
149
126
|
eventDurationEditable: 'durationEditable',
|
|
150
|
-
dateUnit: 'milliseconds'
|
|
151
|
-
msg: DEFAULT_MESSAGES
|
|
127
|
+
dateUnit: 'milliseconds'
|
|
152
128
|
};
|
|
153
129
|
|
|
154
130
|
/** @returns {HTMLElement} */
|
|
@@ -178,9 +154,9 @@ export class Calendar extends Component {
|
|
|
178
154
|
this._nowTimer = null;
|
|
179
155
|
|
|
180
156
|
const navigation = h('div', { class: 'zx-calendar__navigation' },
|
|
181
|
-
this._toolbarButton('previous', this.msg('previous'), 'chevron-left'),
|
|
182
|
-
this._toolbarButton('today', this.msg('today')),
|
|
183
|
-
this._toolbarButton('next', this.msg('next'), 'chevron-right'));
|
|
157
|
+
this._toolbarButton('previous', this.msg('calendar.previous'), 'chevron-left'),
|
|
158
|
+
this._toolbarButton('today', this.msg('calendar.today')),
|
|
159
|
+
this._toolbarButton('next', this.msg('calendar.next'), 'chevron-right'));
|
|
184
160
|
const heading = h('h2', {
|
|
185
161
|
ref: 'heading',
|
|
186
162
|
class: 'zx-calendar__heading',
|
|
@@ -196,14 +172,14 @@ export class Calendar extends Component {
|
|
|
196
172
|
class: 'zx-calendar__view-button',
|
|
197
173
|
dataset: { calendarAction: 'view', view },
|
|
198
174
|
disabled: this.options.disabled
|
|
199
|
-
}, this.msg(view))));
|
|
175
|
+
}, this.msg(`calendar.${view}`))));
|
|
200
176
|
const commands = h('div', { class: 'zx-calendar__commands' }, views,
|
|
201
177
|
h('button', {
|
|
202
178
|
type: 'button',
|
|
203
179
|
class: 'zx-calendar__new',
|
|
204
180
|
dataset: { calendarAction: 'new' },
|
|
205
181
|
disabled: this.options.disabled
|
|
206
|
-
}, icon('plus'), h('span', {}, this.msg('new'))));
|
|
182
|
+
}, icon('plus'), h('span', {}, this.msg('calendar.new'))));
|
|
207
183
|
const toolbar = h('header', { class: 'zx-calendar__toolbar' }, navigation, heading, commands);
|
|
208
184
|
const body = h('div', { ref: 'body', class: 'zx-calendar__body' });
|
|
209
185
|
const loading = h('div', {
|
|
@@ -211,7 +187,7 @@ export class Calendar extends Component {
|
|
|
211
187
|
class: 'zx-calendar__loading',
|
|
212
188
|
role: 'status',
|
|
213
189
|
hidden: true
|
|
214
|
-
}, this.msg('loading'));
|
|
190
|
+
}, this.msg('calendar.loading'));
|
|
215
191
|
const status = h('div', {
|
|
216
192
|
ref: 'status',
|
|
217
193
|
class: 'zx-calendar__status',
|
|
@@ -220,7 +196,7 @@ export class Calendar extends Component {
|
|
|
220
196
|
ariaAtomic: 'true'
|
|
221
197
|
});
|
|
222
198
|
root.replaceChildren(toolbar, body, loading, status);
|
|
223
|
-
root.setAttribute('aria-label', this.msg('calendar'));
|
|
199
|
+
root.setAttribute('aria-label', this.msg('calendar.label'));
|
|
224
200
|
root.dataset.view = this._view;
|
|
225
201
|
root.dataset.state = 'ready';
|
|
226
202
|
|
|
@@ -470,7 +446,7 @@ export class Calendar extends Component {
|
|
|
470
446
|
}, this._format(day, { weekday: 'long', day: 'numeric', month: 'long' })));
|
|
471
447
|
const entries = h('div', { class: 'zx-calendar__agenda-events', role: 'gridcell' });
|
|
472
448
|
if (!events.length) {
|
|
473
|
-
entries.append(h('p', { class: 'zx-calendar__agenda-empty' }, this.msg('noEvents')));
|
|
449
|
+
entries.append(h('p', { class: 'zx-calendar__agenda-empty' }, this.msg('calendar.noEvents')));
|
|
474
450
|
} else {
|
|
475
451
|
for (const event of events) entries.append(this._eventElement(event, { variant: 'agenda', day }));
|
|
476
452
|
}
|
|
@@ -576,7 +552,7 @@ export class Calendar extends Component {
|
|
|
576
552
|
/** @param {Date[]} days @returns {HTMLElement} */
|
|
577
553
|
_renderAllDayRail(days) {
|
|
578
554
|
const rail = h('div', { class: 'zx-calendar__all-day' },
|
|
579
|
-
h('span', { class: 'zx-calendar__all-day-label' }, this.msg('allDay')));
|
|
555
|
+
h('span', { class: 'zx-calendar__all-day-label' }, this.msg('calendar.allDay')));
|
|
580
556
|
const layer = h('div', {
|
|
581
557
|
class: 'zx-calendar__all-day-grid',
|
|
582
558
|
role: 'row',
|
|
@@ -625,7 +601,7 @@ export class Calendar extends Component {
|
|
|
625
601
|
type: 'button',
|
|
626
602
|
class: 'zx-calendar__month-week-number',
|
|
627
603
|
dataset: { calendarAction: 'week', date: calendarDayKey(start) },
|
|
628
|
-
ariaLabel: this.msg('weekNumber', isoWeek(start)),
|
|
604
|
+
ariaLabel: this.msg('calendar.weekNumber', isoWeek(start)),
|
|
629
605
|
disabled: this.options.disabled
|
|
630
606
|
}, String(isoWeek(start))));
|
|
631
607
|
const days = h('div', { class: 'zx-calendar__month-days' });
|
|
@@ -666,7 +642,7 @@ export class Calendar extends Component {
|
|
|
666
642
|
dataset: { calendarAction: 'more', date: calendarDayKey(day), count: String(count) },
|
|
667
643
|
style: { gridColumn: String(index + 1), gridRow: String(eventLimit + 1) },
|
|
668
644
|
disabled: this.options.disabled
|
|
669
|
-
}, this.msg('more', count)));
|
|
645
|
+
}, this.msg('calendar.more', count)));
|
|
670
646
|
}
|
|
671
647
|
row.append(days, lanes);
|
|
672
648
|
wrapper.append(row);
|
|
@@ -758,7 +734,7 @@ export class Calendar extends Component {
|
|
|
758
734
|
type: 'button',
|
|
759
735
|
class: 'zx-calendar__event-resize',
|
|
760
736
|
dataset: { eventAction: 'resize', eventId: key },
|
|
761
|
-
ariaLabel: this.msg('resize', event.title),
|
|
737
|
+
ariaLabel: this.msg('calendar.resize', event.title),
|
|
762
738
|
disabled: this.options.disabled
|
|
763
739
|
}, h('span', { ariaHidden: 'true' })));
|
|
764
740
|
}
|
|
@@ -886,7 +862,7 @@ export class Calendar extends Component {
|
|
|
886
862
|
};
|
|
887
863
|
control.setAttribute('aria-grabbed', 'true');
|
|
888
864
|
control.closest('.zx-calendar__event')?.setAttribute('data-state', 'grabbed');
|
|
889
|
-
this._announce(this.msg(resize ? 'resizeStarted' : 'moveStarted', item.title));
|
|
865
|
+
this._announce(this.msg(resize ? 'calendar.resizeStarted' : 'calendar.moveStarted', item.title));
|
|
890
866
|
return;
|
|
891
867
|
}
|
|
892
868
|
if (!this._keyboardEdit || String(this._keyboardEdit.event.id) !== String(item.id)) return;
|
|
@@ -919,7 +895,7 @@ export class Calendar extends Component {
|
|
|
919
895
|
if (proposed.end > proposed.start) edit.event = proposed;
|
|
920
896
|
}
|
|
921
897
|
edit.control.closest('.zx-calendar__event')?.setAttribute('data-preview', this._eventTime(edit.event, edit.event.start));
|
|
922
|
-
this._announce(this.msg('editPreview', edit.event.title,
|
|
898
|
+
this._announce(this.msg('calendar.editPreview', edit.event.title,
|
|
923
899
|
this._dateTimeLabel(edit.event.start), this._dateTimeLabel(edit.event.end)));
|
|
924
900
|
}
|
|
925
901
|
|
|
@@ -1065,7 +1041,7 @@ export class Calendar extends Component {
|
|
|
1065
1041
|
}
|
|
1066
1042
|
wrapper.dataset.preview = this._eventTime(proposed, proposed.start);
|
|
1067
1043
|
}
|
|
1068
|
-
this._announce(this.msg('editPreview', proposed.title,
|
|
1044
|
+
this._announce(this.msg('calendar.editPreview', proposed.title,
|
|
1069
1045
|
this._dateTimeLabel(proposed.start), this._dateTimeLabel(proposed.end)));
|
|
1070
1046
|
}
|
|
1071
1047
|
|
|
@@ -1255,7 +1231,7 @@ export class Calendar extends Component {
|
|
|
1255
1231
|
edit.control.removeAttribute('aria-grabbed');
|
|
1256
1232
|
edit.control.closest('.zx-calendar__event')?.removeAttribute('data-state');
|
|
1257
1233
|
this._keyboardEdit = null;
|
|
1258
|
-
this._announce(this.msg('editCancelled'));
|
|
1234
|
+
this._announce(this.msg('calendar.editCancelled'));
|
|
1259
1235
|
this._renderView({ preserveFocus: true });
|
|
1260
1236
|
}
|
|
1261
1237
|
|
|
@@ -1286,7 +1262,7 @@ export class Calendar extends Component {
|
|
|
1286
1262
|
this._replaceNormalizedEvent(oldEvent);
|
|
1287
1263
|
this._mutationVersions.delete(key);
|
|
1288
1264
|
this._renderView({ preserveFocus: true });
|
|
1289
|
-
this._announce(this.msg('editCancelled'));
|
|
1265
|
+
this._announce(this.msg('calendar.editCancelled'));
|
|
1290
1266
|
return true;
|
|
1291
1267
|
};
|
|
1292
1268
|
const detail = {
|
|
@@ -1299,7 +1275,7 @@ export class Calendar extends Component {
|
|
|
1299
1275
|
};
|
|
1300
1276
|
const emitted = this.emit('eventchange', detail);
|
|
1301
1277
|
if (emitted.defaultPrevented) revert();
|
|
1302
|
-
else this._announce(this.msg('editCommitted', proposed.title));
|
|
1278
|
+
else this._announce(this.msg('calendar.editCommitted', proposed.title));
|
|
1303
1279
|
}
|
|
1304
1280
|
|
|
1305
1281
|
/** @param {CalendarEvent} event @returns {void} */
|
|
@@ -1364,11 +1340,11 @@ export class Calendar extends Component {
|
|
|
1364
1340
|
|
|
1365
1341
|
/** @param {CalendarEvent} event @param {Date} day @returns {string} */
|
|
1366
1342
|
_eventTime(event, day) {
|
|
1367
|
-
if (event.allDay) return this.msg('allDay');
|
|
1343
|
+
if (event.allDay) return this.msg('calendar.allDay');
|
|
1368
1344
|
if (calendarEventSpansDays(event)) {
|
|
1369
1345
|
if (sameCalendarDay(event.start, day)) return `${formatDateTime(event.start, this.options.locale)} →`;
|
|
1370
1346
|
if (sameCalendarDay(event.end, day)) return `→ ${formatDateTime(event.end, this.options.locale)}`;
|
|
1371
|
-
return this.msg('allDay');
|
|
1347
|
+
return this.msg('calendar.allDay');
|
|
1372
1348
|
}
|
|
1373
1349
|
const start = formatTimeDate(event.start, this.options.locale);
|
|
1374
1350
|
if (event.end <= event.start) return start;
|
|
@@ -1490,10 +1466,8 @@ export class Calendar extends Component {
|
|
|
1490
1466
|
}
|
|
1491
1467
|
|
|
1492
1468
|
/**
|
|
1493
|
-
* Resolves a message through
|
|
1494
|
-
*
|
|
1495
|
-
* Distinct from `msg()`: the built-in `msg` option answers the calendar's own vocabulary, so a
|
|
1496
|
-
* dotted key falls past it to the host translator, which is what these strings never had.
|
|
1469
|
+
* Resolves a message through `msg()`, falling back to the built-in English text. Redundant now
|
|
1470
|
+
* that `msg()` ends in the default catalogue; kept until the private copies are removed.
|
|
1497
1471
|
* @param {string} key Message key.
|
|
1498
1472
|
* @param {string} fallback Built-in text, with `%1`-style placeholders.
|
|
1499
1473
|
* @param {...unknown} args Interpolation values.
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
.zx-card:has(.zx-card__primary:focus-visible) {
|
|
54
|
-
outline:
|
|
54
|
+
outline-color: transparent;
|
|
55
55
|
box-shadow: var(--zx-focus-ring);
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
.zx-card__primary:focus-visible {
|
|
132
|
-
outline:
|
|
132
|
+
outline-color: transparent;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
.zx-card__actions,
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
.zx-card-view__sort select:focus-visible {
|
|
41
|
-
outline:
|
|
41
|
+
outline-color: transparent;
|
|
42
42
|
box-shadow: var(--zx-focus-ring);
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
.zx-record-card:focus-visible {
|
|
106
|
-
outline:
|
|
106
|
+
outline-color: transparent;
|
|
107
107
|
box-shadow: var(--zx-focus-ring);
|
|
108
108
|
}
|
|
109
109
|
|
|
@@ -179,7 +179,7 @@
|
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
.zx-record-card__selection input:focus-visible {
|
|
182
|
-
outline:
|
|
182
|
+
outline-color: transparent;
|
|
183
183
|
box-shadow: var(--zx-focus-ring);
|
|
184
184
|
}
|
|
185
185
|
|
|
@@ -246,7 +246,7 @@
|
|
|
246
246
|
|
|
247
247
|
.zx-record-card__primary:focus-visible {
|
|
248
248
|
border-radius: var(--zx-radius-sm);
|
|
249
|
-
outline:
|
|
249
|
+
outline-color: transparent;
|
|
250
250
|
box-shadow: var(--zx-focus-ring);
|
|
251
251
|
}
|
|
252
252
|
|
|
@@ -291,7 +291,7 @@
|
|
|
291
291
|
}
|
|
292
292
|
|
|
293
293
|
.zx-record-card__action:focus-visible {
|
|
294
|
-
outline:
|
|
294
|
+
outline-color: transparent;
|
|
295
295
|
box-shadow: var(--zx-focus-ring);
|
|
296
296
|
}
|
|
297
297
|
|
|
@@ -47,7 +47,8 @@ import {
|
|
|
47
47
|
* @property {'outlined'|'raised'|'filled'} [variant='outlined'] Card surface treatment.
|
|
48
48
|
* @property {number} [loadingCount=6] Skeleton cards shown while loading.
|
|
49
49
|
* @property {1|2|3|4|5|6} [headingLevel=3] Per-card title heading level.
|
|
50
|
-
* @property {string} [label=
|
|
50
|
+
* @property {string|null} [label=null] Accessible collection label; null resolves message
|
|
51
|
+
* `cardView.label`, "Card view".
|
|
51
52
|
* @property {(event:CustomEvent<Record<string,unknown>>)=>void} [onrecordaction]
|
|
52
53
|
*/
|
|
53
54
|
|
|
@@ -96,7 +97,7 @@ export class CardView extends RecordView {
|
|
|
96
97
|
variant: 'outlined',
|
|
97
98
|
loadingCount: 6,
|
|
98
99
|
headingLevel: 3,
|
|
99
|
-
label:
|
|
100
|
+
label: null
|
|
100
101
|
};
|
|
101
102
|
|
|
102
103
|
/**
|
|
@@ -126,7 +127,7 @@ export class CardView extends RecordView {
|
|
|
126
127
|
this._cardHeadingLevel = normalizeHeadingLevel(options.headingLevel);
|
|
127
128
|
try {
|
|
128
129
|
this._initRecordView(root);
|
|
129
|
-
root.setAttribute('aria-label', String(options.label || '
|
|
130
|
+
root.setAttribute('aria-label', String(options.label || this.msg('cardView.label')));
|
|
130
131
|
const sort = h('label', { ref: 'sortWrap', class: 'zx-card-view__sort' },
|
|
131
132
|
h('span', { class: 'zx-card-view__sort-label' }, this._message('cardView.sort', 'Sort')),
|
|
132
133
|
h('select', { ref: 'sort', ariaLabel: this._message('cardView.sortCards', 'Sort cards') }));
|
|
@@ -258,7 +259,7 @@ export class CardView extends RecordView {
|
|
|
258
259
|
return;
|
|
259
260
|
}
|
|
260
261
|
const groups = groupCardRecords(this._viewData, this._cardOptions().groupBy,
|
|
261
|
-
this._cardGroupOrder, this._viewFields);
|
|
262
|
+
this._cardGroupOrder, this._viewFields, this.msg('cardView.ungrouped'));
|
|
262
263
|
if (this._viewData.length === 0 && groups.length === 0) {
|
|
263
264
|
content.replaceChildren(this._createCardEmpty());
|
|
264
265
|
return;
|
|
@@ -298,13 +299,14 @@ export class CardView extends RecordView {
|
|
|
298
299
|
selectionTrigger: options.selectionTrigger,
|
|
299
300
|
selected: this._isViewSelected(id),
|
|
300
301
|
variant: this._cardVariant,
|
|
301
|
-
headingLevel: this._cardHeadingLevel
|
|
302
|
+
headingLevel: this._cardHeadingLevel,
|
|
303
|
+
message: (key, ...args) => this.msg(key, ...args)
|
|
302
304
|
});
|
|
303
305
|
this._cardNodesById.set(id, card);
|
|
304
306
|
list.append(card);
|
|
305
307
|
}
|
|
306
308
|
if (group.records.length === 0) {
|
|
307
|
-
list.append(h('li', { class: 'zx-card-view__group-empty' },
|
|
309
|
+
list.append(h('li', { class: 'zx-card-view__group-empty' }, this.msg('cardView.groupEmpty')));
|
|
308
310
|
}
|
|
309
311
|
if (group.id === null) return list;
|
|
310
312
|
return h('section', { class: 'zx-card-view__group', ariaLabelledby: headingId },
|
|
@@ -339,7 +341,8 @@ export class CardView extends RecordView {
|
|
|
339
341
|
for (const [id, card] of this._cardNodesById) {
|
|
340
342
|
const selected = this._isViewSelected(id);
|
|
341
343
|
card.dataset.selected = String(selected);
|
|
342
|
-
if (this.options.selectable) card.setAttribute('aria-description',
|
|
344
|
+
if (this.options.selectable) card.setAttribute('aria-description',
|
|
345
|
+
this.msg(selected ? 'recordCard.selected' : 'recordCard.notSelected'));
|
|
343
346
|
const checkbox = /** @type {HTMLInputElement|null} */ (card.querySelector('[data-record-selection]'));
|
|
344
347
|
if (checkbox) checkbox.checked = selected;
|
|
345
348
|
}
|
|
@@ -444,9 +447,10 @@ export class CardView extends RecordView {
|
|
|
444
447
|
* @param {CardViewOptions['groupBy']} groupBy Group field or resolver.
|
|
445
448
|
* @param {unknown[]} [groupOrder=[]] Preferred group ids.
|
|
446
449
|
* @param {ViewField[]} [fields=[]] Complete fields for accessor-aware grouping.
|
|
450
|
+
* @param {string} [ungroupedLabel='Ungrouped'] Label of the group collecting records without a value.
|
|
447
451
|
* @returns {CardRecordGroup[]} Deterministic groups.
|
|
448
452
|
*/
|
|
449
|
-
export function groupCardRecords(records, groupBy, groupOrder = [], fields = []) {
|
|
453
|
+
export function groupCardRecords(records, groupBy, groupOrder = [], fields = [], ungroupedLabel = 'Ungrouped') {
|
|
450
454
|
if (!Array.isArray(records)) throw new TypeError('Card view records must be an array');
|
|
451
455
|
if (groupBy == null) return records.length ? [{ id: null, label: '', records: [...records] }] : [];
|
|
452
456
|
const preferred = normalizeGroupOrder(groupOrder);
|
|
@@ -461,7 +465,7 @@ export function groupCardRecords(records, groupBy, groupOrder = [], fields = [])
|
|
|
461
465
|
}
|
|
462
466
|
return [...groups].map(([id, grouped]) => ({
|
|
463
467
|
id,
|
|
464
|
-
label: id ||
|
|
468
|
+
label: id || ungroupedLabel,
|
|
465
469
|
records: grouped
|
|
466
470
|
}));
|
|
467
471
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { h, safeHref } from '../../core/dom.js';
|
|
3
3
|
import { icon } from '../../core/icons.js';
|
|
4
|
+
import { translate } from '../../core/i18n.js';
|
|
4
5
|
import { uid } from '../../core/util.js';
|
|
5
6
|
import { readViewField, renderViewField } from '../view/record-view.js';
|
|
6
7
|
|
|
@@ -67,6 +68,10 @@ import { readViewField, renderViewField } from '../view/record-view.js';
|
|
|
67
68
|
* @property {'outlined'|'raised'|'filled'} [variant='outlined'] Surface treatment.
|
|
68
69
|
* @property {1|2|3|4|5|6} [headingLevel=3] Card title heading level.
|
|
69
70
|
* @property {Node[]} [controls=[]] Listener-free, owner-created controls such as a move handle.
|
|
71
|
+
* @property {(key: string, ...args: unknown[]) => string} [message] Resolves the card's built-in strings
|
|
72
|
+
* (`recordCard.select`, `recordCard.actions`, `recordCard.untitled`, `recordCard.selected`,
|
|
73
|
+
* `recordCard.notSelected`). An owning component passes its own `msg()`; omitted, the host
|
|
74
|
+
* translator and then the default English catalogue answer.
|
|
70
75
|
*/
|
|
71
76
|
|
|
72
77
|
/**
|
|
@@ -111,6 +116,11 @@ export function createRecordCard(record, index, options = {}) {
|
|
|
111
116
|
const selected = Boolean(options.selected);
|
|
112
117
|
const headingId = uid('zx-record-card-title');
|
|
113
118
|
const headingLevel = normalizeHeadingLevel(options.headingLevel);
|
|
119
|
+
/** @type {(key: string, ...args: unknown[]) => string} */
|
|
120
|
+
const message = typeof options.message === 'function'
|
|
121
|
+
? options.message
|
|
122
|
+
: (key, ...args) => translate(key, args);
|
|
123
|
+
const name = textAlternative(title) || message('recordCard.untitled');
|
|
114
124
|
|
|
115
125
|
const headingContent = link
|
|
116
126
|
? h('a', {
|
|
@@ -137,13 +147,13 @@ export function createRecordCard(record, index, options = {}) {
|
|
|
137
147
|
type: 'checkbox',
|
|
138
148
|
checked: selected,
|
|
139
149
|
dataset: { recordSelection: '' },
|
|
140
|
-
ariaLabel:
|
|
150
|
+
ariaLabel: message('recordCard.select', name)
|
|
141
151
|
})) : null;
|
|
142
152
|
const actionNodes = actions.map(createAction);
|
|
143
153
|
const actionArea = actionNodes.length || controls.length ? h('div', {
|
|
144
154
|
class: 'zx-record-card__actions',
|
|
145
155
|
role: 'group',
|
|
146
|
-
ariaLabel:
|
|
156
|
+
ariaLabel: message('recordCard.actions', name)
|
|
147
157
|
}, controls, actionNodes) : null;
|
|
148
158
|
const header = h('header', { class: 'zx-record-card__header' }, selection,
|
|
149
159
|
h('div', { class: 'zx-record-card__titles' }, titleRow,
|
|
@@ -154,7 +164,8 @@ export function createRecordCard(record, index, options = {}) {
|
|
|
154
164
|
const card = /** @type {HTMLLIElement} */ (h('li', {
|
|
155
165
|
class: 'zx-record-card',
|
|
156
166
|
tabindex: 0,
|
|
157
|
-
ariaDescription: selectable
|
|
167
|
+
ariaDescription: selectable
|
|
168
|
+
? message(selected ? 'recordCard.selected' : 'recordCard.notSelected') : undefined,
|
|
158
169
|
ariaLabelledby: headingId,
|
|
159
170
|
ariaKeyshortcuts: selectable && options.selectionTrigger === 'card' ? 'Space Enter' : undefined,
|
|
160
171
|
dataset: {
|
|
@@ -16,9 +16,15 @@ export function registerCodeEditorFieldAdapter() {
|
|
|
16
16
|
value: options.value
|
|
17
17
|
}));
|
|
18
18
|
let setting = false;
|
|
19
|
-
|
|
19
|
+
// The textarea's native `change` bubbles out of the editor after the editor has reported the
|
|
20
|
+
// same commit; without this the Field would emit `change` twice per edit.
|
|
21
|
+
field.listen(editor.el, 'change', (event) => event.stopImmediatePropagation());
|
|
22
|
+
// `change` on commit (the editor's own, when the textarea loses focus after an edit); every
|
|
23
|
+
// keystroke as `input`.
|
|
24
|
+
editor.on('change', (event) => {
|
|
20
25
|
if (!setting) field.emit('change', { value: event.detail.value });
|
|
21
26
|
});
|
|
27
|
+
editor.on('input', (event) => field.emit('input', { value: event.detail.value }));
|
|
22
28
|
return {
|
|
23
29
|
el: editor.el,
|
|
24
30
|
get: () => editor.getValue(),
|
|
@@ -28,7 +34,8 @@ export function registerCodeEditorFieldAdapter() {
|
|
|
28
34
|
finally { setting = false; }
|
|
29
35
|
},
|
|
30
36
|
focus: () => editor.focus(),
|
|
31
|
-
setDisabled: (value) => (value ? editor.disable() : editor.enable())
|
|
37
|
+
setDisabled: (value) => (value ? editor.disable() : editor.enable()),
|
|
38
|
+
setReadonly: (value) => { editor.setReadOnly(value); }
|
|
32
39
|
};
|
|
33
40
|
});
|
|
34
41
|
}
|
|
@@ -9,7 +9,11 @@ import {
|
|
|
9
9
|
import { Dropdown } from '../dropdown/dropdown.js';
|
|
10
10
|
|
|
11
11
|
/** @typedef {import('../../internal/menu-items.js').MenuItem} MenuItem */
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* A context menu's entries: the shared menu model without `choice` rows, which a menu that closes
|
|
14
|
+
* on every activation cannot hold.
|
|
15
|
+
* @typedef {import('../../internal/menu-items.js').MenuItem|import('../../internal/menu-items.js').MenuHeading|import('../../internal/menu-items.js').MenuSeparator|'-'} ContextMenuEntry
|
|
16
|
+
*/
|
|
13
17
|
|
|
14
18
|
/**
|
|
15
19
|
* @typedef {Object} ContextMenuOptions
|
|
@@ -90,6 +94,8 @@ export class ContextMenu extends Component {
|
|
|
90
94
|
scope: resolved
|
|
91
95
|
});
|
|
92
96
|
this.#panel = this.#dropdown.getPanel();
|
|
97
|
+
// Escape arrives through the overlay stack; closing returns focus where the menu came from.
|
|
98
|
+
this.#dropdown._configure({ onEscape: () => this.close(), tabReach: false });
|
|
93
99
|
this.#panel.classList.add('zx-context-menu');
|
|
94
100
|
this.#panel.setAttribute('role', 'menu');
|
|
95
101
|
|
|
@@ -268,7 +274,7 @@ export class ContextMenu extends Component {
|
|
|
268
274
|
/** @param {Event} event @returns {void} */
|
|
269
275
|
#onMenuKeydown(event) {
|
|
270
276
|
const key = /** @type {KeyboardEvent} */ (event);
|
|
271
|
-
if (key.key === '
|
|
277
|
+
if (key.key === 'Tab') {
|
|
272
278
|
event.preventDefault();
|
|
273
279
|
this.close();
|
|
274
280
|
return;
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
* @property {Array<string|((row: DataFilterRow) => unknown)>} [fields] Row fields combined with OR.
|
|
21
21
|
* @property {(row: DataFilterRow) => unknown} [get] Custom value accessor.
|
|
22
22
|
* @property {Array<unknown|DataFilterOption>} [options] Explicit options; omitted derives distinct values.
|
|
23
|
-
* @property {string} [emptyLabel] Empty option label.
|
|
23
|
+
* @property {string} [emptyLabel] Empty option label; omitted resolves message `dataFilter.all`, "All".
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
/**
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
* @property {FilterDefinition[]} [filters=[]] Declarative filters.
|
|
49
49
|
* @property {DataFilterRow[]} [data=[]] Rows to filter.
|
|
50
50
|
* @property {boolean} [autoApply=true] Apply and emit whenever a control changes.
|
|
51
|
-
* @property {string|null} [clearLabel=null] Clear button label; null resolves `dataFilter.clear
|
|
51
|
+
* @property {string|null} [clearLabel=null] Clear button label; null resolves message `dataFilter.clear`, "Clear".
|
|
52
52
|
* @property {(event: CustomEvent<DataFilterEventDetail>) => void} [onfilter]
|
|
53
53
|
*/
|
|
54
54
|
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
.zx-time-picker__clock-unit:focus-visible {
|
|
87
|
-
outline:
|
|
87
|
+
outline-color: transparent;
|
|
88
88
|
box-shadow: var(--zx-focus-ring);
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
.zx-time-picker__mark:focus-visible {
|
|
149
|
-
outline:
|
|
149
|
+
outline-color: transparent;
|
|
150
150
|
box-shadow: var(--zx-focus-ring);
|
|
151
151
|
}
|
|
152
152
|
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
.zx-dock__toggle:disabled .zx-dock__chevron { visibility: hidden; }
|
|
84
84
|
|
|
85
85
|
.zx-dock__toggle:focus-visible {
|
|
86
|
-
outline:
|
|
86
|
+
outline-color: transparent;
|
|
87
87
|
box-shadow: var(--zx-focus-ring);
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
.zx-dock__tab:focus-visible {
|
|
144
|
-
outline:
|
|
144
|
+
outline-color: transparent;
|
|
145
145
|
box-shadow: var(--zx-focus-ring);
|
|
146
146
|
}
|
|
147
147
|
|
|
@@ -172,7 +172,8 @@
|
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
.zx-dock__panel:focus-visible {
|
|
175
|
-
outline:
|
|
175
|
+
outline-color: transparent;
|
|
176
|
+
outline-offset: -2px;
|
|
176
177
|
box-shadow: inset var(--zx-focus-ring);
|
|
177
178
|
}
|
|
178
179
|
|
|
@@ -222,7 +223,7 @@
|
|
|
222
223
|
}
|
|
223
224
|
|
|
224
225
|
.zx-dock__divider:focus-visible {
|
|
225
|
-
outline:
|
|
226
|
+
outline-color: transparent;
|
|
226
227
|
z-index: 1;
|
|
227
228
|
box-shadow: var(--zx-focus-ring);
|
|
228
229
|
}
|