@lo-tek/interfaces 0.37.0 → 0.38.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 +137 -2
- package/README.md +4 -3
- package/agent/astro.md +1 -1
- package/agent/bundles.md +1 -1
- package/agent/datastar.md +48 -48
- package/agent/html.md +51 -51
- package/agent/react.md +1 -1
- package/agent/templates.md +49 -49
- package/core/lotek-core.wasm +0 -0
- package/core/lotek.wasm +0 -0
- package/dist/components/default-texts.d.ts +6 -0
- package/dist/components/default-texts.d.ts.map +1 -1
- package/dist/components/default-texts.js +6 -0
- package/dist/components/default-texts.js.map +1 -1
- package/dist/components/frame/dialog/lt-dialog.d.ts.map +1 -1
- package/dist/components/frame/dialog/lt-dialog.js +5 -2
- package/dist/components/frame/dialog/lt-dialog.js.map +1 -1
- package/dist/components/frame/error-summary/error-summary.d.ts +15 -2
- package/dist/components/frame/error-summary/error-summary.d.ts.map +1 -1
- package/dist/components/frame/error-summary/error-summary.js +33 -11
- package/dist/components/frame/error-summary/error-summary.js.map +1 -1
- package/dist/components/frame/error-summary/lt-error-summary.d.ts +11 -0
- package/dist/components/frame/error-summary/lt-error-summary.d.ts.map +1 -1
- package/dist/components/frame/error-summary/lt-error-summary.js +114 -8
- package/dist/components/frame/error-summary/lt-error-summary.js.map +1 -1
- package/dist/components/frame/field/lt-field.d.ts.map +1 -1
- package/dist/components/frame/field/lt-field.js +34 -14
- package/dist/components/frame/field/lt-field.js.map +1 -1
- package/dist/components/frame/popover/lt-popover.d.ts +6 -2
- package/dist/components/frame/popover/lt-popover.d.ts.map +1 -1
- package/dist/components/frame/popover/lt-popover.js +44 -14
- package/dist/components/frame/popover/lt-popover.js.map +1 -1
- package/dist/components/frame/session-timeout/lt-session-timeout.d.ts.map +1 -1
- package/dist/components/frame/session-timeout/lt-session-timeout.js +43 -6
- package/dist/components/frame/session-timeout/lt-session-timeout.js.map +1 -1
- package/dist/components/frame/suggestion/lt-suggestion.d.ts +8 -2
- package/dist/components/frame/suggestion/lt-suggestion.d.ts.map +1 -1
- package/dist/components/frame/suggestion/lt-suggestion.js +56 -37
- package/dist/components/frame/suggestion/lt-suggestion.js.map +1 -1
- package/dist/components/frame/tabs/lt-tabs.d.ts +32 -10
- package/dist/components/frame/tabs/lt-tabs.d.ts.map +1 -1
- package/dist/components/frame/tabs/lt-tabs.js +85 -21
- package/dist/components/frame/tabs/lt-tabs.js.map +1 -1
- package/dist/components/host-element.d.ts +49 -0
- package/dist/components/host-element.d.ts.map +1 -1
- package/dist/components/host-element.js +74 -0
- package/dist/components/host-element.js.map +1 -1
- package/dist/components/standalone/connection-status/connection-status.d.ts +5 -1
- package/dist/components/standalone/connection-status/connection-status.d.ts.map +1 -1
- package/dist/components/standalone/connection-status/connection-status.js +5 -1
- package/dist/components/standalone/connection-status/connection-status.js.map +1 -1
- package/dist/components/standalone/connection-status/lt-connection-status.d.ts +11 -6
- package/dist/components/standalone/connection-status/lt-connection-status.d.ts.map +1 -1
- package/dist/components/standalone/connection-status/lt-connection-status.js +34 -10
- package/dist/components/standalone/connection-status/lt-connection-status.js.map +1 -1
- package/dist/diagnostics/core.d.ts +34 -0
- package/dist/diagnostics/core.d.ts.map +1 -1
- package/dist/diagnostics/core.js +14 -2
- package/dist/diagnostics/core.js.map +1 -1
- package/dist/lotek.css +1 -1
- package/dist/lt.d.ts +1 -1
- package/dist/react.d.ts +2 -0
- package/dist/react.d.ts.map +1 -1
- package/dist/vocabulary/classes.d.ts.map +1 -1
- package/dist/vocabulary/classes.js +34 -0
- package/dist/vocabulary/classes.js.map +1 -1
- package/dist/vocabulary/elements.d.ts.map +1 -1
- package/dist/vocabulary/elements.js +87 -7
- package/dist/vocabulary/elements.js.map +1 -1
- package/dist/vocabulary/types.d.ts +54 -0
- package/dist/vocabulary/types.d.ts.map +1 -1
- package/live-templates.xml +3 -2
- package/manifest/manifest.json +133 -8
- package/manifest/manifest.schema.json +73 -0
- package/package.json +2 -1
- package/src/components/default-texts.ts +7 -0
- package/src/components/frame/dialog/lt-dialog.ts +5 -2
- package/src/components/frame/error-summary/error-summary.ts +45 -11
- package/src/components/frame/error-summary/lt-error-summary.ts +121 -7
- package/src/components/frame/field/lt-field.ts +65 -28
- package/src/components/frame/popover/lt-popover.ts +43 -12
- package/src/components/frame/session-timeout/lt-session-timeout.ts +40 -6
- package/src/components/frame/suggestion/lt-suggestion.ts +57 -36
- package/src/components/frame/tabs/lt-tabs.ts +114 -38
- package/src/components/host-element.ts +93 -0
- package/src/components/standalone/connection-status/connection-status.ts +7 -1
- package/src/components/standalone/connection-status/lt-connection-status.ts +36 -10
- package/src/diagnostics/core.ts +19 -2
- package/src/vocabulary/classes.ts +34 -0
- package/src/vocabulary/elements.ts +87 -7
- package/src/vocabulary/types.ts +50 -0
- package/web-types.json +1 -1
|
@@ -12,6 +12,8 @@ export type ConnectionStatusOptions = {
|
|
|
12
12
|
|
|
13
13
|
export type ConnectionStatusAttributes = {
|
|
14
14
|
class: typeof CONNECTION_STATUS_CLASS
|
|
15
|
+
role: "status"
|
|
16
|
+
"aria-live": "polite"
|
|
15
17
|
"offline-text"?: string
|
|
16
18
|
"online-text"?: string
|
|
17
19
|
"data-ignore-morph": ""
|
|
@@ -23,7 +25,9 @@ export type ConnectionStatusAttributes = {
|
|
|
23
25
|
* By definition the server cannot tell you it is unreachable. When it is
|
|
24
26
|
* down, nothing comes from it to render. So the component creates all the
|
|
25
27
|
* content itself, and `data-ignore-morph` stops a later patch from tearing
|
|
26
|
-
* it away the moment the connection is back.
|
|
28
|
+
* it away the moment the connection is back. The host is the live region,
|
|
29
|
+
* `role="status"` with `aria-live="polite"`, so the region exists before the
|
|
30
|
+
* bar and its text arrive.
|
|
27
31
|
*
|
|
28
32
|
* ```ts
|
|
29
33
|
* <lt-connection-status {...lt.connectionStatus()} />
|
|
@@ -35,6 +39,8 @@ export const connectionStatus = ({
|
|
|
35
39
|
}: ConnectionStatusOptions = {}): ConnectionStatusAttributes =>
|
|
36
40
|
attributes({
|
|
37
41
|
class: CONNECTION_STATUS_CLASS,
|
|
42
|
+
role: "status" as const,
|
|
43
|
+
"aria-live": "polite" as const,
|
|
38
44
|
"offline-text": offlineText,
|
|
39
45
|
"online-text": onlineText,
|
|
40
46
|
"data-ignore-morph": "" as const,
|
|
@@ -77,6 +77,23 @@ export class LtConnectionStatus extends HostElement {
|
|
|
77
77
|
|
|
78
78
|
connectedCallback(): void {
|
|
79
79
|
this.classList.add(CONNECTION_STATUS_CLASS)
|
|
80
|
+
/*
|
|
81
|
+
* The host is the live region, from the moment it is connected, so the
|
|
82
|
+
* region exists long before the bar and its text arrive. Only what is
|
|
83
|
+
* missing: a role or politeness the server wrote stays. When the bar was
|
|
84
|
+
* the region, it was inserted together with its text, and Firefox sent
|
|
85
|
+
* no live-region text through AT-SPI at all, so "No connection" was
|
|
86
|
+
* never announced. `check-accessibility-tree.ts` checks it.
|
|
87
|
+
*/
|
|
88
|
+
this.markRegion()
|
|
89
|
+
// A morph without `data-ignore-morph` takes both off, and then the next
|
|
90
|
+
// outage is never announced. Writing only what is missing keeps the
|
|
91
|
+
// observer from triggering itself.
|
|
92
|
+
this.regionObserver = new MutationObserver(() => this.markRegion())
|
|
93
|
+
this.regionObserver.observe(this, {
|
|
94
|
+
attributes: true,
|
|
95
|
+
attributeFilter: ["role", "aria-live"],
|
|
96
|
+
})
|
|
80
97
|
window.addEventListener("offline", this.handleOffline)
|
|
81
98
|
window.addEventListener("online", this.handleOnline)
|
|
82
99
|
if (!navigator.onLine) {
|
|
@@ -96,7 +113,22 @@ export class LtConnectionStatus extends HostElement {
|
|
|
96
113
|
}
|
|
97
114
|
}
|
|
98
115
|
|
|
116
|
+
private regionObserver?: MutationObserver
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* The region, as a pair and only when both are missing. A role the server
|
|
120
|
+
* wrote carries its own politeness (`alert` is assertive), and an
|
|
121
|
+
* `aria-live` added next to it would override that.
|
|
122
|
+
*/
|
|
123
|
+
private markRegion(): void {
|
|
124
|
+
if (this.hasAttribute("role") || this.hasAttribute("aria-live")) return
|
|
125
|
+
this.setAttribute("role", "status")
|
|
126
|
+
this.setAttribute("aria-live", "polite")
|
|
127
|
+
}
|
|
128
|
+
|
|
99
129
|
disconnectedCallback(): void {
|
|
130
|
+
this.regionObserver?.disconnect()
|
|
131
|
+
this.regionObserver = undefined
|
|
100
132
|
window.removeEventListener("offline", this.handleOffline)
|
|
101
133
|
window.removeEventListener("online", this.handleOnline)
|
|
102
134
|
if (this.timer) window.clearTimeout(this.timer)
|
|
@@ -107,12 +139,10 @@ export class LtConnectionStatus extends HostElement {
|
|
|
107
139
|
* The bar, created empty first and filled afterwards.
|
|
108
140
|
*
|
|
109
141
|
* A live region must exist before its content arrives, or assistive
|
|
110
|
-
* technology does not announce the first change.
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* checked without a screen reader; the rule is known from NVDA, JAWS and
|
|
115
|
-
* VoiceOver.
|
|
142
|
+
* technology does not announce the first change. The region is the host
|
|
143
|
+
* (see `connectedCallback`), so the bar is content inside a region that is
|
|
144
|
+
* already there; the text is still set in the next frame when the bar is
|
|
145
|
+
* new, so the bar and its text arrive as two changes.
|
|
116
146
|
*
|
|
117
147
|
* The bar is created only when it is needed, not on connection: when it
|
|
118
148
|
* was in the DOM before React hydrated, React found an element it had not
|
|
@@ -123,10 +153,6 @@ export class LtConnectionStatus extends HostElement {
|
|
|
123
153
|
|
|
124
154
|
const bar = document.createElement("div")
|
|
125
155
|
bar.className = CONNECTION_STATUS_BAR_CLASS
|
|
126
|
-
// polite and not assertive: the message matters, but should not
|
|
127
|
-
// interrupt mid-word. It stays until the connection is back.
|
|
128
|
-
bar.setAttribute("role", "status")
|
|
129
|
-
bar.setAttribute("aria-live", "polite")
|
|
130
156
|
this.append(bar)
|
|
131
157
|
this.bar = bar
|
|
132
158
|
return { bar, fresh: true }
|
package/src/diagnostics/core.ts
CHANGED
|
@@ -148,12 +148,23 @@ type Exports = {
|
|
|
148
148
|
inspect_theme_raw(pointer: number, length: number): number
|
|
149
149
|
inspect_styles_raw(pointer: number, length: number): void
|
|
150
150
|
diagnose_styled_raw(pointer: number, length: number): number
|
|
151
|
+
accessibility_tree_raw(pointer: number, length: number): number
|
|
152
|
+
accessibility_facts_raw(): void
|
|
153
|
+
accessibility_roles_raw(): void
|
|
154
|
+
accessibility_states_raw(): void
|
|
151
155
|
result_ptr(): number
|
|
152
156
|
result_len(): number
|
|
153
157
|
}
|
|
154
158
|
|
|
155
|
-
/**
|
|
156
|
-
|
|
159
|
+
/**
|
|
160
|
+
* @internal Not part of the package's API.
|
|
161
|
+
*
|
|
162
|
+
* An instance of the core and the helpers every call goes through: the text
|
|
163
|
+
* written into the module's memory, and the answer read back. Not part of
|
|
164
|
+
* the package: `index.ts` exports `loadCore`. The tests reach the core's
|
|
165
|
+
* other functions, such as the accessibility tree, through this.
|
|
166
|
+
*/
|
|
167
|
+
export function instantiate(source: BufferSource | WebAssembly.Module) {
|
|
157
168
|
const module =
|
|
158
169
|
source instanceof WebAssembly.Module
|
|
159
170
|
? source
|
|
@@ -181,6 +192,12 @@ export function loadCore(source: BufferSource | WebAssembly.Module): Core {
|
|
|
181
192
|
if (status !== 0) throw new Error(read<{ error: string }>().error)
|
|
182
193
|
return read<T>()
|
|
183
194
|
}
|
|
195
|
+
return { e, write, read, answer }
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** Loads the core from the module's bytes or an already compiled module. */
|
|
199
|
+
export function loadCore(source: BufferSource | WebAssembly.Module): Core {
|
|
200
|
+
const { e, write, read, answer } = instantiate(source)
|
|
184
201
|
|
|
185
202
|
return {
|
|
186
203
|
diagnoseMarkup: (html) => answer(e.diagnose_markup_raw(...write(html))),
|
|
@@ -311,6 +311,7 @@ export const classes: Classes = {
|
|
|
311
311
|
"optional": true
|
|
312
312
|
}
|
|
313
313
|
},
|
|
314
|
+
"name": {},
|
|
314
315
|
"attributes": {
|
|
315
316
|
"data-state": {
|
|
316
317
|
"values": [
|
|
@@ -328,6 +329,22 @@ export const classes: Classes = {
|
|
|
328
329
|
"link": "https://lo-tek.sobernetics.no/components/fieldset/",
|
|
329
330
|
"content": "text",
|
|
330
331
|
"partOf": "lt-fieldset",
|
|
332
|
+
"texts": [
|
|
333
|
+
{
|
|
334
|
+
"variable": "--lt-label-required-text",
|
|
335
|
+
"text": " (required)",
|
|
336
|
+
"attribute": "data-required",
|
|
337
|
+
"value": "text"
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
"variable": "--lt-label-optional-text",
|
|
341
|
+
"text": " (optional)",
|
|
342
|
+
"attribute": "data-optional",
|
|
343
|
+
"unless": [
|
|
344
|
+
"data-required"
|
|
345
|
+
]
|
|
346
|
+
}
|
|
347
|
+
],
|
|
331
348
|
"attributes": {
|
|
332
349
|
"data-required": {
|
|
333
350
|
"values": [
|
|
@@ -453,6 +470,22 @@ export const classes: Classes = {
|
|
|
453
470
|
"description": "A label for form fields, with marking of required and optional. A CSS component.",
|
|
454
471
|
"link": "https://lo-tek.sobernetics.no/components/label/",
|
|
455
472
|
"content": "text",
|
|
473
|
+
"texts": [
|
|
474
|
+
{
|
|
475
|
+
"variable": "--lt-label-required-text",
|
|
476
|
+
"text": " (required)",
|
|
477
|
+
"attribute": "data-required",
|
|
478
|
+
"value": "text"
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
"variable": "--lt-label-optional-text",
|
|
482
|
+
"text": " (optional)",
|
|
483
|
+
"attribute": "data-optional",
|
|
484
|
+
"unless": [
|
|
485
|
+
"data-required"
|
|
486
|
+
]
|
|
487
|
+
}
|
|
488
|
+
],
|
|
456
489
|
"attributes": {
|
|
457
490
|
"data-required": {
|
|
458
491
|
"values": [
|
|
@@ -885,6 +918,7 @@ export const classes: Classes = {
|
|
|
885
918
|
"multiple": true
|
|
886
919
|
}
|
|
887
920
|
},
|
|
921
|
+
"name": {},
|
|
888
922
|
"attributes": {}
|
|
889
923
|
},
|
|
890
924
|
"lt-toggle-group__option": {
|
|
@@ -30,7 +30,10 @@ export const elements: Elements = {
|
|
|
30
30
|
"description": "The control the field wires: an `<input>`, `<textarea>` or `<select>` with its `<option>`s. `type=\"hidden\"` does not count, and only the first one is wired. The template writes `for` on the label and `id` on the control, or wraps the control in the label.",
|
|
31
31
|
"content": "none",
|
|
32
32
|
"unique": true,
|
|
33
|
-
"stableId": true
|
|
33
|
+
"stableId": true,
|
|
34
|
+
"name": {
|
|
35
|
+
"after": "label"
|
|
36
|
+
}
|
|
34
37
|
},
|
|
35
38
|
"help": {
|
|
36
39
|
"selector": ".lt-help-text",
|
|
@@ -75,7 +78,8 @@ export const elements: Elements = {
|
|
|
75
78
|
"selector": "[role='tablist'], .lt-tabs__list",
|
|
76
79
|
"description": "The tab list, a `<ul>` where each `<li>` gets `role=\"presentation\"`. It needs a name, such as `aria-label`. When the server has written `role=\"tab\"` on the links, the list can also hold other links.",
|
|
77
80
|
"content": "free",
|
|
78
|
-
"unique": true
|
|
81
|
+
"unique": true,
|
|
82
|
+
"name": {}
|
|
79
83
|
},
|
|
80
84
|
"tab": {
|
|
81
85
|
"selector": "a[role='tab'][href^='#'], .lt-tabs__list a[href^='#']:not([role])",
|
|
@@ -87,7 +91,10 @@ export const elements: Elements = {
|
|
|
87
91
|
"selector": "[role='tabpanel'], .lt-tabs__panel:not([role])",
|
|
88
92
|
"description": "The content of one tab, with the id the link points to. The panel has the same name as the tab: the heading at the top of the panel is the name when it says the same as the tab.",
|
|
89
93
|
"content": "free",
|
|
90
|
-
"multiple": true
|
|
94
|
+
"multiple": true,
|
|
95
|
+
"name": {
|
|
96
|
+
"component": true
|
|
97
|
+
}
|
|
91
98
|
}
|
|
92
99
|
},
|
|
93
100
|
"events": {
|
|
@@ -127,6 +134,10 @@ export const elements: Elements = {
|
|
|
127
134
|
"content": "text",
|
|
128
135
|
"multiple": true
|
|
129
136
|
}
|
|
137
|
+
},
|
|
138
|
+
"name": {
|
|
139
|
+
"after": "title",
|
|
140
|
+
"id": true
|
|
130
141
|
}
|
|
131
142
|
},
|
|
132
143
|
"lt-popover": {
|
|
@@ -220,13 +231,19 @@ export const elements: Elements = {
|
|
|
220
231
|
"description": "The field the user types in: `role=\"combobox\"`, otherwise the first `<input>`. The template writes `for` on the label and `id` on the field, or wraps the field in the label.",
|
|
221
232
|
"content": "none",
|
|
222
233
|
"unique": true,
|
|
223
|
-
"stableId": true
|
|
234
|
+
"stableId": true,
|
|
235
|
+
"name": {
|
|
236
|
+
"after": "label"
|
|
237
|
+
}
|
|
224
238
|
},
|
|
225
239
|
"list": {
|
|
226
240
|
"selector": "[role='listbox'], .lt-suggestion__list",
|
|
227
241
|
"description": "The list of suggestions. It sits in the top layer when it is open, `popover=\"manual\"`, and has the label as its name.",
|
|
228
242
|
"content": "parts",
|
|
229
|
-
"unique": true
|
|
243
|
+
"unique": true,
|
|
244
|
+
"name": {
|
|
245
|
+
"component": true
|
|
246
|
+
}
|
|
230
247
|
},
|
|
231
248
|
"option": {
|
|
232
249
|
"selector": "[role='option'], .lt-suggestion__list > li:not([role])",
|
|
@@ -252,6 +269,34 @@ export const elements: Elements = {
|
|
|
252
269
|
"content": "none",
|
|
253
270
|
"unique": true,
|
|
254
271
|
"optional": true
|
|
272
|
+
},
|
|
273
|
+
"label": {
|
|
274
|
+
"selector": "label",
|
|
275
|
+
"description": "The label. The component writes `for` on it from the field's id when it does not wrap the field, and names the list after it.",
|
|
276
|
+
"content": "text",
|
|
277
|
+
"optional": true
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
"texts": {
|
|
281
|
+
"suggestionNone": {
|
|
282
|
+
"text": "No matches",
|
|
283
|
+
"replacedBy": [
|
|
284
|
+
"count-none",
|
|
285
|
+
"count-other"
|
|
286
|
+
]
|
|
287
|
+
},
|
|
288
|
+
"suggestionOne": {
|
|
289
|
+
"text": "One match",
|
|
290
|
+
"replacedBy": [
|
|
291
|
+
"count-one",
|
|
292
|
+
"count-other"
|
|
293
|
+
]
|
|
294
|
+
},
|
|
295
|
+
"suggestionOther": {
|
|
296
|
+
"text": "{n} matches",
|
|
297
|
+
"replacedBy": [
|
|
298
|
+
"count-other"
|
|
299
|
+
]
|
|
255
300
|
}
|
|
256
301
|
},
|
|
257
302
|
"events": {
|
|
@@ -281,7 +326,10 @@ export const elements: Elements = {
|
|
|
281
326
|
"selector": ":scope > dialog",
|
|
282
327
|
"description": "The `<dialog>` element, as a direct child of the host.",
|
|
283
328
|
"content": "free",
|
|
284
|
-
"unique": true
|
|
329
|
+
"unique": true,
|
|
330
|
+
"name": {
|
|
331
|
+
"after": "title"
|
|
332
|
+
}
|
|
285
333
|
},
|
|
286
334
|
"title": {
|
|
287
335
|
"selector": "h1, h2, h3, h4, h5, h6",
|
|
@@ -324,6 +372,21 @@ export const elements: Elements = {
|
|
|
324
372
|
}
|
|
325
373
|
},
|
|
326
374
|
"parts": {},
|
|
375
|
+
"texts": {
|
|
376
|
+
"toastRegion": {
|
|
377
|
+
"text": "Notifications",
|
|
378
|
+
"replacedBy": [
|
|
379
|
+
"label",
|
|
380
|
+
"aria-label"
|
|
381
|
+
]
|
|
382
|
+
},
|
|
383
|
+
"toastClose": {
|
|
384
|
+
"text": "Close message",
|
|
385
|
+
"replacedBy": [
|
|
386
|
+
"close-label"
|
|
387
|
+
]
|
|
388
|
+
}
|
|
389
|
+
},
|
|
327
390
|
"events": {
|
|
328
391
|
"toast-dismiss": {}
|
|
329
392
|
}
|
|
@@ -350,7 +413,10 @@ export const elements: Elements = {
|
|
|
350
413
|
"selector": "dialog",
|
|
351
414
|
"description": "The `<dialog>` element with the warning.",
|
|
352
415
|
"content": "free",
|
|
353
|
-
"unique": true
|
|
416
|
+
"unique": true,
|
|
417
|
+
"name": {
|
|
418
|
+
"after": "title"
|
|
419
|
+
}
|
|
354
420
|
},
|
|
355
421
|
"title": {
|
|
356
422
|
"selector": "h1, h2, h3, h4, h5, h6",
|
|
@@ -404,6 +470,20 @@ export const elements: Elements = {
|
|
|
404
470
|
}
|
|
405
471
|
},
|
|
406
472
|
"parts": {},
|
|
473
|
+
"texts": {
|
|
474
|
+
"connectionOffline": {
|
|
475
|
+
"text": "No connection. What you type is not being saved.",
|
|
476
|
+
"replacedBy": [
|
|
477
|
+
"offline-text"
|
|
478
|
+
]
|
|
479
|
+
},
|
|
480
|
+
"connectionOnline": {
|
|
481
|
+
"text": "Connection restored.",
|
|
482
|
+
"replacedBy": [
|
|
483
|
+
"online-text"
|
|
484
|
+
]
|
|
485
|
+
}
|
|
486
|
+
},
|
|
407
487
|
"events": {
|
|
408
488
|
"connection-lost": {},
|
|
409
489
|
"connection-restored": {}
|
package/src/vocabulary/types.ts
CHANGED
|
@@ -34,8 +34,29 @@ export type Part = {
|
|
|
34
34
|
optional?: true
|
|
35
35
|
/** The part must have an id from the server; the component never writes one. */
|
|
36
36
|
stableId?: true
|
|
37
|
+
/** LO-TEK demands a name for the part. */
|
|
38
|
+
name?: Name
|
|
37
39
|
}
|
|
38
40
|
|
|
41
|
+
/**
|
|
42
|
+
* A name LO-TEK demands where WAI-ARIA does not, or one the component gives
|
|
43
|
+
* itself. WAI-ARIA's own demands, by role, are in the core, and `lotek check`
|
|
44
|
+
* reports an element the markup gives no name (`without-name`).
|
|
45
|
+
*
|
|
46
|
+
* `after` is the part the component points `aria-labelledby` at when the
|
|
47
|
+
* markup has neither `aria-label` nor `aria-labelledby`, such as the heading
|
|
48
|
+
* of a dialog; then that part's name is enough. With `id` the part must have
|
|
49
|
+
* an id from the template, since the component does not write one. With
|
|
50
|
+
* `component` the component names it itself, after what the other rules
|
|
51
|
+
* check, such as the list in a suggestion field after the label, and no
|
|
52
|
+
* rule judges its name in the markup.
|
|
53
|
+
*
|
|
54
|
+
* Each of them is held to the component by a contract in
|
|
55
|
+
* `interfaces/scripts/accessibility/contracts.ts`: a mutation that takes the name away
|
|
56
|
+
* must fail in the browsers, and `lotek check` must report it.
|
|
57
|
+
*/
|
|
58
|
+
export type Name = { after?: string; id?: true; component?: true }
|
|
59
|
+
|
|
39
60
|
/**
|
|
40
61
|
* An event an element dispatches, such as `dialog-toggle`. `detail` is the
|
|
41
62
|
* fields in `event.detail` with their types, and is absent when the event
|
|
@@ -52,10 +73,35 @@ export type Element = {
|
|
|
52
73
|
/** Empty for the elements that create all of their content themselves. */
|
|
53
74
|
parts?: Record<string, Part>
|
|
54
75
|
events?: Record<string, ElementEvent>
|
|
76
|
+
/** LO-TEK demands a name for the element itself. */
|
|
77
|
+
name?: Name
|
|
78
|
+
/** The texts the element writes itself, by their name in `DEFAULT_TEXTS`. */
|
|
79
|
+
texts?: Record<string, DefaultText>
|
|
55
80
|
/** Attributes that have been removed, with what applies instead. */
|
|
56
81
|
removed?: Record<string, string>
|
|
57
82
|
}
|
|
58
83
|
|
|
84
|
+
/**
|
|
85
|
+
* A text the element writes itself when nobody has given it another, from
|
|
86
|
+
* `DEFAULT_TEXTS`. `replacedBy` is the attributes that replace it; any one
|
|
87
|
+
* of them is enough, and `lotek check` warns when none is there on a page in
|
|
88
|
+
* another language than the text's.
|
|
89
|
+
*/
|
|
90
|
+
export type DefaultText = { text: string; replacedBy: readonly string[] }
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* A text the stylesheet shows in `::after` on an element with the class and
|
|
94
|
+
* `attribute`, with `value` when the selector requires one, and none of the
|
|
95
|
+
* attributes in `unless`. `variable` is the CSS variable that replaces it.
|
|
96
|
+
*/
|
|
97
|
+
export type CssText = {
|
|
98
|
+
variable: string
|
|
99
|
+
text: string
|
|
100
|
+
attribute: string
|
|
101
|
+
value?: string
|
|
102
|
+
unless?: readonly string[]
|
|
103
|
+
}
|
|
104
|
+
|
|
59
105
|
/** The content of `elements.ts`: tag to element. */
|
|
60
106
|
export type Elements = Record<string, Element>
|
|
61
107
|
|
|
@@ -88,6 +134,10 @@ export type ClassInfo = {
|
|
|
88
134
|
partOf?: string
|
|
89
135
|
/** The parts the markup consists of, for the classes with a fixed structure. */
|
|
90
136
|
parts?: Record<string, Part>
|
|
137
|
+
/** LO-TEK demands a name for the element with the class. */
|
|
138
|
+
name?: Name
|
|
139
|
+
/** The texts the stylesheet shows on it. */
|
|
140
|
+
texts?: readonly CssText[]
|
|
91
141
|
attributes: Record<string, ClassAttribute>
|
|
92
142
|
}
|
|
93
143
|
|
package/web-types.json
CHANGED