@inglorious/ui 9.8.0 → 9.8.2
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/package.json +8 -8
- package/src/controls/button/style.css +0 -2
- package/src/controls/button/template.js +2 -3
- package/src/controls/checkbox/style.css +0 -1
- package/src/controls/checkbox/template.js +0 -2
- package/src/controls/combobox/style.css +0 -14
- package/src/controls/combobox/template.js +0 -13
- package/src/controls/file-upload/template.js +1 -1
- package/src/controls/image-cropper/helpers.js +0 -2
- package/src/controls/image-cropper/image.js +0 -2
- package/src/controls/image-cropper/style.css +0 -6
- package/src/controls/image-cropper/template.js +3 -5
- package/src/controls/input/style.css +0 -1
- package/src/controls/radio-group/style.css +0 -2
- package/src/controls/rating/style.css +0 -3
- package/src/controls/select/style.css +0 -6
- package/src/controls/slider/style.css +0 -5
- package/src/controls/slider/template.js +0 -1
- package/src/controls/switch/style.css +0 -1
- package/src/controls/switch/template.js +0 -2
- package/src/controls/textarea/style.css +0 -2
- package/src/data-display/before-after/style.css +0 -4
- package/src/data-display/before-after/template.js +3 -3
- package/src/data-display/carousel/carousel.stories.js +0 -2
- package/src/data-display/carousel/handlers.js +0 -2
- package/src/data-display/carousel/style.css +0 -18
- package/src/data-display/carousel/template.js +0 -15
- package/src/data-display/chat/index.js +0 -1
- package/src/data-display/chat/style.css +0 -2
- package/src/data-display/chat/template.js +0 -1
- package/src/data-display/chip/template.js +0 -1
- package/src/data-display/data-grid/base.css +0 -2
- package/src/data-display/data-grid/handlers.js +1 -8
- package/src/data-display/data-grid/helpers.js +0 -5
- package/src/data-display/data-grid/template.js +0 -1
- package/src/data-display/data-grid/theme.css +0 -1
- package/src/data-display/icon/style.css +0 -7
- package/src/data-display/icon/template.js +2 -2
- package/src/data-display/table/style.css +0 -2
- package/src/data-display/tooltip/style.css +0 -3
- package/src/data-display/virtual-list/handlers.js +0 -2
- package/src/data-display/virtual-list/template.js +2 -4
- package/src/examples/dashboard/before-after-data.js +0 -3
- package/src/examples/dashboard/data.js +0 -1
- package/src/examples/dashboard/primitive-content.js +0 -2
- package/src/examples/dashboard/style.css +0 -3
- package/src/feedback/alert/style.css +0 -1
- package/src/feedback/dialog/dialog.stories.js +0 -4
- package/src/feedback/dialog/style.css +0 -10
- package/src/feedback/dialog/template.js +0 -5
- package/src/feedback/progress/style.css +0 -6
- package/src/feedback/progress/template.js +0 -3
- package/src/feedback/snackbar/snackbar.stories.js +0 -1
- package/src/feedback/snackbar/style.css +0 -10
- package/src/layout/flex/style.css +0 -2
- package/src/navigation/bottom-navigation/style.css +0 -7
- package/src/navigation/drawer/style.css +0 -21
- package/src/navigation/drawer/template.js +0 -2
- package/src/navigation/menu/menu.stories.js +0 -2
- package/src/navigation/menu/style.css +0 -4
- package/src/navigation/menu/template.js +0 -3
- package/src/navigation/speed-dial/style.css +0 -4
- package/src/navigation/speed-dial/template.js +0 -5
- package/src/navigation/tabs/template.js +0 -2
- package/src/navigation/view-transitions/index.js +0 -13
- package/src/navigation/view-transitions/style.css +0 -2
- package/src/shared/icons.js +0 -4
- package/src/styles/themes/bootstrap.css +0 -40
- package/src/styles/themes/inglorious.css +0 -21
- package/src/styles/themes/ios-18.css +0 -47
- package/src/styles/themes/ios-26.css +0 -55
- package/src/styles/themes/material-3.css +0 -52
- package/src/styles/themes/material-ui.css +0 -43
- package/src/styles/tokens.css +0 -40
- package/src/surfaces/accordion/style.css +41 -3
- package/src/surfaces/accordion/template.js +0 -4
- package/src/surfaces/app-bar/style.css +0 -3
- package/src/surfaces/card/style.css +0 -3
- package/types/controls/button-group.d.ts +5 -3
- package/types/controls/button.d.ts +3 -1
- package/types/controls/combobox.d.ts +13 -0
- package/types/controls/fab.d.ts +1 -1
- package/types/controls/icon-button.d.ts +7 -21
- package/types/controls/input.d.ts +2 -2
- package/types/data-display/avatar.d.ts +1 -1
- package/types/data-display/badge.d.ts +4 -2
- package/types/data-display/chip.d.ts +5 -3
- package/types/data-display/icon.d.ts +4 -2
- package/types/data-display/tooltip.d.ts +4 -2
- package/types/data-display/typography.d.ts +3 -1
- package/types/feedback/alert.d.ts +3 -1
- package/types/feedback/backdrop.d.ts +4 -2
- package/types/feedback/dialog.d.ts +3 -1
- package/types/index.d.ts +1 -0
- package/types/layout/container.d.ts +3 -1
- package/types/layout/flex.d.ts +9 -11
- package/types/layout/grid.d.ts +4 -2
- package/types/navigation/breadcrumbs.d.ts +1 -1
- package/types/navigation/drawer.d.ts +3 -1
- package/types/navigation/link.d.ts +4 -2
- package/types/shared/renderable.d.ts +12 -0
- package/types/surfaces/app-bar.d.ts +3 -1
- package/types/surfaces/card.d.ts +4 -2
- package/types/surfaces/paper.d.ts +3 -1
|
@@ -42,7 +42,6 @@
|
|
|
42
42
|
min-inline-size: 0;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
/* A message's own line breaks show; the template's around it do not. */
|
|
46
45
|
.iw-chat-text {
|
|
47
46
|
white-space: pre-wrap;
|
|
48
47
|
}
|
|
@@ -85,7 +84,6 @@
|
|
|
85
84
|
min-inline-size: 0;
|
|
86
85
|
}
|
|
87
86
|
|
|
88
|
-
/* The box grows with the message up to a point, then scrolls. */
|
|
89
87
|
.iw-textarea {
|
|
90
88
|
max-block-size: 10rem;
|
|
91
89
|
}
|
|
@@ -167,7 +167,6 @@ export const Chat = {
|
|
|
167
167
|
isFullWidth: true,
|
|
168
168
|
onChange: (value) => props.onDraftChange?.(value),
|
|
169
169
|
onKeyDown: (event) => {
|
|
170
|
-
// Enter sends, unless it closes a character being composed.
|
|
171
170
|
if (event.key !== "Enter" || event.shiftKey || event.isComposing) {
|
|
172
171
|
return
|
|
173
172
|
}
|
|
@@ -38,7 +38,6 @@ export function render(props) {
|
|
|
38
38
|
() => html`<span class="iw-chip-icon" aria-hidden="true">${icon}</span>`,
|
|
39
39
|
)} <span class="iw-chip-label">${children}</span>`
|
|
40
40
|
|
|
41
|
-
// A chip that can be picked is a toggle button, pressed while selected.
|
|
42
41
|
if (isSelected !== undefined) {
|
|
43
42
|
return html`<button
|
|
44
43
|
type="button"
|
|
@@ -37,16 +37,13 @@ export function sortChange(entity, columnId) {
|
|
|
37
37
|
const existingIndex = entity.sorts.findIndex((s) => s.column === columnId)
|
|
38
38
|
|
|
39
39
|
if (existingIndex !== -1) {
|
|
40
|
-
// Toggle direction
|
|
41
40
|
const existing = entity.sorts[existingIndex]
|
|
42
41
|
if (existing.direction === "asc") {
|
|
43
42
|
existing.direction = "desc"
|
|
44
43
|
} else {
|
|
45
|
-
// Remove from sort if going from desc back to nothing
|
|
46
44
|
entity.sorts.splice(existingIndex, 1)
|
|
47
45
|
}
|
|
48
46
|
} else {
|
|
49
|
-
// Add new sort
|
|
50
47
|
entity.sorts.push({ column: columnId, direction: "asc" })
|
|
51
48
|
}
|
|
52
49
|
|
|
@@ -201,7 +198,7 @@ export function rowToggle(entity, rowId) {
|
|
|
201
198
|
|
|
202
199
|
if (index === -1) {
|
|
203
200
|
if (!entity.isMultiSelect) {
|
|
204
|
-
entity.selection = [rowId]
|
|
201
|
+
entity.selection = [rowId]
|
|
205
202
|
} else {
|
|
206
203
|
entity.selection.push(rowId)
|
|
207
204
|
}
|
|
@@ -251,14 +248,12 @@ export function rowsToggleAll(entity) {
|
|
|
251
248
|
)
|
|
252
249
|
|
|
253
250
|
if (allSelected) {
|
|
254
|
-
// Deselect all visible
|
|
255
251
|
rows.forEach((row) => {
|
|
256
252
|
const rowId = getRowKeyValue(entity, row)
|
|
257
253
|
const index = entity.selection.indexOf(rowId)
|
|
258
254
|
if (index !== -1) entity.selection.splice(index, 1)
|
|
259
255
|
})
|
|
260
256
|
} else {
|
|
261
|
-
// Select all visible
|
|
262
257
|
rows.forEach((row) => {
|
|
263
258
|
const rowId = getRowKeyValue(entity, row)
|
|
264
259
|
if (!entity.selection.includes(rowId)) {
|
|
@@ -398,7 +393,6 @@ function initDataGrid(entity) {
|
|
|
398
393
|
entity.rows ??= []
|
|
399
394
|
entity.rowId ??= "id"
|
|
400
395
|
|
|
401
|
-
// Auto-generate columns from first data item if not provided
|
|
402
396
|
if (!entity.columns && entity.rows.length) {
|
|
403
397
|
const [firstRow] = entity.rows
|
|
404
398
|
|
|
@@ -427,7 +421,6 @@ function initDataGrid(entity) {
|
|
|
427
421
|
})
|
|
428
422
|
}
|
|
429
423
|
|
|
430
|
-
// State
|
|
431
424
|
entity.sorts ??= []
|
|
432
425
|
entity.filters ??= {}
|
|
433
426
|
entity.search ??= null
|
|
@@ -196,12 +196,10 @@ function applyFilters(entity, rows) {
|
|
|
196
196
|
const column = entity.columns.find((c) => c.id === columnId)
|
|
197
197
|
if (!column) return true
|
|
198
198
|
|
|
199
|
-
// Custom filter function
|
|
200
199
|
if (column.filterFn) {
|
|
201
200
|
return column.filterFn(row, filterValue)
|
|
202
201
|
}
|
|
203
202
|
|
|
204
|
-
// Default filters by type
|
|
205
203
|
const value = row[columnId]
|
|
206
204
|
|
|
207
205
|
if (["range", "date", "time", "datetime"].includes(column.filter.type)) {
|
|
@@ -215,7 +213,6 @@ function applyFilters(entity, rows) {
|
|
|
215
213
|
return value === filterValue
|
|
216
214
|
}
|
|
217
215
|
|
|
218
|
-
// String filtering (case-insensitive contains)
|
|
219
216
|
return String(value)
|
|
220
217
|
.toLowerCase()
|
|
221
218
|
.includes(String(filterValue).toLowerCase())
|
|
@@ -262,7 +259,6 @@ function applySorts(entity, rows) {
|
|
|
262
259
|
let aVal = a[columnId]
|
|
263
260
|
let bVal = b[columnId]
|
|
264
261
|
|
|
265
|
-
// Custom sort function
|
|
266
262
|
if (column?.sortFn) {
|
|
267
263
|
const result =
|
|
268
264
|
direction === "asc" ? column.sortFn(a, b) : column.sortFn(b, a)
|
|
@@ -270,7 +266,6 @@ function applySorts(entity, rows) {
|
|
|
270
266
|
continue
|
|
271
267
|
}
|
|
272
268
|
|
|
273
|
-
// Default sorting
|
|
274
269
|
if (aVal === bVal) continue
|
|
275
270
|
if (aVal == null) return 1
|
|
276
271
|
if (bVal == null) return -1
|
|
@@ -264,7 +264,6 @@ export const DataGrid = {
|
|
|
264
264
|
const column = props.columns[index]
|
|
265
265
|
const isEditable = Boolean(column.isEditable && row)
|
|
266
266
|
|
|
267
|
-
// Typing in a cell's editor is not picking its row.
|
|
268
267
|
return html`<div
|
|
269
268
|
class="iw-data-grid-cell ${classMap({
|
|
270
269
|
"iw-data-grid-cell-number": column.type === "number",
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/* The size is a floor, not a fixed box. A glyph or an `icon` takes the size's
|
|
2
|
-
font-size and fits it exactly, an SVG being drawn at 1em; content that sizes
|
|
3
|
-
itself (an SVG with its own width, a button) grows the box instead of
|
|
4
|
-
overflowing it or being squeezed into it. */
|
|
5
1
|
.iw-icon {
|
|
6
2
|
display: inline-flex;
|
|
7
3
|
align-items: center;
|
|
@@ -26,9 +22,6 @@
|
|
|
26
22
|
font-size: var(--iw-font-size-2xl);
|
|
27
23
|
}
|
|
28
24
|
|
|
29
|
-
/* An icon that points along the line, in right-to-left text. `scale`
|
|
30
|
-
rather than `transform`, so it adds to a rotation set elsewhere instead
|
|
31
|
-
of replacing it. */
|
|
32
25
|
&.iw-icon-rtl {
|
|
33
26
|
scale: -1 1;
|
|
34
27
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @typedef {import('@inglorious/web').TemplateResult} TemplateResult
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { html } from "@inglorious/web"
|
|
7
|
+
import { html, nothing } from "@inglorious/web"
|
|
8
8
|
import { classMap } from "@inglorious/web/directives/class-map"
|
|
9
9
|
import { ref } from "@inglorious/web/directives/ref"
|
|
10
10
|
import { unsafeSVG } from "@inglorious/web/directives/unsafe-svg"
|
|
@@ -53,7 +53,7 @@ export function render({
|
|
|
53
53
|
"iw-icon-rtl": direction === "rtl",
|
|
54
54
|
...extraClasses,
|
|
55
55
|
})}
|
|
56
|
-
style=${color !== "current" ? `color: ${color};` :
|
|
56
|
+
style=${color !== "current" ? `color: ${color};` : nothing}
|
|
57
57
|
@click=${onClick}
|
|
58
58
|
${ref((el) =>
|
|
59
59
|
applyElementProps(el, {
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/* The bubble is anchored to the trigger by CSS: the browser places it on the
|
|
2
|
-
requested side and flips it to the opposite one when it would leave the
|
|
3
|
-
viewport. Fixed, so a container that clips its overflow does not cut it. */
|
|
4
1
|
.iw-tooltip {
|
|
5
2
|
anchor-scope: --iw-tooltip;
|
|
6
3
|
display: inline-flex;
|
|
@@ -45,8 +45,6 @@ export function scroll(entity, containerEl) {
|
|
|
45
45
|
*/
|
|
46
46
|
export function mount(entity, containerEl) {
|
|
47
47
|
const firstItem = containerEl.querySelector("[data-index]")
|
|
48
|
-
// A list not laid out yet, such as one rendered into a detached element,
|
|
49
|
-
// measures 0: keep the estimate, and measure again on a later render.
|
|
50
48
|
if (!firstItem?.offsetHeight) return
|
|
51
49
|
|
|
52
50
|
entity.itemHeight = firstItem.offsetHeight
|
|
@@ -4,15 +4,13 @@
|
|
|
4
4
|
* @typedef {import('@inglorious/web').Api} Api
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { html } from "@inglorious/web"
|
|
7
|
+
import { html, nothing } from "@inglorious/web"
|
|
8
8
|
import { ref } from "@inglorious/web/directives/ref"
|
|
9
9
|
import { repeat } from "@inglorious/web/directives/repeat"
|
|
10
10
|
import { styleMap } from "@inglorious/web/directives/style-map"
|
|
11
11
|
|
|
12
12
|
const PRETTY_INDEX = 1
|
|
13
13
|
|
|
14
|
-
// The list elements already being measured. Every update re-renders, and
|
|
15
|
-
// measuring is an update, so measuring on each render would loop forever.
|
|
16
14
|
const measured = new WeakSet()
|
|
17
15
|
|
|
18
16
|
/**
|
|
@@ -49,7 +47,7 @@ export function render(entity, api) {
|
|
|
49
47
|
|
|
50
48
|
return html`
|
|
51
49
|
<div
|
|
52
|
-
class=${className ??
|
|
50
|
+
class=${className ?? nothing}
|
|
53
51
|
style=${styleMap({ height: `${viewportHeight}px`, overflow: "auto" })}
|
|
54
52
|
@scroll=${(e) => api.notify(`#${entity.id}:scroll`, e.currentTarget)}
|
|
55
53
|
${ref((el) => {
|
|
@@ -9,9 +9,6 @@ export const beforeAfterImages = {
|
|
|
9
9
|
},
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
// Self-contained demo images for the Before/After control, so the dashboard
|
|
13
|
-
// renders the comparison without any network requests.
|
|
14
|
-
|
|
15
12
|
function svg(label, from, to) {
|
|
16
13
|
return (
|
|
17
14
|
"data:image/svg+xml," +
|
|
@@ -1525,8 +1525,6 @@ function toTitleCase(slug) {
|
|
|
1525
1525
|
function livePreview(types, entity) {
|
|
1526
1526
|
if (!livePreviews.has(entity.id)) {
|
|
1527
1527
|
const container = document.createElement("div")
|
|
1528
|
-
// The mount needs an element, but it must not become a box of its own:
|
|
1529
|
-
// as a flex item it would shrink and take the primitive down with it.
|
|
1530
1528
|
container.style.display = "contents"
|
|
1531
1529
|
|
|
1532
1530
|
const store = createStore({ types, entities: { [entity.id]: entity } })
|
|
@@ -57,7 +57,6 @@
|
|
|
57
57
|
width: 100%;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
/* Outside the app bar, so it pads itself to line up with it. */
|
|
61
60
|
.iw-dashboard-breadcrumbs {
|
|
62
61
|
min-height: var(--iw-space-12);
|
|
63
62
|
padding-inline: var(--iw-space-4);
|
|
@@ -261,8 +260,6 @@
|
|
|
261
260
|
inset: 0;
|
|
262
261
|
}
|
|
263
262
|
|
|
264
|
-
/* Shown in place (isModal: false), so it can sit in the preview's flow
|
|
265
|
-
rather than where the browser positions a non-modal dialog. */
|
|
266
263
|
.iw-primitive-preview .iw-dialog {
|
|
267
264
|
position: static;
|
|
268
265
|
min-width: 0;
|
|
@@ -19,7 +19,6 @@ export default {
|
|
|
19
19
|
},
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
// In place, so the docs page that shows every story stays usable.
|
|
23
22
|
export const Open = {
|
|
24
23
|
args: {
|
|
25
24
|
isOpen: true,
|
|
@@ -53,14 +52,11 @@ export const Large = {
|
|
|
53
52
|
},
|
|
54
53
|
}
|
|
55
54
|
|
|
56
|
-
// Modal takes over the page, so it is left out of the docs page.
|
|
57
55
|
export const Modal = {
|
|
58
56
|
tags: ["!autodocs"],
|
|
59
57
|
args: { ...Open.args, isModal: true },
|
|
60
58
|
}
|
|
61
59
|
|
|
62
|
-
// A bottom sheet below 48rem: shrink the viewport to see it rise from the
|
|
63
|
-
// bottom edge. Modal, like Modal, so it stays off the docs page.
|
|
64
60
|
export const Sheet = {
|
|
65
61
|
tags: ["!autodocs"],
|
|
66
62
|
args: { ...Open.args, isModal: true, variant: "sheet" },
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/* A native <dialog>, so the browser's own box is reset: the surface inside
|
|
2
|
-
carries the padding, which leaves the dialog element itself reachable only
|
|
3
|
-
through the backdrop. Modal dialogs sit in the top layer, above any
|
|
4
|
-
z-index, and the browser centres them. */
|
|
5
1
|
.iw-dialog {
|
|
6
2
|
background: var(--iw-color-surface);
|
|
7
3
|
color: var(--iw-color-text);
|
|
@@ -47,7 +43,6 @@
|
|
|
47
43
|
font-size: 1.1rem;
|
|
48
44
|
}
|
|
49
45
|
|
|
50
|
-
/* The title takes the room, the close button only its own. */
|
|
51
46
|
.iw-dialog-close {
|
|
52
47
|
flex-shrink: 0;
|
|
53
48
|
}
|
|
@@ -69,11 +64,6 @@
|
|
|
69
64
|
gap: var(--iw-space-2);
|
|
70
65
|
}
|
|
71
66
|
|
|
72
|
-
/* A sheet on a narrow screen: anchored to the bottom edge at full width,
|
|
73
|
-
rising from below, clear of the home indicator. The browser centres a modal
|
|
74
|
-
dialog with auto margins in a full-screen inset, so the sheet resets both.
|
|
75
|
-
Only the bottom corners are squared, so a theme's radius stays on top. The
|
|
76
|
-
breakpoint is --iw-breakpoint-md, which a media query cannot read. */
|
|
77
67
|
@media (width < 48rem) {
|
|
78
68
|
dialog.iw-dialog.iw-dialog-sheet {
|
|
79
69
|
inset: auto 0 0;
|
|
@@ -55,10 +55,6 @@ export function render(props) {
|
|
|
55
55
|
const descriptionId = id && description ? `${id}-description` : ""
|
|
56
56
|
const onBackdrop = onBackdropClick ?? onClose
|
|
57
57
|
|
|
58
|
-
// The surface fills the dialog box, so a click that lands on the dialog
|
|
59
|
-
// itself can only have come from the backdrop around it. The press has to
|
|
60
|
-
// start there too: a drag from inside the surface that ends on the backdrop
|
|
61
|
-
// also clicks the dialog, and must not close it.
|
|
62
58
|
return html`<dialog
|
|
63
59
|
id=${id || nothing}
|
|
64
60
|
class=${classMap({
|
|
@@ -83,7 +79,6 @@ export function render(props) {
|
|
|
83
79
|
}
|
|
84
80
|
}}
|
|
85
81
|
@cancel=${(event) => {
|
|
86
|
-
// Without onClose nothing would take isOpen down, so Esc is refused.
|
|
87
82
|
if (!onClose) event.preventDefault()
|
|
88
83
|
}}
|
|
89
84
|
${ref((element) => syncDialog(element, { isOpen, isModal, onClose }))}
|
|
@@ -24,10 +24,6 @@
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
/* A native <progress>, restyled. Browsers draw its value through their own
|
|
28
|
-
pseudo-elements, so the look is set once here: the bar takes `color`, like
|
|
29
|
-
the color variants above, and an app adjusts the rest through
|
|
30
|
-
--iw-progress-height, --iw-progress-radius and --iw-progress-track-color. */
|
|
31
27
|
.iw-progress-linear {
|
|
32
28
|
--iw-progress-bar: linear-gradient(
|
|
33
29
|
90deg,
|
|
@@ -63,8 +59,6 @@
|
|
|
63
59
|
border-radius: var(--iw-progress-radius, var(--iw-radius-sm));
|
|
64
60
|
}
|
|
65
61
|
|
|
66
|
-
/* Indeterminate: no value to draw, so a sliver of the bar sweeps across
|
|
67
|
-
the track, painted on the element itself. */
|
|
68
62
|
&:indeterminate {
|
|
69
63
|
background:
|
|
70
64
|
var(--iw-progress-bar) no-repeat 0 0 / 30% 100%,
|
|
@@ -77,9 +77,6 @@ export function render(props) {
|
|
|
77
77
|
|
|
78
78
|
const progress = value == null ? null : clamp(value)
|
|
79
79
|
|
|
80
|
-
// An attribute, not a property: removing it is the only way back to
|
|
81
|
-
// indeterminate, which `:indeterminate` styles and assistive tech announces
|
|
82
|
-
// as busy.
|
|
83
80
|
return html`<progress
|
|
84
81
|
class=${classMap({
|
|
85
82
|
"iw-progress": true,
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/* Fixed to the viewport, clear of the system bars. A bottom snackbar also
|
|
2
|
-
clears whatever bar the app keeps at the bottom: the app sets
|
|
3
|
-
--iw-snackbar-offset-bottom to that bar's height while it shows, and the
|
|
4
|
-
offset then stands in for the safe area, which the bar already covers.
|
|
5
|
-
Only the app knows when its bar is on screen, so nothing is guessed here. */
|
|
6
1
|
.iw-snackbar {
|
|
7
2
|
--iw-snackbar-gap: var(--iw-space-4);
|
|
8
3
|
position: fixed;
|
|
@@ -10,9 +5,6 @@
|
|
|
10
5
|
max-width: calc(100vw - 2 * var(--iw-snackbar-gap));
|
|
11
6
|
}
|
|
12
7
|
|
|
13
|
-
/* A manual popover in the top layer. The browser centres a popover in the
|
|
14
|
-
viewport as a bordered box, so its insets and box are reset, with no
|
|
15
|
-
specificity so the positions below still set their own sides. */
|
|
16
8
|
:where(.iw-snackbar) {
|
|
17
9
|
inset: auto;
|
|
18
10
|
margin: 0;
|
|
@@ -48,8 +40,6 @@
|
|
|
48
40
|
right: var(--iw-snackbar-gap);
|
|
49
41
|
}
|
|
50
42
|
|
|
51
|
-
/* Both insets and auto margins: the snackbar is as wide as its content, up
|
|
52
|
-
to the gutters, and centered within them. */
|
|
53
43
|
.iw-snackbar-bottom-center,
|
|
54
44
|
.iw-snackbar-top-center {
|
|
55
45
|
inset-inline: var(--iw-snackbar-gap);
|
|
@@ -129,8 +129,6 @@
|
|
|
129
129
|
padding: var(--iw-space-8);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
/* A flex item needs both minimum dimensions released before either axis can
|
|
133
|
-
overflow instead of expanding its parent. */
|
|
134
132
|
&.iw-flex-overflow-auto,
|
|
135
133
|
&.iw-flex-overflow-scroll,
|
|
136
134
|
&.iw-flex-overflow-hidden,
|
|
@@ -19,8 +19,6 @@
|
|
|
19
19
|
align-items: center;
|
|
20
20
|
justify-content: center;
|
|
21
21
|
gap: var(--iw-space-1);
|
|
22
|
-
/* Narrow sides: a tab is a quarter or a fifth of a phone, and its label
|
|
23
|
-
needs every pixel of it. */
|
|
24
22
|
padding: var(--iw-space-2) var(--iw-space-1);
|
|
25
23
|
cursor: pointer;
|
|
26
24
|
}
|
|
@@ -29,13 +27,8 @@
|
|
|
29
27
|
color: var(--iw-color-primary);
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
/* 12px, as Material sizes navigation labels: at 14px, "Applications" or
|
|
33
|
-
"Candidatures" does not fit a quarter of a 360px phone. */
|
|
34
30
|
.iw-bottom-navigation-label {
|
|
35
31
|
font-size: var(--iw-font-size-xs);
|
|
36
|
-
/* One line, like its neighbours: a label too long for its tab is cut short
|
|
37
|
-
rather than wrapping, which in languages that break between any two
|
|
38
|
-
characters (Japanese, Chinese) splits a word and makes the bar taller. */
|
|
39
32
|
max-width: 100%;
|
|
40
33
|
overflow: hidden;
|
|
41
34
|
text-overflow: ellipsis;
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/* While it overlays the page the drawer is a popover in the top layer. The
|
|
2
|
-
browser styles every popover as a centred, bordered box hidden until it
|
|
3
|
-
opens, so those defaults are reset here: the drawer stays displayed while
|
|
4
|
-
closed, off-screen or docked, and slides rather than appears. */
|
|
5
1
|
.iw-drawer {
|
|
6
2
|
display: flex;
|
|
7
3
|
flex-direction: column;
|
|
@@ -24,8 +20,6 @@
|
|
|
24
20
|
inset-block: 0;
|
|
25
21
|
z-index: var(--iw-z-modal, 1050);
|
|
26
22
|
|
|
27
|
-
/* As tall as an app bar, so the line under a drawer and the app bar beside
|
|
28
|
-
it runs straight across. */
|
|
29
23
|
.iw-drawer-header {
|
|
30
24
|
min-height: var(--iw-space-16);
|
|
31
25
|
border-bottom: 1px solid var(--iw-color-border);
|
|
@@ -52,8 +46,6 @@
|
|
|
52
46
|
transition: transform var(--iw-transition-fast);
|
|
53
47
|
}
|
|
54
48
|
|
|
55
|
-
/* The toggle points at the edge the drawer sits on, which a right-to-left
|
|
56
|
-
page mirrors. `scale`, so the collapsed state's rotation still applies. */
|
|
57
49
|
.iw-drawer-toggler > span:dir(rtl) {
|
|
58
50
|
scale: -1 1;
|
|
59
51
|
}
|
|
@@ -84,15 +76,10 @@
|
|
|
84
76
|
opacity: 0;
|
|
85
77
|
}
|
|
86
78
|
|
|
87
|
-
/* The header keeps only what fits the rail, such as a brand mark, so
|
|
88
|
-
it centres it. */
|
|
89
79
|
.iw-drawer-header {
|
|
90
80
|
justify-content: center;
|
|
91
81
|
}
|
|
92
82
|
|
|
93
|
-
/* Only the icon is left, centred in the rail. The label also has to
|
|
94
|
-
leave the row: faded out, it still took its width and pushed the
|
|
95
|
-
icon off centre, as did the icon's side margin. */
|
|
96
83
|
.iw-list-item > .iw-flex {
|
|
97
84
|
justify-content: center;
|
|
98
85
|
}
|
|
@@ -112,8 +99,6 @@
|
|
|
112
99
|
}
|
|
113
100
|
}
|
|
114
101
|
|
|
115
|
-
/* `left` and `right` are the start and end of the line: the left drawer
|
|
116
|
-
sits on the right in a right-to-left page, and slides off that way. */
|
|
117
102
|
.iw-drawer-left {
|
|
118
103
|
inset-inline: 0 auto;
|
|
119
104
|
border-inline-end: 1px solid var(--iw-color-border);
|
|
@@ -136,9 +121,6 @@
|
|
|
136
121
|
backdrop-filter: none;
|
|
137
122
|
}
|
|
138
123
|
|
|
139
|
-
/* Overlaying: a temporary drawer at every width, a responsive one below
|
|
140
|
-
64rem. Off-screen until open, raised, closed from its header. The collapse
|
|
141
|
-
toggle only makes sense for a rail, so the footer goes. */
|
|
142
124
|
.iw-drawer {
|
|
143
125
|
box-shadow: var(--iw-shadow-lg);
|
|
144
126
|
|
|
@@ -151,9 +133,6 @@
|
|
|
151
133
|
}
|
|
152
134
|
}
|
|
153
135
|
|
|
154
|
-
/* Docked: a permanent drawer at every width, a responsive one from 64rem
|
|
155
|
-
(keep in step with DOCKED_QUERY in template.js). In place, flat, and
|
|
156
|
-
hidden only on request. */
|
|
157
136
|
.iw-drawer-permanent {
|
|
158
137
|
transform: none;
|
|
159
138
|
box-shadow: none;
|
|
@@ -77,8 +77,6 @@ export function render(props) {
|
|
|
77
77
|
...extraClasses,
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
// Without onClose nothing would take isOpen down, so the browser is not
|
|
81
|
-
// allowed to dismiss it: a manual popover ignores Esc and outside presses.
|
|
82
80
|
const popover =
|
|
83
81
|
variant === "permanent" ? nothing : onClose ? "auto" : "manual"
|
|
84
82
|
|
|
@@ -10,10 +10,6 @@
|
|
|
10
10
|
box-shadow: var(--iw-shadow-lg);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
/* Anchored to its trigger: below it and aligned with its start, flipping up
|
|
14
|
-
or across when there is no room. The browser's popover box is centred in
|
|
15
|
-
the viewport, so its insets and margins are reset; its hidden state has to
|
|
16
|
-
be restated, because the display above outranks it. */
|
|
17
13
|
.iw-menu[popover] {
|
|
18
14
|
inset: auto;
|
|
19
15
|
margin: var(--iw-space-1) 0 0;
|
|
@@ -46,7 +46,6 @@ export const Menu = {
|
|
|
46
46
|
commandfor: id,
|
|
47
47
|
command: "toggle-popover",
|
|
48
48
|
"aria-haspopup": "menu",
|
|
49
|
-
// Left to the browser when it alone keeps the open state.
|
|
50
49
|
"aria-expanded": onToggle ? String(isOpen) : undefined,
|
|
51
50
|
style: `anchor-name: ${anchorName(id)}`,
|
|
52
51
|
})
|
|
@@ -96,7 +95,6 @@ export const Menu = {
|
|
|
96
95
|
${ref((element) => {
|
|
97
96
|
if (!element) return
|
|
98
97
|
applyElementProps(element, rest)
|
|
99
|
-
// Without onToggle the browser alone opens and closes it.
|
|
100
98
|
if (trigger && onToggle) {
|
|
101
99
|
syncPopover(element, {
|
|
102
100
|
isOpen,
|
|
@@ -123,7 +121,6 @@ export const Menu = {
|
|
|
123
121
|
return html`<div class="iw-menu-divider" role="separator"></div>`
|
|
124
122
|
}
|
|
125
123
|
|
|
126
|
-
// In an anchored menu each item also hides the popover once picked.
|
|
127
124
|
return html`<button
|
|
128
125
|
type="button"
|
|
129
126
|
class=${classMap({
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/* The actions are a popover anchored to the trigger and placed on the side
|
|
2
|
-
`direction` names. The browser's popover box is centred in the viewport,
|
|
3
|
-
so its insets and box are reset; its hidden state has to be restated,
|
|
4
|
-
because the display below outranks it. */
|
|
5
1
|
.iw-speed-dial {
|
|
6
2
|
anchor-scope: --iw-speed-dial;
|
|
7
3
|
display: inline-flex;
|
|
@@ -49,9 +49,7 @@ export const SpeedDial = {
|
|
|
49
49
|
if (!element) return
|
|
50
50
|
const trigger = element.querySelector(".iw-speed-dial-trigger")
|
|
51
51
|
const popover = element.querySelector(".iw-speed-dial-actions")
|
|
52
|
-
// A property, not `commandfor`, so the link needs no id.
|
|
53
52
|
trigger.commandForElement = popover
|
|
54
|
-
// Without onToggle the browser alone opens and closes it.
|
|
55
53
|
if (onToggle) {
|
|
56
54
|
syncPopover(popover, {
|
|
57
55
|
isOpen,
|
|
@@ -92,9 +90,6 @@ export const SpeedDial = {
|
|
|
92
90
|
class="iw-speed-dial-action"
|
|
93
91
|
command="hide-popover"
|
|
94
92
|
${ref((element) => {
|
|
95
|
-
// Hides the popover once the action runs, like a menu item. Linked a
|
|
96
|
-
// microtask later: a new action is still outside the popover when its
|
|
97
|
-
// ref runs.
|
|
98
93
|
if (element) {
|
|
99
94
|
queueMicrotask(() => {
|
|
100
95
|
element.commandForElement = element.parentElement
|
|
@@ -65,8 +65,6 @@ export const Tabs = {
|
|
|
65
65
|
renderTab(item, index, props) {
|
|
66
66
|
const tabValue = item.value ?? index
|
|
67
67
|
const selected = tabValue === props.value
|
|
68
|
-
// Only one tab is in the Tab order, and the arrow keys move between them:
|
|
69
|
-
// the selected tab, or the first one while none is.
|
|
70
68
|
const hasSelection = props.items.some(
|
|
71
69
|
(other, otherIndex) => (other.value ?? otherIndex) === props.value,
|
|
72
70
|
)
|