tosijs-ui 1.17.0-beta.5 → 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 CHANGED
@@ -1,15 +1,46 @@
1
1
  # Changelog
2
2
 
3
- ## 1.17.0-beta.5
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.
4
27
 
5
- > Prerelease, published under the `beta` dist-tag: install with `tosijs-ui@beta`. `latest` stays
6
- > on 1.16.41. Accessibility fixes across the components, the doc site's SEO surface, and two
7
- > ways to run live examples under a strict Content Security Policy.
28
+ ### Security
8
29
 
9
- **Visible changes.** An editable `<tosi-select>` now looks like a text field rather than a
10
- button, because it is one. `<tosi-month>` uses mediumvioletred where it used hotpink, which
11
- failed contrast; its CSS variables restore the old colour. `<tosi-carousel>`'s dots are further
12
- apart. A section page's `<!-- toc -->` list is no longer written into its source file.
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.
13
44
 
14
45
  ### Accessibility: the components pass axe's WCAG 2.2 AA rules
15
46
 
@@ -47,6 +78,97 @@ included, at zero.
47
78
  strip takes focus, with ← and → paging it (#3573). `<tosi-rich-text>`'s toolbar buttons are
48
79
  at least 24px, and a live example's scrolling test results take focus.
49
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
86
+
87
+ - **An opt-in accessibility mode for doc sites (#3521).** `accessibility: 'wcag22-aa'` in the
88
+ site config makes the build do what it can decide on its own and report what it cannot, on the
89
+ site, in print and in the ePub:
90
+ - an image alone in its paragraph, followed by an italic-only paragraph, renders as a
91
+ `<figure>` with that text as its `<figcaption>`;
92
+ - every page has exactly one `<h1>`, its title: a page's first heading is promoted when its
93
+ title came from it, a later `#` becomes `##`, and the rest shift to start at `##`;
94
+ - the build lists, by file and line, each image with no alt text and no caption, each heading
95
+ that skips a level, and each link named "here" or the like, and fails on them under `strict`.
96
+
97
+ Off by default; a site that does not set it renders exactly as before.
98
+ - **The mode audits the built site with axe.** A full build opens every page in Chromium and runs
99
+ axe-core's WCAG 2.2 AA rules, listing each failure by page, rule and element and failing under
100
+ `strict`. It needs `playwright` and `axe-core` in your project; without them the build says the
101
+ audit did not run rather than reporting a pass. Never under a dev server.
102
+ - **Accessible ePubs (#3522).** In the mode, the book's package document declares its access
103
+ modes, features, hazards and a summary (EPUB Accessibility 1.1), derived from the build: it
104
+ claims alternative text only when every image has alt text or a caption. Conformance to WCAG
105
+ 2.2 AA is claimed only when DAISY Ace, installed in your project, has checked the finished book
106
+ and passed it. `epub: { accessibility: { summary, hazards, certifiedBy } }` overrides the
107
+ defaults. Checked against real Ace: this site's own book passes.
108
+ - **Every ePub, mode or not: the right language, readable links, landmarks.** Each chapter, the
109
+ nav, the contents and the cover said `xml:lang="en"` whatever the book's language, and the
110
+ package said none, so a reading system pronounced a French book as English. Links were
111
+ `#0088cc` (3.9:1 on white) and marked by colour alone; they are now 6.6:1 and underlined.
112
+ The nav gains a landmarks list (cover, contents, start of the text) and its table of contents
113
+ `role="doc-toc"`.
114
+ - **`altText`: a hook that supplies alt text for undescribed images.** With the mode on, it is
115
+ called for each image the build would report, and its answer becomes that image's alt text in
116
+ the built site, `docs.json` and the ePub. It never writes a source file. It runs on every
117
+ build, so cache anything slow by `src`.
118
+ - **The doc-site search trigger's name contains its visible text (#3569).** Its `aria-label`
119
+ was "Search (⌘K)" beside visible text "Search ⌘K", which fails WCAG 2.5.3 (a voice-control user
120
+ says what they see) on every page of every doc site. A `<tosi-palette>` field trigger is now
121
+ named by its text, an icon trigger keeps an `aria-label`, and the shortcut is announced through
122
+ `aria-keyshortcuts`. The frame's axe test now runs every WCAG 2.2 A and AA rule, not four.
123
+ - **The header's site name is no longer a heading.** It was an `<h2>` above every page's own
124
+ `<h1>`, so it was each page's first heading. It is now `<span class="site-name">` and looks the
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.
50
172
 
51
173
  ### Live examples under a strict CSP
52
174
 
@@ -106,123 +228,51 @@ included, at zero.
106
228
  A description derived from a page's first paragraph no longer keeps `_emphasis_`,
107
229
  `~~strikethrough~~`, wikilinks or footnote markers, and is cut at 155 characters, where
108
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.
109
235
 
110
- ### Build
111
-
112
- - **`buildSite` no longer rewrites the `<!-- toc -->` block in a section's source `.md` on
113
- every build (#3733),** which left every adopter with section pages a dirty tree after
114
- building. The list of child pages is filled in the built page (and its book variant) only; a
115
- section with no `<!-- toc -->` marker still gets the list at the end. A committed block's old
116
- list is harmless (the build replaces it), but can be emptied to the bare markers.
117
-
118
- ### 1.17.0-beta.4 (prerelease detail)
119
-
120
- > Prerelease, published under the `beta` dist-tag: install with `tosijs-ui@beta`. `latest` stays
121
- > on 1.16.41. Fixes from Learn 3D and from tosijs-native's first site build.
122
-
123
- - **Every doc page can be scrolled by keyboard, and has a main landmark (#3575).** A page of
124
- plain prose had nothing to tab to inside its scrolling content, so a keyboard user could not
125
- scroll it, which axe reports as `scrollable-region-focusable` (Learn 3D: 71 of 126 pages). The
126
- content scroller is now focusable, and it is the page's main landmark, which the doc site did not
127
- have at all: a screen reader's "jump to main content" now works. A doc browser embedded in
128
- another page stays focusable without claiming that page's main landmark.
129
- - **`buildSite` says it needs `happy-dom` before it starts (#3600).** Without it, the build died
130
- partway through with "Cannot find package 'happy-dom'" from a file inside tosijs-ui. It now
131
- stops before writing anything and prints the install command. `happy-dom` stays an optional
132
- peer: a project that only uses the components never needs it.
133
- - **TJS's own doc comments, `/# … #/`, become documentation (#3601).** In `.tjs` and `.ajs`
134
- files they are read in source order with any `/*#` blocks. tjs-lang finds them, so its grammar
135
- applies exactly; that needs a tjs-lang that exports `findDocCommentSpans` (requested). With an
136
- older one, the build names each file whose `/#` comments it could not read, instead of
137
- dropping the page silently. `.ajs` files are now scraped for `/*#` blocks too.
138
-
139
- ### 1.17.0-beta.3 (prerelease detail)
140
-
141
- > Prerelease, published under the `beta` dist-tag: install with `tosijs-ui@beta`. `latest` stays
142
- > on 1.16.41. beta.2 was staged and never published; its notes follow.
143
-
144
- - **The axe audit waits for a page marked `aria-busy`, and one slow page no longer ends it.** A
145
- page that is still loading (a 3D scene fetching large models, say) marks an element
146
- `aria-busy="true"`, the standard ARIA signal, and is waited for up to 30 seconds; other pages
147
- are audited once they have stopped adding elements, or after five seconds. A page that never
148
- loads, or is still busy at 30 seconds, is listed as not fully checked, and the build makes no
149
- claim about it. Before, each page load waited for the network to go idle, so a page that kept
150
- downloading for 30 seconds, or that polled, threw and ended the audit of every page. The doc
151
- site reference shows a component setting and clearing `aria-busy`.
152
-
153
- ### 1.17.0-beta.2 (prerelease detail)
154
-
155
- > Prerelease, published under the `beta` dist-tag: install with `tosijs-ui@beta`. `latest` stays
156
- > on 1.16.41. Fixes from Learn 3D's first run of beta.1.
157
-
158
- - **Accessibility mode: headings in a blockquote or list shift with the rest of the page
159
- (#3576).** A sidebar's `> ####` under `###` sections stayed an `<h4>` under the new `<h2>`s, so
160
- the build reported a skipped level and DAISY Ace failed the ePub on heading order. A heading
161
- inside a blockquote still never becomes the page's title.
162
- - **DAISY Ace is found on `PATH` (#3577).** The docs said `bun add -d @daisy/ace`, which brings
163
- Electron and Puppeteer into the project, and their advisories then failed the build's own
164
- dependency audit. Install it globally (`npm install -g @daisy/ace`) instead; the build looks in
165
- the project first, then on `PATH`.
166
- - **The axe audit is about twice as fast, and audits the page a reader gets (#3585).** Pages are
167
- audited four at a time (this site: 80s to 43s). Each is audited once it stops adding elements,
168
- rather than after a fixed 300ms, which on a busy machine caught pages half-built. And the
169
- audit no longer starts the doc browser's background test runner, which runs on localhost and
170
- never on a deployed site. `TOSIJS_A11Y_AUDIT=off` skips the audit and the Ace check for one
171
- build while the mode stays on; the ePub then claims no conformance.
172
- - **Section stubs are not written where they cannot be read, or mid-edit (#3584).** A page whose
173
- `parent` names a missing doc gets a stub section doc in `sectionsDir`. When `sectionsDir` is
174
- outside every `docPaths` entry, the build now warns and writes nothing, since the stub would
175
- never be read back. Stubs are created only on the first build in a process, so a parent that
176
- disappears for a second during a rename no longer leaves files behind. Each stub written is
177
- named in the build output.
178
- - **`preview.host` is optional, and the preview docs no longer say `host` is required (#3586).**
179
- The type has allowed a config with only `preview.tunnel` since 1.10.0, but the doc comment and
180
- the reference table still said so. `as any` casts written for it can go.
181
-
182
- ### 1.17.0-beta.1 (prerelease detail)
183
-
184
- > Prerelease, published under the `beta` dist-tag: install with `tosijs-ui@beta`. `latest` stays
185
- > on 1.16.41. It carries the accessibility half of 1.17.0; the SEO work and #245/#246 follow.
186
-
187
- - **An opt-in accessibility mode for doc sites (#3521).** `accessibility: 'wcag22-aa'` in the
188
- site config makes the build do what it can decide on its own and report what it cannot, on the
189
- site, in print and in the ePub:
190
- - an image alone in its paragraph, followed by an italic-only paragraph, renders as a
191
- `<figure>` with that text as its `<figcaption>`;
192
- - every page has exactly one `<h1>`, its title: a page's first heading is promoted when its
193
- title came from it, a later `#` becomes `##`, and the rest shift to start at `##`;
194
- - the build lists, by file and line, each image with no alt text and no caption, each heading
195
- that skips a level, and each link named "here" or the like, and fails on them under `strict`.
236
+ ### Components
196
237
 
197
- Off by default; a site that does not set it renders exactly as before.
198
- - **The mode audits the built site with axe.** A full build opens every page in Chromium and runs
199
- axe-core's WCAG 2.2 AA rules, listing each failure by page, rule and element and failing under
200
- `strict`. It needs `playwright` and `axe-core` in your project; without them the build says the
201
- audit did not run rather than reporting a pass. Never under a dev server.
202
- - **Accessible ePubs (#3522).** In the mode, the book's package document declares its access
203
- modes, features, hazards and a summary (EPUB Accessibility 1.1), derived from the build: it
204
- claims alternative text only when every image has alt text or a caption. Conformance to WCAG
205
- 2.2 AA is claimed only when DAISY Ace, installed in your project, has checked the finished book
206
- and passed it. `epub: { accessibility: { summary, hazards, certifiedBy } }` overrides the
207
- defaults. Checked against real Ace: this site's own book passes.
208
- - **Every ePub, mode or not: the right language, readable links, landmarks.** Each chapter, the
209
- nav, the contents and the cover said `xml:lang="en"` whatever the book's language, and the
210
- package said none, so a reading system pronounced a French book as English. Links were
211
- `#0088cc` (3.9:1 on white) and marked by colour alone; they are now 6.6:1 and underlined.
212
- The nav gains a landmarks list (cover, contents, start of the text) and its table of contents
213
- `role="doc-toc"`.
214
- - **`altText`: a hook that supplies alt text for undescribed images.** With the mode on, it is
215
- called for each image the build would report, and its answer becomes that image's alt text in
216
- the built site, `docs.json` and the ePub. It never writes a source file. It runs on every
217
- build, so cache anything slow by `src`.
218
- - **The doc-site search trigger's name contains its visible text (#3569).** Its `aria-label`
219
- was "Search (⌘K)" beside visible text "Search ⌘K", which fails WCAG 2.5.3 (a voice-control user
220
- says what they see) on every page of every doc site. A `<tosi-palette>` field trigger is now
221
- named by its text, an icon trigger keeps an `aria-label`, and the shortcut is announced through
222
- `aria-keyshortcuts`. The frame's axe test now runs every WCAG 2.2 A and AA rule, not four.
223
- - **The header's site name is no longer a heading.** It was an `<h2>` above every page's own
224
- `<h1>`, so it was each page's first heading. It is now `<span class="site-name">` and looks the
225
- same; site CSS that styled `header h2` should target `header .site-name`.
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.
226
276
 
227
277
  ## 1.16.41
228
278
 
@@ -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
- let svgSource = content
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(/(stroke)(?!-rule)(-\w+)?:[^;]+;?/g, '')
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/,
@@ -11,6 +11,13 @@ export interface ColumnOptions {
11
11
  align?: string;
12
12
  type?: ValueRendererType;
13
13
  pinned?: 'left' | 'right';
14
+ /**
15
+ * Whether this column takes a share of the space left over when the columns add up to
16
+ * less than the table's width. Elastic columns grow in proportion to their `width`, and
17
+ * never shrink below it. Defaults to the table's `elastic`. A pinned column is never
18
+ * elastic: its sticky offset is its width.
19
+ */
20
+ elastic?: boolean;
14
21
  sort?: false | 'ascending' | 'descending';
15
22
  /**
16
23
  * What this column SORTS by, when that differs from what it stores.
@@ -49,6 +56,19 @@ export interface ColumnOptions {
49
56
  }
50
57
  /** Builds the element shown under an expanded row. `null` means the row has no detail. */
51
58
  export type RowDetailFn = (row: any) => HTMLElement | null;
59
+ /**
60
+ * How a table's columns divide its width: the grid tracks, and the width each column is
61
+ * actually drawn at. Pure, so the grid (CSS) and the resize hit-test (JS) cannot disagree.
62
+ *
63
+ * When the columns add up to less than `available`, the leftover goes to the elastic
64
+ * columns in proportion to their widths, or, if there are none, to `stretchAt` (the
65
+ * `fullWidthHeader` column). Otherwise every column is drawn at its width.
66
+ */
67
+ export declare function columnLayout(widths: number[], elastic: boolean[], stretchAt: number, available: number): {
68
+ tracks: string[];
69
+ drawn: number[];
70
+ stretches: boolean;
71
+ };
52
72
  export interface TableData {
53
73
  columns?: ColumnOptions[] | null;
54
74
  array: any[];
@@ -81,6 +101,7 @@ declare const TosiTable_base: import("tosijs").WithAttributes<{
81
101
  nopreservescroll: boolean;
82
102
  editable: boolean;
83
103
  fullWidthHeader: boolean;
104
+ elastic: boolean;
84
105
  }>;
85
106
  export declare class TosiTable extends TosiTable_base {
86
107
  static preferredTagName: string;
@@ -100,6 +121,8 @@ export declare class TosiTable extends TosiTable_base {
100
121
  height: string;
101
122
  overflow: string;
102
123
  overscrollBehavior: string;
124
+ backgroundImage: string;
125
+ backgroundAttachment: string;
103
126
  };
104
127
  ':host .thead, :host .tbody': {
105
128
  display: string;
@@ -479,6 +502,11 @@ export declare class TosiTable extends TosiTable_base {
479
502
  private focusCell;
480
503
  private handleKeyNav;
481
504
  connectedCallback(): void;
505
+ /** Where `col`'s right edge is drawn, from the left of the columns. */
506
+ private drawnEdge;
507
+ private widthForEdge;
508
+ private isElastic;
509
+ private layoutColumns;
482
510
  setColumnWidths(): void;
483
511
  sortByColumn: (columnOptions: ColumnOptions, direction?: "ascending" | "descending" | "auto") => void;
484
512
  popColumnMenu: (target: HTMLElement, options: ColumnOptions) => void;