tosijs-ui 1.17.0-beta.4 → 1.17.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 +231 -66
- package/README.md +1 -1
- package/bin/make-icon-data.js +39 -4
- package/dist/ab-test.js +2 -2
- package/dist/affix.js +1 -1
- package/dist/carousel.d.ts +6 -1
- package/dist/carousel.js +32 -3
- package/dist/code-editor-cm.d.ts +2 -0
- package/dist/code-editor-cm.js +13 -2
- package/dist/code-editor.js +4 -0
- package/dist/crud.js +1 -1
- package/dist/data-table.d.ts +30 -0
- package/dist/data-table.js +205 -14
- package/dist/dialog.js +1 -1
- package/dist/diff.js +1 -1
- package/dist/doc-browser.js +31 -4
- package/dist/doc-system/example-policy.d.ts +15 -1
- package/dist/doc-system/example-policy.js +28 -0
- package/dist/doc-system/render.d.ts +21 -0
- package/dist/doc-system/render.js +55 -9
- package/dist/doc-system/site/check-examples-cli.js +1 -0
- package/dist/doc-system/site/check-examples.d.ts +18 -0
- package/dist/doc-system/site/check-examples.js +46 -3
- package/dist/doc-system/site/config-fingerprint.d.ts +1 -0
- package/dist/doc-system/site/config-fingerprint.js +33 -0
- package/dist/doc-system/site/dev-server.d.ts +1 -0
- package/dist/doc-system/site/dev-server.js +25 -0
- package/dist/doc-system/site/docs.d.ts +1 -0
- package/dist/doc-system/site/docs.js +1 -1
- package/dist/doc-system/site/generate-site.d.ts +11 -1
- package/dist/doc-system/site/generate-site.js +141 -16
- package/dist/doc-system/site/image-size.d.ts +8 -0
- package/dist/doc-system/site/image-size.js +72 -0
- package/dist/doc-system/site/make-llms-txt.d.ts +24 -11
- package/dist/doc-system/site/make-llms-txt.js +118 -93
- package/dist/doc-system/site/orchestrator.d.ts +8 -0
- package/dist/doc-system/site/orchestrator.js +112 -15
- package/dist/doc-system/site/page-dates.d.ts +8 -0
- package/dist/doc-system/site/page-dates.js +85 -0
- package/dist/doc-system/site/page-globals.d.ts +12 -1
- package/dist/doc-system/site/page-globals.js +26 -4
- package/dist/doc-system/site/page-metadata.d.ts +36 -0
- package/dist/doc-system/site/page-metadata.js +96 -0
- package/dist/doc-system/site/sections.js +27 -17
- package/dist/doc-system/site/site-config.d.ts +51 -10
- package/dist/filter-builder.js +4 -4
- package/dist/float.js +3 -3
- package/dist/form.js +1 -1
- package/dist/header.js +2 -2
- package/dist/icon-data.js +11 -11
- package/dist/icons.js +43 -5
- package/dist/iife.js +105 -105
- package/dist/iife.js.map +45 -44
- package/dist/layout.js +1 -1
- package/dist/live-example/component.d.ts +7 -0
- package/dist/live-example/component.js +158 -36
- package/dist/live-example/example-hooks.d.ts +55 -0
- package/dist/live-example/example-hooks.js +48 -0
- package/dist/live-example/execution.d.ts +8 -11
- package/dist/live-example/execution.js +60 -5
- package/dist/live-example/index.d.ts +5 -1
- package/dist/live-example/index.js +3 -1
- package/dist/live-example/insert-examples.d.ts +4 -0
- package/dist/live-example/insert-examples.js +42 -4
- package/dist/live-theme.js +4 -4
- package/dist/make-sorter.js +2 -1
- package/dist/mapbox.js +1 -1
- package/dist/markdown-viewer.js +1 -1
- package/dist/menu.d.ts +1 -0
- package/dist/menu.js +20 -2
- package/dist/month.js +9 -3
- package/dist/palette.d.ts +4 -2
- package/dist/palette.js +29 -14
- package/dist/password-strength.js +2 -2
- package/dist/rating.js +1 -1
- package/dist/rich-text.js +3 -0
- package/dist/router.js +1 -1
- package/dist/schema-form.d.ts +2 -0
- package/dist/schema-form.js +27 -3
- package/dist/select.d.ts +34 -1
- package/dist/select.js +111 -16
- package/dist/sizer.js +1 -1
- package/dist/tab-selector.d.ts +7 -5
- package/dist/tab-selector.js +46 -13
- package/dist/tag-list.js +11 -2
- package/dist/theme.js +1 -1
- package/dist/tooltip.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/llms.txt +95 -155
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,73 +1,88 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 1.17.0
|
|
4
|
-
|
|
5
|
-
>
|
|
6
|
-
>
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
> on 1.16.41. beta.2 was staged and never published; its notes follow.
|
|
28
|
-
|
|
29
|
-
- **The axe audit waits for a page marked `aria-busy`, and one slow page no longer ends it.** A
|
|
30
|
-
page that is still loading (a 3D scene fetching large models, say) marks an element
|
|
31
|
-
`aria-busy="true"`, the standard ARIA signal, and is waited for up to 30 seconds; other pages
|
|
32
|
-
are audited once they have stopped adding elements, or after five seconds. A page that never
|
|
33
|
-
loads, or is still busy at 30 seconds, is listed as not fully checked, and the build makes no
|
|
34
|
-
claim about it. Before, each page load waited for the network to go idle, so a page that kept
|
|
35
|
-
downloading for 30 seconds, or that polled, threw and ended the audit of every page. The doc
|
|
36
|
-
site reference shows a component setting and clearing `aria-busy`.
|
|
37
|
-
|
|
38
|
-
### 1.17.0-beta.2 (prerelease detail)
|
|
39
|
-
|
|
40
|
-
> Prerelease, published under the `beta` dist-tag: install with `tosijs-ui@beta`. `latest` stays
|
|
41
|
-
> on 1.16.41. Fixes from Learn 3D's first run of beta.1.
|
|
42
|
-
|
|
43
|
-
- **Accessibility mode: headings in a blockquote or list shift with the rest of the page
|
|
44
|
-
(#3576).** A sidebar's `> ####` under `###` sections stayed an `<h4>` under the new `<h2>`s, so
|
|
45
|
-
the build reported a skipped level and DAISY Ace failed the ePub on heading order. A heading
|
|
46
|
-
inside a blockquote still never becomes the page's title.
|
|
47
|
-
- **DAISY Ace is found on `PATH` (#3577).** The docs said `bun add -d @daisy/ace`, which brings
|
|
48
|
-
Electron and Puppeteer into the project, and their advisories then failed the build's own
|
|
49
|
-
dependency audit. Install it globally (`npm install -g @daisy/ace`) instead; the build looks in
|
|
50
|
-
the project first, then on `PATH`.
|
|
51
|
-
- **The axe audit is about twice as fast, and audits the page a reader gets (#3585).** Pages are
|
|
52
|
-
audited four at a time (this site: 80s to 43s). Each is audited once it stops adding elements,
|
|
53
|
-
rather than after a fixed 300ms, which on a busy machine caught pages half-built. And the
|
|
54
|
-
audit no longer starts the doc browser's background test runner, which runs on localhost and
|
|
55
|
-
never on a deployed site. `TOSIJS_A11Y_AUDIT=off` skips the audit and the Ace check for one
|
|
56
|
-
build while the mode stays on; the ePub then claims no conformance.
|
|
57
|
-
- **Section stubs are not written where they cannot be read, or mid-edit (#3584).** A page whose
|
|
58
|
-
`parent` names a missing doc gets a stub section doc in `sectionsDir`. When `sectionsDir` is
|
|
59
|
-
outside every `docPaths` entry, the build now warns and writes nothing, since the stub would
|
|
60
|
-
never be read back. Stubs are created only on the first build in a process, so a parent that
|
|
61
|
-
disappears for a second during a rename no longer leaves files behind. Each stub written is
|
|
62
|
-
named in the build output.
|
|
63
|
-
- **`preview.host` is optional, and the preview docs no longer say `host` is required (#3586).**
|
|
64
|
-
The type has allowed a config with only `preview.tunnel` since 1.10.0, but the doc comment and
|
|
65
|
-
the reference table still said so. `as any` casts written for it can go.
|
|
3
|
+
## 1.17.0
|
|
4
|
+
|
|
5
|
+
> Accessibility and SEO for doc sites, and the components themselves passing WCAG 2.2 AA. A doc
|
|
6
|
+
> site can now be built to a stated accessibility level, with an accessible ePub, and every page
|
|
7
|
+
> carries share images, structured data and an llms.txt worth reading. Live examples can run
|
|
8
|
+
> under a Content Security Policy with no `'unsafe-eval'`. `<tosi-table>` gains elastic columns,
|
|
9
|
+
> and the icon generator keeps open paths open. Released as five betas; this section folds them
|
|
10
|
+
> together.
|
|
11
|
+
>
|
|
12
|
+
> **`dist/iife.js` grew 505.2 kB → 509.5 kB gzip (+4.3 kB, +0.9%)**, measured with `gzip -9`
|
|
13
|
+
> against 1.16.41. The ESM entry points pay only for what they import.
|
|
14
|
+
|
|
15
|
+
**Visible changes.** Nothing an adopter must change, but these look or behave differently:
|
|
16
|
+
|
|
17
|
+
- An editable `<tosi-select>` looks like a text field rather than a button, because it is one.
|
|
18
|
+
- `<tosi-month>` uses mediumvioletred where it used hotpink, which failed contrast;
|
|
19
|
+
`--month-day-color` and `--month-date-checked-background` restore the old colour.
|
|
20
|
+
- `<tosi-carousel>`'s dots are 24px apart rather than 16px.
|
|
21
|
+
- An icon whose classes are both `stroked filled` now draws its outline, over a knockout fill
|
|
22
|
+
(`--tosi-icon-knockout`, default `--tosi-bg`). The `filled` class used to win and remove every
|
|
23
|
+
stroke.
|
|
24
|
+
- The doc site header's site name is a `<span class="site-name">`, not an `<h2>`: site CSS that
|
|
25
|
+
styled `header h2` should target `header .site-name`.
|
|
26
|
+
- A section page's `<!-- toc -->` list is no longer written into its source file.
|
|
66
27
|
|
|
67
|
-
###
|
|
28
|
+
### Security
|
|
68
29
|
|
|
69
|
-
|
|
70
|
-
|
|
30
|
+
- **Image alt and title text are escaped in rendered pages.** marked wrote alt text into the
|
|
31
|
+
attribute as it was, so a `"` ended it. An ordinary caption (`A sign reading "Open"`) broke the
|
|
32
|
+
tag in every release that renders markdown images. In the 1.17 betas, alt text from an
|
|
33
|
+
`altText` hook, which is machine-generated and so untrusted, could inject markup such as a live
|
|
34
|
+
`<img onerror>`. **Affected:** 1.17.0-beta.1 through beta.5 with an `altText` hook (author
|
|
35
|
+
markdown with a `"` in its alt text rendered a broken tag in every earlier version, but that
|
|
36
|
+
text is the site author's own).
|
|
37
|
+
- **What a `setExampleHooks` `sanitize` hook returns is what the preview gets.** The betas
|
|
38
|
+
serialized the hook's fragment and parsed it again, and HTML does not survive that round trip
|
|
39
|
+
through MathML or SVG: markup the hook had judged harmless could come back as a live
|
|
40
|
+
`<img onerror>` (shown in Chromium, Firefox and WebKit). The fragment is now inserted as it is.
|
|
41
|
+
**Affected:** 1.17.0-beta.5, on pages that register a `sanitize` hook.
|
|
42
|
+
|
|
43
|
+
The 1.17.0 betas are deprecated on npm with a message pointing here; upgrade to 1.17.0.
|
|
44
|
+
|
|
45
|
+
### Accessibility: the components pass axe's WCAG 2.2 AA rules
|
|
46
|
+
|
|
47
|
+
The doc site's accessibility audit found 142 failures across 75 pages, most of them in
|
|
48
|
+
components every adopter ships. A new Playwright spec holds 20 component pages, examples
|
|
49
|
+
included, at zero.
|
|
50
|
+
|
|
51
|
+
- **`<tosi-table>` is a grid of rows (#3570).** Its scroll area is `role="grid"` and every row
|
|
52
|
+
`role="row"`. It was a list of list items holding grid cells, which a screen reader announced
|
|
53
|
+
as a list of unnamed items. A custom `dataCell` gets `role="gridcell"` like the table's own
|
|
54
|
+
cells, unless it carries a role of its own, and an expanded row's detail is a full-width
|
|
55
|
+
`gridcell` rather than a `region`, because a row may only contain cells.
|
|
56
|
+
- **`<tosi-tag-list>`'s chips are list items**, and an empty tag list is no longer an empty list.
|
|
57
|
+
- **`<tosi-select>` no longer puts its input inside its button (#3571).** A select you pick from
|
|
58
|
+
is its button, which is the combobox and shows the caption as text; an editable one is its
|
|
59
|
+
input, in a field beside the button. The combobox is named by the host's `aria-label` or
|
|
60
|
+
`title`, its `<label>`, or the placeholder, and ↓ opens the list.
|
|
61
|
+
- **`<tosi-tabs>` (#3572):** the tab row is the `tablist` and each body a `tabpanel`; a tab
|
|
62
|
+
points at its panel through `ariaControlsElements` (an id cannot cross the shadow root), and
|
|
63
|
+
`aria-selected` is `"true"` or absent rather than empty. The close glyph is no longer a button
|
|
64
|
+
inside the tab: Delete or Backspace closes a closeable tab from the keyboard, and the glyph
|
|
65
|
+
keeps a 24px pointer target.
|
|
66
|
+
- **Names for icon-only controls.** An icon-only `<tosi-menu>`'s trigger is named by the host's
|
|
67
|
+
`aria-label` or `title`, and says it opens a menu. `<tosi-month>`'s header buttons and
|
|
68
|
+
month/year selects have names. `<tosi-code>`'s editable area is named (the host's `aria-label`
|
|
69
|
+
or `title`, else "<mode> code"). `<tosi-theme-editor>`'s inputs and the filter builder's
|
|
70
|
+
controls are named. `<tosi-schema-form>`'s labels are tied to their controls (a plugin's
|
|
71
|
+
through its first input), so every field has a name.
|
|
72
|
+
- **Contrast.** `<tosi-month>`'s day headings and checked dates use mediumvioletred (5:1)
|
|
73
|
+
instead of hotpink (2.6:1); `--month-day-color` and `--month-date-checked-background` restore
|
|
74
|
+
the old colour. `<tosi-code>`'s light theme's type names are #075 instead of CodeMirror's #085
|
|
75
|
+
(4.43:1). `<tosi-palette>`'s trigger text is #0009 instead of #0008, just under 4.5:1 on a
|
|
76
|
+
near-white field.
|
|
77
|
+
- **Targets and keyboard.** `<tosi-carousel>`'s dots sit 24px apart (WCAG 2.5.8), and its slide
|
|
78
|
+
strip takes focus, with ← and → paging it (#3573). `<tosi-rich-text>`'s toolbar buttons are
|
|
79
|
+
at least 24px, and a live example's scrolling test results take focus.
|
|
80
|
+
- The doc examples name their controls and use colours that pass AA (#3574).
|
|
81
|
+
- **Enter opens a `<tosi-select>` you pick from**, like Space and ↓. (beta.5 cancelled it.)
|
|
82
|
+
- **`<tosi-table>` gives `role="row"` only to its own rows**: a list inside a cell keeps its list
|
|
83
|
+
items.
|
|
84
|
+
|
|
85
|
+
### Accessibility mode for doc sites
|
|
71
86
|
|
|
72
87
|
- **An opt-in accessibility mode for doc sites (#3521).** `accessibility: 'wcag22-aa'` in the
|
|
73
88
|
site config makes the build do what it can decide on its own and report what it cannot, on the
|
|
@@ -108,6 +123,156 @@
|
|
|
108
123
|
- **The header's site name is no longer a heading.** It was an `<h2>` above every page's own
|
|
109
124
|
`<h1>`, so it was each page's first heading. It is now `<span class="site-name">` and looks the
|
|
110
125
|
same; site CSS that styled `header h2` should target `header .site-name`.
|
|
126
|
+
- **Accessibility mode: headings in a blockquote or list shift with the rest of the page
|
|
127
|
+
(#3576).** A sidebar's `> ####` under `###` sections stayed an `<h4>` under the new `<h2>`s, so
|
|
128
|
+
the build reported a skipped level and DAISY Ace failed the ePub on heading order. A heading
|
|
129
|
+
inside a blockquote still never becomes the page's title.
|
|
130
|
+
- **DAISY Ace is found on `PATH` (#3577).** The docs said `bun add -d @daisy/ace`, which brings
|
|
131
|
+
Electron and Puppeteer into the project, and their advisories then failed the build's own
|
|
132
|
+
dependency audit. Install it globally (`npm install -g @daisy/ace`) instead; the build looks in
|
|
133
|
+
the project first, then on `PATH`.
|
|
134
|
+
- **The axe audit is about twice as fast, and audits the page a reader gets (#3585).** Pages are
|
|
135
|
+
audited four at a time (this site: 80s to 43s). Each is audited once it stops adding elements,
|
|
136
|
+
rather than after a fixed 300ms, which on a busy machine caught pages half-built. And the
|
|
137
|
+
audit no longer starts the doc browser's background test runner, which runs on localhost and
|
|
138
|
+
never on a deployed site. `TOSIJS_A11Y_AUDIT=off` skips the audit and the Ace check for one
|
|
139
|
+
build while the mode stays on; the ePub then claims no conformance.
|
|
140
|
+
- **Section stubs are not written where they cannot be read, or mid-edit (#3584).** A page whose
|
|
141
|
+
`parent` names a missing doc gets a stub section doc in `sectionsDir`. When `sectionsDir` is
|
|
142
|
+
outside every `docPaths` entry, the build now warns and writes nothing, since the stub would
|
|
143
|
+
never be read back. Stubs are created only on the first build in a process, so a parent that
|
|
144
|
+
disappears for a second during a rename no longer leaves files behind. Each stub written is
|
|
145
|
+
named in the build output.
|
|
146
|
+
- **`preview.host` is optional, and the preview docs no longer say `host` is required (#3586).**
|
|
147
|
+
The type has allowed a config with only `preview.tunnel` since 1.10.0, but the doc comment and
|
|
148
|
+
the reference table still said so. `as any` casts written for it can go.
|
|
149
|
+
- **The axe audit waits for a page marked `aria-busy`, and one slow page no longer ends it.** A
|
|
150
|
+
page that is still loading (a 3D scene fetching large models, say) marks an element
|
|
151
|
+
`aria-busy="true"`, the standard ARIA signal, and is waited for up to 30 seconds; other pages
|
|
152
|
+
are audited once they have stopped adding elements, or after five seconds. A page that never
|
|
153
|
+
loads, or is still busy at 30 seconds, is listed as not fully checked, and the build makes no
|
|
154
|
+
claim about it. Before, each page load waited for the network to go idle, so a page that kept
|
|
155
|
+
downloading for 30 seconds, or that polled, threw and ended the audit of every page. The doc
|
|
156
|
+
site reference shows a component setting and clearing `aria-busy`.
|
|
157
|
+
- **Every doc page can be scrolled by keyboard, and has a main landmark (#3575).** A page of
|
|
158
|
+
plain prose had nothing to tab to inside its scrolling content, so a keyboard user could not
|
|
159
|
+
scroll it, which axe reports as `scrollable-region-focusable` (Learn 3D: 71 of 126 pages). The
|
|
160
|
+
content scroller is now focusable, and it is the page's main landmark, which the doc site did not
|
|
161
|
+
have at all: a screen reader's "jump to main content" now works. A doc browser embedded in
|
|
162
|
+
another page stays focusable without claiming that page's main landmark.
|
|
163
|
+
- **`buildSite` says it needs `happy-dom` before it starts (#3600).** Without it, the build died
|
|
164
|
+
partway through with "Cannot find package 'happy-dom'" from a file inside tosijs-ui. It now
|
|
165
|
+
stops before writing anything and prints the install command. `happy-dom` stays an optional
|
|
166
|
+
peer: a project that only uses the components never needs it.
|
|
167
|
+
- **TJS's own doc comments, `/# … #/`, become documentation (#3601).** In `.tjs` and `.ajs`
|
|
168
|
+
files they are read in source order with any `/*#` blocks. tjs-lang finds them, so its grammar
|
|
169
|
+
applies exactly; that needs a tjs-lang that exports `findDocCommentSpans` (requested). With an
|
|
170
|
+
older one, the build names each file whose `/#` comments it could not read, instead of
|
|
171
|
+
dropping the page silently. `.ajs` files are now scraped for `/*#` blocks too.
|
|
172
|
+
|
|
173
|
+
### Live examples under a strict CSP
|
|
174
|
+
|
|
175
|
+
- **`liveExamples: 'no-code'` (tosijs-ui#246):** only `html` and `css` fences run; script,
|
|
176
|
+
dialect and `test` fences are shown as highlighted code. Nothing on a no-code example's path
|
|
177
|
+
constructs a `Function` or calls `eval` (no Console tab, since its REPL evaluates), so a doc
|
|
178
|
+
system served under a CSP without `'unsafe-eval'` runs its examples.
|
|
179
|
+
- **`setExampleHooks({ sanitize, hydrate, chat })`** from `tosijs-ui/live-example`:
|
|
180
|
+
`sanitize(fragment, example)` sees the markup parsed but inert before it enters the preview;
|
|
181
|
+
`hydrate(preview, signal, example)` runs once it is in (after any script), with a signal that
|
|
182
|
+
aborts on the next run; `chat(session)` builds a Chat tab whose `session.apply({ html, css })`
|
|
183
|
+
runs like an edit. They apply in every mode.
|
|
184
|
+
- **`exampleTabs`** in the site config, and `{"tabs": [...]}` per fence, choose the code panel's
|
|
185
|
+
tabs from `js`, `html`, `css`, `test`, `console`, `chat`. Under no-code the default is
|
|
186
|
+
`['html', 'css', 'chat']`. A misspelt tab fails the build by name.
|
|
187
|
+
- **`setExamplePolicy` and `setExampleTabs` are exported** from `tosijs-ui/live-example`; the
|
|
188
|
+
first was documented as callable but never exported.
|
|
189
|
+
- **`exampleModules: true` (tosijs-ui#245):** the build writes each script example (`js`, `ts`,
|
|
190
|
+
`tjs`) to `<outputDir>/_examples/<hash>.js`, and the page runs an unedited inline example by
|
|
191
|
+
`import()`-ing its module instead of compiling its source, so it runs under
|
|
192
|
+
`script-src 'self'` with no `'unsafe-eval'`. The module's lines are the example's own, so an
|
|
193
|
+
error still names its line. Under such a policy, an EDITED example (which must compile) says
|
|
194
|
+
the policy refused it and that reverting runs the published example, instead of an engine
|
|
195
|
+
message about `'unsafe-eval'`.
|
|
196
|
+
|
|
197
|
+
### The doc site's SEO surface
|
|
198
|
+
|
|
199
|
+
- **Share images (#3562).** A page's share image (og:image, twitter:image) is its own `image`,
|
|
200
|
+
else its card at `/og/<slug>.webp|png|jpg` when the static files have one, else the site's
|
|
201
|
+
`ogImage`, else the home page's card. The cards `bun run og` wrote were linked from no page,
|
|
202
|
+
so every share unfurled without an image. A local share image gets `og:image:width`/`height`,
|
|
203
|
+
read from its header (PNG, WebP, JPEG, GIF), and every one gets an alt of the page's title.
|
|
204
|
+
- **`bun run og`** cards only the home page and pages with a live example and no `image` of
|
|
205
|
+
their own; every other page shares the home page's card instead of getting a text-only one.
|
|
206
|
+
It encodes with cwebp (`brew install webp`): Homebrew's ffmpeg 8 has no webp encoder, so every
|
|
207
|
+
card failed to encode. A card with an example screenshot gives its title and description the
|
|
208
|
+
left column (they ran under the shot) and captures the preview without the example's toolbar,
|
|
209
|
+
and a page whose example cannot be captured now fails the run (exit 1) instead of quietly
|
|
210
|
+
getting a text-only card.
|
|
211
|
+
- **`sitemap.xml` entries carry `lastmod` (#3565):** the last commit that touched the page's
|
|
212
|
+
source, or its mtime while it has uncommitted edits. Without git there is none, rather than
|
|
213
|
+
an invented one.
|
|
214
|
+
- **JSON-LD names the page properly** (its headTitle without the project suffix), with
|
|
215
|
+
`dateModified`, `datePublished` (frontmatter `date`) and `author` (the page's, else
|
|
216
|
+
`epub.author`); a page inside a nav section gets a `BreadcrumbList`; the home page is the
|
|
217
|
+
`WebSite` rather than a `TechArticle`.
|
|
218
|
+
- **`kind: 'book'`** in the site config: pages become `Chapter`s of a `Book`, numbered in
|
|
219
|
+
reading order, and link the previous and next page with `<link rel="prev/next">`.
|
|
220
|
+
- **`llms.txt` follows llmstxt.org (#3564):** an H1, the site description as a `>` summary,
|
|
221
|
+
then `- [title](url): description` lines in nav order, with each nav section as its own `##`
|
|
222
|
+
section. Links are the pages' markdown copies, and descriptions are the ones the pages' heads
|
|
223
|
+
carry. **`llms-full.txt`** is the whole indexed corpus as one markdown file, in nav order,
|
|
224
|
+
each page followed by its URL, written to the output dir only.
|
|
225
|
+
- **The metadata lint (#3563):** every build lists pages whose title or description needs
|
|
226
|
+
writing — missing, too short or long, derived from a paragraph cut mid-sentence, or shared
|
|
227
|
+
with another page. It warns (once per change under `bun start`) and fails a `strict` build.
|
|
228
|
+
A description derived from a page's first paragraph no longer keeps `_emphasis_`,
|
|
229
|
+
`~~strikethrough~~`, wikilinks or footnote markers, and is cut at 155 characters, where
|
|
230
|
+
search results cut it.
|
|
231
|
+
- **`bun run og` no longer stops the dev server it captures from.** It wrote each card into the
|
|
232
|
+
watched `demo/static/og/` as it went, and the server's rebuild-loop guard shut the server down
|
|
233
|
+
part way through; cards are now written elsewhere and copied in at the end. It also removes
|
|
234
|
+
haltija's dev widget before capturing, which sat in the corner of every card.
|
|
235
|
+
|
|
236
|
+
### Components
|
|
237
|
+
|
|
238
|
+
- **Elastic table columns (snowfox, #3858).** A `<tosi-table>` column with `elastic: true` takes
|
|
239
|
+
a share of the space left over when the columns add up to less than the table's width, in
|
|
240
|
+
proportion to its `width`, and never shrinks below it, so a narrow table still scrolls. The
|
|
241
|
+
table's `elastic` attribute makes every unpinned column elastic unless it says
|
|
242
|
+
`elastic: false`, which covers columns inferred from the data. Pinned columns are never
|
|
243
|
+
elastic, and elastic columns take precedence over `full-width-header`. Dragging an elastic
|
|
244
|
+
column's edge keeps the edge under the pointer, and a stretched column's edge can be grabbed
|
|
245
|
+
where it is drawn.
|
|
246
|
+
- **`--tosi-table-fill`** paints the space to the right of a table's columns when they don't
|
|
247
|
+
fill it. Transparent by default.
|
|
248
|
+
- **`<tosi-palette>`'s `localizer` localizes every caption the palette owns (tosijs-ui#247):** the
|
|
249
|
+
footer's Navigate, Select and Close, the dialog's Search and the clear button's Clear names,
|
|
250
|
+
`emptyCaption` and `quickLinksCaption`, not only the placeholder.
|
|
251
|
+
- **`tosijs-make-icons` keeps open paths open (tosijs-ui#249).** In a folder that is both stroked
|
|
252
|
+
and filled (`stroked/filled/`), an element's own `fill="none"`, or `fill:none` in its style, is
|
|
253
|
+
kept: those icons' fill is a knockout, and `fill="none"` is what keeps an arc or arrowhead
|
|
254
|
+
open. It also no longer swallows the rest of an icon after a `style` whose last fill or stroke
|
|
255
|
+
had no trailing `;`, and drops a style left empty. Checked against tosijs-3d's icons: the
|
|
256
|
+
output matches their post-pass, which can now go.
|
|
257
|
+
|
|
258
|
+
### Doc system and build
|
|
259
|
+
|
|
260
|
+
- **A memory-routed doc browser follows `/slug/` links in memory (tosijs-ui#243).** It resolved
|
|
261
|
+
only `?filename`, yet rewrote every internal link to `/slug/` itself, so every doc-to-doc link
|
|
262
|
+
in an embedded browser was a full page load. A `/slug/#heading` link scrolls to the heading, and
|
|
263
|
+
canonicalising a content link keeps its `#heading`; it used to drop it.
|
|
264
|
+
- **A build handed to a running dev server is refused when the server has a different site
|
|
265
|
+
config (#3772, tosijs-ui#241).** The server builds the config it was started with, so editing
|
|
266
|
+
the config used to produce a build of the old one that reported success. Now `bun run build`
|
|
267
|
+
says to restart the server. The dev server also watches the `bundleEntry` file, so editing it
|
|
268
|
+
rebuilds the hydration bundle.
|
|
269
|
+
- **`buildSite` no longer rewrites the `<!-- toc -->` block in a section's source `.md` on every
|
|
270
|
+
build (#3733),** which left every adopter with section pages a dirty tree after building. The
|
|
271
|
+
list of child pages is filled in the built page (and its book variant) only; a section with no
|
|
272
|
+
`<!-- toc -->` marker still gets the list at the end. A committed block's old list is harmless,
|
|
273
|
+
but can be emptied to the bare markers.
|
|
274
|
+
- **A `liveExamples` or `kind` value the build does not know fails the build**, naming the allowed
|
|
275
|
+
values. `'nocode'` silently ran every example, on a site meant to run none.
|
|
111
276
|
|
|
112
277
|
## 1.16.41
|
|
113
278
|
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# tosijs-ui
|
|
2
2
|
|
|
3
|
-
<!--{ "pin": "top", "order": 0, "layout": "full-width", "headTitle": "tosijs-ui — robust, standards-based web components", "description": "
|
|
3
|
+
<!--{ "pin": "top", "order": 0, "layout": "full-width", "headTitle": "tosijs-ui — robust, standards-based web components", "description": "Standards-based web components (data tables, dialogs, forms, rich text, carousels) built on tosijs: smaller and faster than React, with no virtual DOM.", "keywords": "web components, custom elements, tosijs, data table, dialog, form, rich text, no virtual dom" }-->
|
|
4
4
|
|
|
5
5
|
[ui.tosijs.net live demo](https://ui.tosijs.net) | [tosijs](https://tosijs.net) | [discord](https://discord.gg/ramJ9rgky5) | [github](https://github.com/tonioloewald/tosijs-ui#readme) | [npm](https://www.npmjs.com/package/tosijs-ui)
|
|
6
6
|
|
package/bin/make-icon-data.js
CHANGED
|
@@ -32,6 +32,9 @@ Folder names control CSS classes on the generated SVGs:
|
|
|
32
32
|
- `color/` — icons with baked-in colors (class `color`, fill/stroke preserved)
|
|
33
33
|
- `stroked/` — stroke-only icons (class `stroked`, fill styles removed)
|
|
34
34
|
- `filled/` — fill-only icons (class `filled`, stroke styles removed)
|
|
35
|
+
- a folder that is both (`stroked/filled/`) — classes `stroked filled`; fill colours are
|
|
36
|
+
removed (the renderer supplies the fill), but an element's own `fill="none"` (or
|
|
37
|
+
`fill:none` in its style) is kept, because that is what keeps an arc or arrowhead open
|
|
35
38
|
|
|
36
39
|
### Directional folders
|
|
37
40
|
|
|
@@ -195,6 +198,9 @@ function getDirectionConfig(dir) {
|
|
|
195
198
|
return DIRECTION_FOLDERS[dirName] || null
|
|
196
199
|
}
|
|
197
200
|
|
|
201
|
+
// Stands in for an element's `fill="none"` while the strips run (see keepsOpenPaths).
|
|
202
|
+
const OPEN_PATH_MARK = 'data-tosi-open-path'
|
|
203
|
+
|
|
198
204
|
function generateDirectionalRedirects(name, dirConfig) {
|
|
199
205
|
// Find the base direction word in the camelCase name
|
|
200
206
|
const baseDir = dirConfig.base
|
|
@@ -239,7 +245,28 @@ function findIcons(dirs, ignore = []) {
|
|
|
239
245
|
.replace(/-([a-z0-9])/g, (_, char) => char.toLocaleUpperCase())
|
|
240
246
|
)
|
|
241
247
|
const name = names[0]
|
|
242
|
-
|
|
248
|
+
/*
|
|
249
|
+
In a folder that is BOTH stroked and filled, a fill is a knockout (the renderer sets
|
|
250
|
+
it on the root) and an element's own `fill="none"` is what keeps a path OPEN: an arc,
|
|
251
|
+
an arrowhead. Every strip below removes fills, so such an element filled with the
|
|
252
|
+
knockout colour, and an open arc painted a lens over whatever it crossed
|
|
253
|
+
(tosijs-ui#249). Mark those elements first; the mark survives the strips and becomes
|
|
254
|
+
`fill="none"` again at the end. The root <svg> is not an element here: its fill is
|
|
255
|
+
the folder's to decide.
|
|
256
|
+
*/
|
|
257
|
+
const keepsOpenPaths = dir.includes('stroked') && dir.includes('filled')
|
|
258
|
+
let svgSource = (
|
|
259
|
+
keepsOpenPaths
|
|
260
|
+
? content.replace(/<(?!svg\b)(\w+)\b[^>]*>/g, (tag) =>
|
|
261
|
+
/\bfill="none"|\bfill\s*:\s*none/.test(tag)
|
|
262
|
+
? tag
|
|
263
|
+
.replace(/\s?\bfill="none"/, '')
|
|
264
|
+
.replace(/\bfill\s*:\s*none\s*;?/, '')
|
|
265
|
+
.replace(/^<\w+/, (open) => `${open} ${OPEN_PATH_MARK}`)
|
|
266
|
+
: tag
|
|
267
|
+
)
|
|
268
|
+
: content
|
|
269
|
+
)
|
|
243
270
|
.replace(/(<\?xml.*?>|<!DOCTYPE.*?>)\s?/g, '')
|
|
244
271
|
.replace(/<svg.*?>/, (a) =>
|
|
245
272
|
a.replace(
|
|
@@ -280,7 +307,7 @@ function findIcons(dirs, ignore = []) {
|
|
|
280
307
|
out of the tinting path for an unrelated reason (tosijs-ui#30).
|
|
281
308
|
*/
|
|
282
309
|
svgSource = svgSource.replace(
|
|
283
|
-
/(fill|stroke)(?!-rule)(-\w+)?:[^;]+;?/g,
|
|
310
|
+
/(fill|stroke)(?!-rule)(-\w+)?:[^;"]+;?/g,
|
|
284
311
|
''
|
|
285
312
|
)
|
|
286
313
|
}
|
|
@@ -289,12 +316,20 @@ function findIcons(dirs, ignore = []) {
|
|
|
289
316
|
// survives every strip. `clip-rule` likewise.
|
|
290
317
|
if (dir.includes('stroked')) {
|
|
291
318
|
classes.push('stroked')
|
|
292
|
-
svgSource = svgSource.replace(/(fill)(?!-rule)(-\w+)?:[^;]+;?/g, '')
|
|
319
|
+
svgSource = svgSource.replace(/(fill)(?!-rule)(-\w+)?:[^;"]+;?/g, '')
|
|
293
320
|
}
|
|
294
321
|
if (dir.includes('filled')) {
|
|
295
322
|
classes.push('filled')
|
|
296
|
-
svgSource = svgSource.replace(
|
|
323
|
+
svgSource = svgSource.replace(
|
|
324
|
+
/(stroke)(?!-rule)(-\w+)?:[^;"]+;?/g,
|
|
325
|
+
''
|
|
326
|
+
)
|
|
327
|
+
}
|
|
328
|
+
if (keepsOpenPaths) {
|
|
329
|
+
svgSource = svgSource.replaceAll(OPEN_PATH_MARK, 'fill="none"')
|
|
297
330
|
}
|
|
331
|
+
// A style that held only colours is empty now.
|
|
332
|
+
svgSource = svgSource.replace(/\sstyle=""/g, '')
|
|
298
333
|
if (classes.length) {
|
|
299
334
|
svgSource = svgSource.replace(
|
|
300
335
|
/^<svg/,
|
package/dist/ab-test.js
CHANGED
|
@@ -66,7 +66,7 @@ randomize()
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
.preview tosi-ab[not] p {
|
|
69
|
-
background:
|
|
69
|
+
background: #c00;
|
|
70
70
|
}
|
|
71
71
|
```
|
|
72
72
|
|
|
@@ -75,7 +75,7 @@ randomize()
|
|
|
75
75
|
- `condition` attribute determines which value in `AbTest.conditions` controls the element
|
|
76
76
|
- `not` reverses the condition (so `<tosi-ab not condition="foo">` will be visible if `conditions.foo` is `false`)
|
|
77
77
|
*/
|
|
78
|
-
/*{ "parent": "Helper Libraries", "description": "<tosi-ab> shows or hides content by condition, so you can run A/B tests or feature flags by setting AbTest.conditions." }*/
|
|
78
|
+
/*{ "headTitle": "<tosi-ab> A/B tests and feature flags — tosijs-ui", "parent": "Helper Libraries", "description": "<tosi-ab> shows or hides content by condition, so you can run A/B tests or feature flags by setting AbTest.conditions." }*/
|
|
79
79
|
import { withAttributes } from 'tosijs';
|
|
80
80
|
const abTestConditions = {};
|
|
81
81
|
export class AbTest extends withAttributes({
|
package/dist/affix.js
CHANGED
|
@@ -142,7 +142,7 @@ and `describePlacement({ position, inside })` convert between the attribute and
|
|
|
142
142
|
`{ position, inside }`, and `affixCell(placement)` gives the grid cell and alignment a
|
|
143
143
|
placement takes.
|
|
144
144
|
*/
|
|
145
|
-
/*{ "parent": "Components", "description": "<tosi-affix> attaches a toolbar, badge or caption to one edge of its content, laid out beside it rather than floated, so it never covers it." }*/
|
|
145
|
+
/*{ "headTitle": "<tosi-affix> edge toolbars and badges — tosijs-ui", "parent": "Components", "description": "<tosi-affix> attaches a toolbar, badge or caption to one edge of its content, laid out beside it rather than floated, so it never covers it." }*/
|
|
146
146
|
import { Component, elements } from 'tosijs';
|
|
147
147
|
const { slot } = elements;
|
|
148
148
|
const POSITIONS = new Set([
|
package/dist/carousel.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ export declare class TosiCarousel extends TosiCarousel_base {
|
|
|
36
36
|
_carouseButtonWidth: number;
|
|
37
37
|
_carouselDotCurrentColor: string;
|
|
38
38
|
_carouselDotSize: number;
|
|
39
|
-
_carouselDotSpacing:
|
|
39
|
+
_carouselDotSpacing: number;
|
|
40
40
|
_carouselDotHitSize: number;
|
|
41
41
|
_carouselProgressPadding: number;
|
|
42
42
|
_carouselDotTransition: string;
|
|
@@ -127,6 +127,10 @@ export declare class TosiCarousel extends TosiCarousel_base {
|
|
|
127
127
|
':host .dot.current::before': {
|
|
128
128
|
background: string;
|
|
129
129
|
};
|
|
130
|
+
':host::part(scroller):focus-visible': {
|
|
131
|
+
outline: string;
|
|
132
|
+
outlineOffset: string;
|
|
133
|
+
};
|
|
130
134
|
':host .dot:focus-visible::before': {
|
|
131
135
|
boxShadow: string;
|
|
132
136
|
};
|
|
@@ -140,6 +144,7 @@ export declare class TosiCarousel extends TosiCarousel_base {
|
|
|
140
144
|
easing: (t: number) => number;
|
|
141
145
|
indicateCurrent: () => void;
|
|
142
146
|
snapPosition: () => void;
|
|
147
|
+
handleScrollerKey: (event: Event) => void;
|
|
143
148
|
back: () => void;
|
|
144
149
|
forward: () => void;
|
|
145
150
|
handleDotClick: (event: Event) => void;
|
package/dist/carousel.js
CHANGED
|
@@ -62,7 +62,9 @@ This is a minimalist carousel component that supports the usual stuff.
|
|
|
62
62
|
would ever end it.
|
|
63
63
|
- **The dots are tappable:** each draws a `--carousel-dot-size` dot (8px) but answers taps across
|
|
64
64
|
its whole slot and `--carousel-dot-hit-size` (44px) tall, so a tap that just misses a dot
|
|
65
|
-
doesn't open the slide underneath.
|
|
65
|
+
doesn't open the slide underneath. Dots sit 24px apart (`--carousel-dot-spacing`, 16px), the
|
|
66
|
+
spacing WCAG 2.5.8 asks of a target smaller than 24px.
|
|
67
|
+
- **The keyboard reaches the slides:** the slide strip takes focus, and ← and → page it.
|
|
66
68
|
- **Resizing keeps the current slide in place** (rotation, a window resize) instead of leaving
|
|
67
69
|
it partway into the next one.
|
|
68
70
|
|
|
@@ -173,7 +175,12 @@ export class TosiCarousel extends withAttributes({
|
|
|
173
175
|
_carouseButtonWidth: 48,
|
|
174
176
|
_carouselDotCurrentColor: '#0008',
|
|
175
177
|
_carouselDotSize: 8,
|
|
176
|
-
|
|
178
|
+
/*
|
|
179
|
+
16px of spacing puts the dots 24px apart: WCAG 2.5.8 takes a target under 24px as long
|
|
180
|
+
as a 24px circle on each one touches no neighbour, and at 16px apart they overlapped
|
|
181
|
+
(#3573).
|
|
182
|
+
*/
|
|
183
|
+
_carouselDotSpacing: 16,
|
|
177
184
|
// The tappable area around each dot; the dot itself stays --carousel-dot-size (#204).
|
|
178
185
|
_carouselDotHitSize: 44,
|
|
179
186
|
_carouselProgressPadding: 12,
|
|
@@ -276,6 +283,10 @@ export class TosiCarousel extends withAttributes({
|
|
|
276
283
|
':host .dot.current::before': {
|
|
277
284
|
background: vars.carouselDotCurrentColor,
|
|
278
285
|
},
|
|
286
|
+
':host::part(scroller):focus-visible': {
|
|
287
|
+
outline: `2px solid ${vars.carouselButtonActiveColor}`,
|
|
288
|
+
outlineOffset: '-2px',
|
|
289
|
+
},
|
|
279
290
|
':host .dot:focus-visible::before': {
|
|
280
291
|
boxShadow: `0 0 0 2px ${vars.carouselButtonActiveColor}`,
|
|
281
292
|
},
|
|
@@ -311,6 +322,18 @@ export class TosiCarousel extends withAttributes({
|
|
|
311
322
|
}
|
|
312
323
|
this.lastAutoAdvance = Date.now();
|
|
313
324
|
};
|
|
325
|
+
handleScrollerKey = (event) => {
|
|
326
|
+
if (event.target !== event.currentTarget)
|
|
327
|
+
return;
|
|
328
|
+
const { key } = event;
|
|
329
|
+
if (key === 'ArrowLeft')
|
|
330
|
+
this.back();
|
|
331
|
+
else if (key === 'ArrowRight')
|
|
332
|
+
this.forward();
|
|
333
|
+
else
|
|
334
|
+
return;
|
|
335
|
+
event.preventDefault();
|
|
336
|
+
};
|
|
314
337
|
back = () => {
|
|
315
338
|
this.page = this.page > 0 ? this.page - 1 : this.lastPage;
|
|
316
339
|
};
|
|
@@ -359,7 +382,12 @@ export class TosiCarousel extends withAttributes({
|
|
|
359
382
|
}
|
|
360
383
|
}
|
|
361
384
|
content = () => [
|
|
362
|
-
div({ part: 'pager' }, button({ title: 'previous slide', part: 'back' }, icons.chevronLeft()), div(
|
|
385
|
+
div({ part: 'pager' }, button({ title: 'previous slide', part: 'back' }, icons.chevronLeft()), div(
|
|
386
|
+
/*
|
|
387
|
+
Focusable, so the strip can be scrolled from the keyboard (#3573); ← and → page it,
|
|
388
|
+
like the arrow buttons.
|
|
389
|
+
*/
|
|
390
|
+
{ title: 'slides', role: 'group', part: 'scroller', tabindex: 0 }, div({ part: 'grid' }, slot())), button({ title: 'next slide', part: 'forward' }, icons.chevronRight())),
|
|
363
391
|
div({ title: 'choose slide to display', role: 'group', part: 'progress' }),
|
|
364
392
|
];
|
|
365
393
|
connectedCallback() {
|
|
@@ -371,6 +399,7 @@ export class TosiCarousel extends withAttributes({
|
|
|
371
399
|
back.addEventListener('click', this.back);
|
|
372
400
|
forward.addEventListener('click', this.forward);
|
|
373
401
|
scroller.addEventListener('scroll', this.indicateCurrent);
|
|
402
|
+
scroller.addEventListener('keydown', this.handleScrollerKey);
|
|
374
403
|
progress.addEventListener('click', this.handleDotClick);
|
|
375
404
|
this.addEventListener('pointerenter', this.handlePointerEnter);
|
|
376
405
|
this.addEventListener('pointerleave', this.handlePointerLeave);
|
package/dist/code-editor-cm.d.ts
CHANGED
|
@@ -53,6 +53,8 @@ export interface CmOptions {
|
|
|
53
53
|
onChange?: (value: string) => void;
|
|
54
54
|
/** style-injection root — pass the host's ShadowRoot when mounted in shadow DOM */
|
|
55
55
|
root?: Document | ShadowRoot;
|
|
56
|
+
/** the editable area's accessible name */
|
|
57
|
+
label?: string;
|
|
56
58
|
}
|
|
57
59
|
/** Create a CodeMirror editor mounted in `parent`, returning an editor-agnostic handle. */
|
|
58
60
|
export declare function createCmEditor(parent: HTMLElement, opts?: CmOptions): CmHandle;
|
package/dist/code-editor-cm.js
CHANGED
|
@@ -13,7 +13,7 @@ layered in separately and only when tjs-lang is installed.
|
|
|
13
13
|
import { EditorView, keymap, lineNumbers, highlightActiveLineGutter, highlightSpecialChars, drawSelection, dropCursor, rectangularSelection, crosshairCursor, highlightActiveLine, tooltips, } from '@codemirror/view';
|
|
14
14
|
import { EditorState, Compartment, Annotation, Transaction, } from '@codemirror/state';
|
|
15
15
|
import { indentWithTab, history, defaultKeymap, historyKeymap, undo, redo, undoDepth, redoDepth, } from '@codemirror/commands';
|
|
16
|
-
import { indentUnit, foldGutter, foldKeymap, indentOnInput, syntaxHighlighting, defaultHighlightStyle, bracketMatching, } from '@codemirror/language';
|
|
16
|
+
import { indentUnit, foldGutter, foldKeymap, indentOnInput, syntaxHighlighting, defaultHighlightStyle, HighlightStyle, bracketMatching, } from '@codemirror/language';
|
|
17
17
|
import { closeBrackets, closeBracketsKeymap, autocompletion, completionKeymap, } from '@codemirror/autocomplete';
|
|
18
18
|
import { searchKeymap, highlightSelectionMatches } from '@codemirror/search';
|
|
19
19
|
import { lintKeymap } from '@codemirror/lint';
|
|
@@ -44,9 +44,17 @@ const isDarkMode = () => typeof document !== 'undefined' &&
|
|
|
44
44
|
* semantic to preserve — and tightening it after 1.7 is on `latest` would be breaking.
|
|
45
45
|
*/
|
|
46
46
|
const programmatic = Annotation.define();
|
|
47
|
+
/*
|
|
48
|
+
CodeMirror's light style, with its one colour under WCAG AA's 4.5:1 darkened (#3572): type and
|
|
49
|
+
namespace names are #085, 4.43:1 on a near-white editor. #075 is 5.5:1 and reads the same.
|
|
50
|
+
*/
|
|
51
|
+
const AA_COLORS = { '#085': '#075' };
|
|
52
|
+
const lightHighlightStyle = HighlightStyle.define(defaultHighlightStyle.specs.map((spec) => typeof spec.color === 'string' && AA_COLORS[spec.color]
|
|
53
|
+
? { ...spec, color: AA_COLORS[spec.color] }
|
|
54
|
+
: spec));
|
|
47
55
|
const highlightFor = (dark) => dark
|
|
48
56
|
? syntaxHighlighting(oneDarkHighlightStyle)
|
|
49
|
-
: syntaxHighlighting(
|
|
57
|
+
: syntaxHighlighting(lightHighlightStyle, { fallback: true });
|
|
50
58
|
/** Map a `<tosi-code mode>` value to a CodeMirror language extension. */
|
|
51
59
|
export function languageForMode(mode) {
|
|
52
60
|
switch (mode) {
|
|
@@ -209,6 +217,9 @@ export function createCmEditor(parent, opts = {}) {
|
|
|
209
217
|
highlight.of(highlightFor(isDarkMode())),
|
|
210
218
|
language.of(langExt),
|
|
211
219
|
readonly.of(EditorState.readOnly.of(!!opts.readOnly)),
|
|
220
|
+
EditorView.contentAttributes.of({
|
|
221
|
+
'aria-label': opts.label || 'code editor',
|
|
222
|
+
}),
|
|
212
223
|
EditorView.updateListener.of((u) => {
|
|
213
224
|
if (!u.docChanged || !opts.onChange)
|
|
214
225
|
return;
|
package/dist/code-editor.js
CHANGED
|
@@ -409,6 +409,10 @@ export class CodeEditor extends withAttributes({
|
|
|
409
409
|
mode: this.mode,
|
|
410
410
|
readOnly: this.disabled,
|
|
411
411
|
root: this.shadowRoot ?? undefined,
|
|
412
|
+
// The editable area is what a screen reader reaches; the host's name is its name.
|
|
413
|
+
label: this.getAttribute('aria-label') ||
|
|
414
|
+
this.title ||
|
|
415
|
+
(this.mode ? `${this.mode} code` : ''),
|
|
412
416
|
onChange: (value) => this.dispatchEvent(new CustomEvent('change', { detail: { value } })),
|
|
413
417
|
});
|
|
414
418
|
this._handle = handle;
|
package/dist/crud.js
CHANGED
|
@@ -304,7 +304,7 @@ for every instance; each one re-checks it the next time it is resized.
|
|
|
304
304
|
- `change` — the selection or the saved record changed.
|
|
305
305
|
- `error` — a store operation failed.
|
|
306
306
|
*/
|
|
307
|
-
/*{ "parent": "Components", "description": "<tosi-crud> pairs a searchable table with a schema-driven form over a store you supply (REST, IndexedDB or an array) for list-and-edit screens." }*/
|
|
307
|
+
/*{ "headTitle": "<tosi-crud> list-and-edit screens — tosijs-ui", "parent": "Components", "description": "<tosi-crud> pairs a searchable table with a schema-driven form over a store you supply (REST, IndexedDB or an array) for list-and-edit screens." }*/
|
|
308
308
|
import { elements, withAttributes } from 'tosijs';
|
|
309
309
|
import { tosiTable } from './data-table.js';
|
|
310
310
|
import { tosiSchemaForm } from './schema-form.js';
|