@reliability-design/web 1.4.10 → 1.4.11
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 +7 -1
- package/custom-elements.json +5 -1
- package/dist/components/rel-pagination/README.md +2 -2
- package/dist/components/rel-select/README.md +1 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +78 -29
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +78 -29
- package/dist/index.mjs.map +1 -1
- package/dist/styles/ag-grid.css +274 -0
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -35,10 +35,11 @@ Paired releases: `@reliability-design/angular` 1.5.0, which now requires web `^1
|
|
|
35
35
|
- **`rel-tab` `orientation="vertical"`** — the tab list sits in a column beside the panel (`--rel-tab-list-width`), with `aria-orientation="vertical"`, tabs 24px apart along a rule on the list's inline-start edge with the active bar on that edge, and Up / Down instead of Left / Right. Long labels wrap; no built-in breakpoint (switch to horizontal on small screens).
|
|
36
36
|
- **`rel-tab` `icon-placement="top"`** — stacks each tab's icon above its label, with the badge beside the label; stacked tabs are 76 / 64 / 52px tall at large / medium / small. Works in both orientations.
|
|
37
37
|
- **`rel-signature-pad`** (new, status stable) — captures a handwritten signature with a mouse, pen or finger on a 160px pad that fills its container (`--rel-signature-pad-height`; focus, drawing and error draw a 2px border inside the pad edge, and focus in error adds a 2px danger ring outside), or a typed name: the "Type your name instead" link switches to `mode="type"` (Poppins italic), the keyboard alternative to drawing (WCAG 2.2 SC 2.5.7). `value` is a trimmed PNG data URL (2×, black ink in every theme) and the **form value**: the pad is form-associated and submits it under `name`, is invalid (`valueMissing`) when `required` and empty, empties on form reset and comes back on state restore (decision 0006; switch, checkbox and radio still set no form value). Also `strokes` (the vector record), `signedAt`, `typed-name`, `toDataURL(type)`, `toSVG()`, `isEmpty()`, `undo()` / `clear()`. Undo is stroke level and also reverses Clear, so Clear asks no confirmation; Ctrl/Cmd+Z undoes inside the field; the helper row shows "Signed {date, time, time zone}". Label, `helper-text`, `error` / `error-message`, `disabled` and `readonly` work as on `rel-textfield`. `rel-change` (`{ value, strokes, signedAt, mode }`, user actions only) and `rel-begin` / `rel-end`.
|
|
38
|
-
- **`rel-split-button`** (new, status stable) — the Combo Button: a main action and a chevron that opens a `rel-menu` of `items` (`{ value, label, icon?, disabled? }`) below the pill, end-aligned and at least as wide. Both segments are drawn with `rel-button`'s own styles, so `variant` (primary | secondary, the default | ghost | static), `tone` (neutral | brand | destructive) and `size` (32 / 40 / 48px) match `rel-button` exactly, including hover, pressed, focus and disabled; outer corners keep the pill radius and the seam is square. While the menu is open the chevron keeps its pressed look. Also `disabled`, `loading` (a spinner only on the main action, which keeps its accessible name; the chevron is disabled), `icon-only` with `aria-label` (the main action is a square too), `icon`, `menu-label` (the chevron's name, default "More options") and `open`. The host's `click` is the main action; `rel-select` (`{ value, item }`) and `rel-open-change` (`{ open }`). WAI-ARIA menu button: two Tab stops; Enter, Space or Down opens on the first entry and Up on the last; Escape or a choice returns focus to the chevron; Tab closes; a mouse open shows no ring. Divider: its own 1px column, in the outline border (secondary; the hover colour while
|
|
38
|
+
- **`rel-split-button`** (new, status stable) — the Combo Button: a main action and a chevron that opens a `rel-menu` of `items` (`{ value, label, icon?, disabled? }`) below the pill, end-aligned and at least as wide. Both segments are drawn with `rel-button`'s own styles, so `variant` (primary | secondary, the default | ghost | static), `tone` (neutral | brand | destructive) and `size` (32 / 40 / 48px) match `rel-button` exactly, including hover, pressed, focus and disabled; outer corners keep the pill radius and the seam is square. While the menu is open the chevron keeps its pressed look. Also `disabled`, `loading` (a spinner only on the main action, which keeps its accessible name; the chevron is disabled), `icon-only` with `aria-label` (the main action is a square too), `icon`, `menu-label` (the chevron's name, default "More options") and `open`. The host's `click` is the main action; `rel-select` (`{ value, item }`) and `rel-open-change` (`{ open }`). WAI-ARIA menu button: two Tab stops; Enter, Space or Down opens on the first entry and Up on the last; Escape or a choice returns focus to the chevron; Tab closes; a mouse open shows no ring. Divider: its own 1px column, in the outline border (secondary; the hover colour while either segment is hovered or pressed, or the menu is open), the label colour (primary), white (static) or `--rel-border-subtle` (ghost).
|
|
39
39
|
- **`rel-popover` `has-popup`** (property `hasPopup`) — the value written to the trigger's `aria-haspopup`: `dialog` (default, unchanged), or `menu` for a panel holding a `rel-menu` (also `listbox`, `tree`, `grid`, `true`).
|
|
40
40
|
- **`rel-menu` item icons and `focusItem(index)`** — `MenuItem.icon` draws a `rel-icon` before the label on `list` and `arrow` rows (20 / 18 / 16px by size, hidden from screen readers); `focusItem()` moves the virtual focus (`aria-activedescendant`), clamped, a negative index counting from the end, for menu buttons that open on the last row.
|
|
41
41
|
- **`createGridNavigation(grid, options)`** (a utility, exported from the main entry) — the WAI-ARIA grid keyboard for plain markup (`[role="row"]` > `[role="gridcell"]`): a roving Tab stop, arrows, Home / End, Ctrl+Home / Ctrl+End, PageUp / PageDown with `pageSize`, right-to-left, `disabledCells` (`"focus"`, the default, or `"skip"`), `wrap`, `onActivate` (Enter, Space, click), `onMove`, a custom `resolve` key map, and a handle with `active`, `focusCell()`, `refresh()` and `destroy()`. Framework-free, so recipes can use it; the Rate Calendar recipe does.
|
|
42
|
+
- **`@reliability-design/web/ag-grid.css`** — an AG Grid theme (v33+ with the Theming API; 32.2–32.3 when the app passes `theme: themeQuartz`) that maps AG Grid's theme params to our tokens, light and dark. Scope it with a `.rel-data-table` wrapper; set `data-density` to `dense` (40px rows) or `comfortable` (64px) on it (default 56px, header 48px). Row-state classes for `rowClassRules`: `rel-data-table__row--error` (wins over selected) and `rel-data-table__row--disabled`. Sortable headers show the unsorted icon at rest, as `unSortIcon: true` would. AG Grid itself is not a dependency. Docs: the Data Table recipe.
|
|
42
43
|
|
|
43
44
|
### Changed
|
|
44
45
|
|
|
@@ -119,6 +120,11 @@ Paired releases: `@reliability-design/angular` 1.5.0, which now requires web `^1
|
|
|
119
120
|
- **`rel-popover` panel sat at a stale spot until the next frame:** it is now placed in the same task that opens it. Before, for one frame it stayed at its previous position, or at 0,0 on a first open; nothing painted there, but a quick pointer release could land on the unplaced panel instead of the trigger.
|
|
120
121
|
- **`rel-button` `variant="static" icon-only` was not square:** the static style's 40 / 50 / 60px minimum width outranked the icon-only reset, so a static icon-only button was 40 / 50 / 60 wide instead of a 32 / 40 / 48 square. Static label buttons keep their minimum width; no other style changes.
|
|
121
122
|
- **`rel-popover` panel text followed the `align` attribute:** Chromium maps an element's `align` attribute to `text-align`, and rel-popover reflects `align` (default `center`), so every popover centred its panel text (and its trigger's inline content) and `align="end"` right-aligned it. The host now takes its parent's alignment, as if the attribute were not there. If you relied on the centring, set `text-align` on your panel content.
|
|
123
|
+
- **`rel-pagination` `type="page-select"`: the dropdown squeezed its rows.** The panel was as narrow as the 72px trigger, so the search box shrank to its icon and, with a classic scrollbar, the selected row showed only its check, not the number. The page list now has no search box (typing a page number still jumps to it) and is at least as wide as the longest number, the check and a scrollbar need. The rows-per-page dropdown had the same squeeze (the selected "20" showed as "2…") and gets the same floor. The width comes from a new opt-in hook on `rel-select`, **`--rel-select-panel-min-width`** (unset by default: the panel still matches the trigger).
|
|
124
|
+
- **`rel-select` / `rel-autocomplete` multi-select logged a deprecation notice the app never caused:** their option checkboxes used the deprecated `supportingtext` attribute spelling, so every multi-select logged `[rel-checkbox] "supportingtext" is deprecated`. They now set the property.
|
|
125
|
+
- **`rel-signature-pad` focused in error drew seams:** the 2px danger edge inside the pad was a border plus a clipped pseudo element, and focus added an outline outside, so light gaps showed between three red bands (clearest when the browser is zoomed). The edge is now one outline, 2px inside at rest and 2px inside plus 2px outside when focused. Same look, no seams.
|
|
126
|
+
- **`rel-split-button` secondary: the chevron showed three dark sides.** Hovered, pressed or open, the chevron's border darkened but the divider beside it didn't, while the main action's hover darkens the divider too. The divider now follows either segment, and the open menu.
|
|
127
|
+
- **`rel-pagination` extended layout lost its ellipsis between 480 and 768px.** In that width it keeps only the first, last and current ±1 pages but also hid every "…", so 5 pages on page 1 read "1 2 5" with nothing between 2 and 5 (and 20 pages on page 10 read "1 9 10 11 20"). A "…" now marks each gap that width opens; a gap of a single page shows that page instead.
|
|
122
128
|
|
|
123
129
|
### Known issues
|
|
124
130
|
|
package/custom-elements.json
CHANGED
|
@@ -8664,7 +8664,7 @@
|
|
|
8664
8664
|
},
|
|
8665
8665
|
{
|
|
8666
8666
|
"keys": "Typing (page dropdown open)",
|
|
8667
|
-
"action": "
|
|
8667
|
+
"action": "Moves the highlight to the next page that starts with the digits typed within half a second (2 then 5 for page 25); Enter picks it"
|
|
8668
8668
|
}
|
|
8669
8669
|
],
|
|
8670
8670
|
"source": "src/components/rel-pagination/README.md#accessibility"
|
|
@@ -11259,6 +11259,10 @@
|
|
|
11259
11259
|
"description": "Panel box-shadow",
|
|
11260
11260
|
"name": "--rel-select-menu-shadow"
|
|
11261
11261
|
},
|
|
11262
|
+
{
|
|
11263
|
+
"description": "Smallest width of the dropdown panel. The panel is as wide as the trigger; set this when the trigger is narrower than its options need (a scrollbar included), and the panel grows past the trigger's right edge instead of squeezing them. Unset by default, so the panel matches the trigger. New in 1.5.0.",
|
|
11264
|
+
"name": "--rel-select-panel-min-width"
|
|
11265
|
+
},
|
|
11262
11266
|
{
|
|
11263
11267
|
"description": "Border colour of the search field inside the panel",
|
|
11264
11268
|
"name": "--rel-select-search-border"
|
|
@@ -123,7 +123,7 @@ Without `show-rows-per-page` there is no rows-per-page selector, and every type
|
|
|
123
123
|
| `Tab` / `Shift+Tab` | Move between the prev button, page chips (or the page dropdown) and next button, then the rows-per-page dropdown |
|
|
124
124
|
| `Enter` / `Space` | Activate the focused button (native behaviour); on a dropdown, open it |
|
|
125
125
|
| `ArrowDown` / `ArrowUp`, `Enter`, `Escape` (dropdown open) | Move the highlight, pick the highlighted value, close without picking (rel-select's keyboard model) |
|
|
126
|
-
| Typing (page dropdown open) |
|
|
126
|
+
| Typing (page dropdown open) | Moves the highlight to the next page that starts with the digits typed within half a second (2 then 5 for page 25); Enter picks it |
|
|
127
127
|
|
|
128
128
|
The page chips and nav buttons have no arrow-key navigation; they are regular tab stops.
|
|
129
129
|
|
|
@@ -133,7 +133,7 @@ The page chips and nav buttons have no arrow-key navigation; they are regular ta
|
|
|
133
133
|
- **Page count.** `totalPages` wins when greater than `0`; otherwise the count is `ceil(totalItems / perPage)`. With neither set the element renders no page chips and both nav buttons disabled.
|
|
134
134
|
- **Controlled vs uncontrolled.** With `page` unset the element tracks the current page itself starting at `defaultPage`. Once `page` is set it stays on that page until the parent changes it — clicking only emits `rel-change`.
|
|
135
135
|
- **Ellipsis window.** Up to 7 pages render in full. Beyond that: the first 5 + last near the start, first + last 5 near the end, otherwise first, current ±1 and last, with `…` between. Far first/last chips abbreviate large numbers (`10000` → `10k`, `2500000` → `2.5M`); chips inside the window are never abbreviated.
|
|
136
|
-
- **Responsive.** `extended` uses a container query on the host: between 480px and 768px only first, last and current ±1 stay visible; under 480px the whole control swaps to the compact layout (media-query fallback for browsers without container queries). The `label` part belongs to the `count-text` layout, not to the "Viewing page" caption.
|
|
136
|
+
- **Responsive.** `extended` uses a container query on the host: between 480px and 768px only first, last and current ±1 stay visible, with `…` wherever that hides two or more pages (a single hidden page stays visible instead); under 480px the whole control swaps to the compact layout (media-query fallback for browsers without container queries). The `label` part belongs to the `count-text` layout, not to the "Viewing page" caption.
|
|
137
137
|
- **`hrefTemplate`** is accepted but currently unused — chips are always buttons, not links. Perform navigation in the `rel-change` handler.
|
|
138
138
|
- **`rel-change` is not fired** for the current page, out-of-range pages, or while `disabled`.
|
|
139
139
|
- **Page select.** The dropdown lists every page. Above 1,000 pages it lists a window of 1,000 around the current page plus the first and last, so the list stays fast. In controlled mode the dropdown snaps back to `page` until the parent commits the new one.
|
|
@@ -139,6 +139,7 @@ Set these on the host (or an ancestor) to customise the element without touching
|
|
|
139
139
|
| `--rel-select-menu-shadow` | `var(--rel-shadows-md)` | Panel box-shadow |
|
|
140
140
|
| `--rel-select-option-hover` | `var(--rel-action-overlay-hover)` | Background of the hovered / keyboard-highlighted / selected option and Select-all row |
|
|
141
141
|
| `--rel-select-option-pressed` | `var(--rel-action-overlay-pressed)` | Background of an option row while it is being pressed |
|
|
142
|
+
| `--rel-select-panel-min-width` | `0px` | Smallest width of the dropdown panel. The panel is as wide as the trigger; set this when the trigger is narrower than its options need (a scrollbar included), and the panel grows past the trigger's right edge instead of squeezing them. Unset by default, so the panel matches the trigger. New in 1.5.0. |
|
|
142
143
|
| `--rel-select-placeholder-color` | `var(--rel-text-placeholder)` | Placeholder colour (trigger, resting floating label, search field, empty-list message) |
|
|
143
144
|
| `--rel-select-placeholder-disabled-color` | `var(--rel-text-caption)` | Placeholder colour when disabled |
|
|
144
145
|
| `--rel-select-radius` | `var(--rel-border-radius-xs)` | Trigger corner radius when `border="rounded"` |
|
package/dist/index.d.mts
CHANGED
|
@@ -2540,6 +2540,7 @@ type SelectOption = string | SelectOptionObject;
|
|
|
2540
2540
|
* @cssprop --rel-select-menu-border - Panel border colour. The panel is borderless by design and only draws this on dark surfaces, where its shadow alone can't separate it from the page.
|
|
2541
2541
|
* @cssprop --rel-select-menu-radius - Panel corner radius
|
|
2542
2542
|
* @cssprop --rel-select-menu-shadow - Panel box-shadow
|
|
2543
|
+
* @cssprop --rel-select-panel-min-width - Smallest width of the dropdown panel. The panel is as wide as the trigger; set this when the trigger is narrower than its options need (a scrollbar included), and the panel grows past the trigger's right edge instead of squeezing them. Unset by default, so the panel matches the trigger. New in 1.5.0.
|
|
2543
2544
|
* @cssprop --rel-select-search-border - Border colour of the search field inside the panel
|
|
2544
2545
|
* @cssprop --rel-select-divider - Hairline under the search field, the Select-all row and every option row
|
|
2545
2546
|
* @cssprop --rel-select-option-hover - Background of the hovered / keyboard-highlighted / selected option and Select-all row
|
|
@@ -2802,6 +2803,11 @@ declare class RelPagination extends RelElement {
|
|
|
2802
2803
|
/** Pages offered by the page-select dropdown: every page, or for very long
|
|
2803
2804
|
ranges a window around the current page plus the first and last. */
|
|
2804
2805
|
private pageOptions;
|
|
2806
|
+
/** Both dropdowns' panels may be wider than their 72px trigger: the longest
|
|
2807
|
+
value (`largest`), the row's 12px side padding, the 16px gap, the 18px
|
|
2808
|
+
check and 20px kept for a classic scrollbar (the page list scrolls past
|
|
2809
|
+
9 pages). */
|
|
2810
|
+
private panelMinWidth;
|
|
2805
2811
|
private stopInner;
|
|
2806
2812
|
private onPageSelect;
|
|
2807
2813
|
private onRowsPerPage;
|
package/dist/index.d.ts
CHANGED
|
@@ -2540,6 +2540,7 @@ type SelectOption = string | SelectOptionObject;
|
|
|
2540
2540
|
* @cssprop --rel-select-menu-border - Panel border colour. The panel is borderless by design and only draws this on dark surfaces, where its shadow alone can't separate it from the page.
|
|
2541
2541
|
* @cssprop --rel-select-menu-radius - Panel corner radius
|
|
2542
2542
|
* @cssprop --rel-select-menu-shadow - Panel box-shadow
|
|
2543
|
+
* @cssprop --rel-select-panel-min-width - Smallest width of the dropdown panel. The panel is as wide as the trigger; set this when the trigger is narrower than its options need (a scrollbar included), and the panel grows past the trigger's right edge instead of squeezing them. Unset by default, so the panel matches the trigger. New in 1.5.0.
|
|
2543
2544
|
* @cssprop --rel-select-search-border - Border colour of the search field inside the panel
|
|
2544
2545
|
* @cssprop --rel-select-divider - Hairline under the search field, the Select-all row and every option row
|
|
2545
2546
|
* @cssprop --rel-select-option-hover - Background of the hovered / keyboard-highlighted / selected option and Select-all row
|
|
@@ -2802,6 +2803,11 @@ declare class RelPagination extends RelElement {
|
|
|
2802
2803
|
/** Pages offered by the page-select dropdown: every page, or for very long
|
|
2803
2804
|
ranges a window around the current page plus the first and last. */
|
|
2804
2805
|
private pageOptions;
|
|
2806
|
+
/** Both dropdowns' panels may be wider than their 72px trigger: the longest
|
|
2807
|
+
value (`largest`), the row's 12px side padding, the 16px gap, the 18px
|
|
2808
|
+
check and 20px kept for a classic scrollbar (the page list scrolls past
|
|
2809
|
+
9 pages). */
|
|
2810
|
+
private panelMinWidth;
|
|
2805
2811
|
private stopInner;
|
|
2806
2812
|
private onPageSelect;
|
|
2807
2813
|
private onRowsPerPage;
|
package/dist/index.js
CHANGED
|
@@ -5112,7 +5112,7 @@ ${item.supportingText}` : import_lit9.nothing;
|
|
|
5112
5112
|
size="${this.optionCheckboxSize}"
|
|
5113
5113
|
label="${item.label}"
|
|
5114
5114
|
icon="${item.icon}"
|
|
5115
|
-
|
|
5115
|
+
.supportingText="${item.supportingText ?? ""}"
|
|
5116
5116
|
status="${this.selectedValues.includes(item.value) ? "checked" : "unchecked"}"
|
|
5117
5117
|
></rel-checkbox>
|
|
5118
5118
|
</div>` : import_lit9.html`
|
|
@@ -17328,13 +17328,14 @@ var RelSelect = class extends RelElement {
|
|
|
17328
17328
|
if (top + c.height > window.innerHeight - 8) {
|
|
17329
17329
|
top = Math.max(8, t.top - c.height - 8);
|
|
17330
17330
|
}
|
|
17331
|
+
this.listboxEl.style.width = `${t.width}px`;
|
|
17332
|
+
const w = Math.max(t.width, this.listboxEl.getBoundingClientRect().width);
|
|
17331
17333
|
let left = t.left;
|
|
17332
|
-
if (left +
|
|
17333
|
-
left = Math.max(8, window.innerWidth -
|
|
17334
|
+
if (left + w > window.innerWidth - 8) {
|
|
17335
|
+
left = Math.max(8, window.innerWidth - w - 8);
|
|
17334
17336
|
}
|
|
17335
17337
|
this.listboxEl.style.top = `${top}px`;
|
|
17336
17338
|
this.listboxEl.style.left = `${left}px`;
|
|
17337
|
-
this.listboxEl.style.width = `${t.width}px`;
|
|
17338
17339
|
const applied = this.listboxEl.getBoundingClientRect();
|
|
17339
17340
|
top -= applied.top - top;
|
|
17340
17341
|
left -= applied.left - left;
|
|
@@ -18018,7 +18019,7 @@ ${option.supportingText}` : import_lit31.nothing;
|
|
|
18018
18019
|
size="${this.optionCheckboxSize}"
|
|
18019
18020
|
label="${option.label}"
|
|
18020
18021
|
icon="${option.icon}"
|
|
18021
|
-
|
|
18022
|
+
.supportingText="${option.supportingText ?? ""}"
|
|
18022
18023
|
status="${this.selectedValues.includes(option.value) ? "checked" : "unchecked"}"
|
|
18023
18024
|
></rel-checkbox>
|
|
18024
18025
|
</div>
|
|
@@ -18650,6 +18651,8 @@ RelSelect.styles = import_lit31.css`
|
|
|
18650
18651
|
margin: 0;
|
|
18651
18652
|
padding: 0;
|
|
18652
18653
|
width: auto;
|
|
18654
|
+
/* Opt-in floor under the trigger-width panel (unset: 0, no change). */
|
|
18655
|
+
min-width: var(--rel-select-panel-min-width, 0px);
|
|
18653
18656
|
height: auto;
|
|
18654
18657
|
color: inherit;
|
|
18655
18658
|
box-sizing: border-box;
|
|
@@ -19281,19 +19284,34 @@ var RelPagination = class extends RelElement {
|
|
|
19281
19284
|
const pages = this.generatePageNumbers();
|
|
19282
19285
|
const current = this.activePage;
|
|
19283
19286
|
const total = this.computedTotalPages;
|
|
19287
|
+
const narrowShown = (p) => p !== -1 && (p === 1 || p === total || Math.abs(p - current) <= 1);
|
|
19288
|
+
const narrowGapAt = /* @__PURE__ */ new Set();
|
|
19289
|
+
const narrowKeep = /* @__PURE__ */ new Set();
|
|
19290
|
+
for (let i = 0; i < pages.length; ) {
|
|
19291
|
+
if (narrowShown(pages[i])) {
|
|
19292
|
+
i++;
|
|
19293
|
+
continue;
|
|
19294
|
+
}
|
|
19295
|
+
let end = i;
|
|
19296
|
+
while (end < pages.length && !narrowShown(pages[end])) end++;
|
|
19297
|
+
if (end - i === 1 && pages[i] !== -1) narrowKeep.add(pages[i]);
|
|
19298
|
+
else narrowGapAt.add(i);
|
|
19299
|
+
i = end;
|
|
19300
|
+
}
|
|
19284
19301
|
return import_lit32.html`
|
|
19285
19302
|
<div part="base" class="pag-root" role="navigation" aria-label="${this.ariaLabel}">
|
|
19286
19303
|
<div class="pag-stack">
|
|
19287
19304
|
${this.renderNavBtn("prev")}
|
|
19288
19305
|
<div class="pag-numbers">
|
|
19289
|
-
${pages.map((p) => {
|
|
19290
|
-
|
|
19306
|
+
${pages.map((p, i) => {
|
|
19307
|
+
const gap = narrowGapAt.has(i) ? import_lit32.html`<span class="pag-ellipsis pag-ellipsis-narrow">...</span>` : import_lit32.nothing;
|
|
19308
|
+
if (p === -1) return import_lit32.html`${gap}<span class="pag-ellipsis">...</span>`;
|
|
19291
19309
|
const isNear = Math.abs(p - current) <= 1;
|
|
19292
19310
|
const isEdge = p === 1 || p === total;
|
|
19293
19311
|
const label = isEdge && !isNear ? this.formatPageLabel(p) : String(p);
|
|
19294
|
-
return import_lit32.html
|
|
19312
|
+
return import_lit32.html`${gap}<button
|
|
19295
19313
|
type="button"
|
|
19296
|
-
class="pag-page-btn ${isNear ? "near" : ""} ${p === 1 || p === total ? "edge" : ""}"
|
|
19314
|
+
class="pag-page-btn ${isNear ? "near" : ""} ${p === 1 || p === total ? "edge" : ""} ${narrowKeep.has(p) ? "keep" : ""}"
|
|
19297
19315
|
aria-label="Page ${p}"
|
|
19298
19316
|
title="${label === String(p) ? import_lit32.nothing : `Page ${p}`}"
|
|
19299
19317
|
aria-current="${p === current ? "page" : "false"}"
|
|
@@ -19352,6 +19370,13 @@ var RelPagination = class extends RelElement {
|
|
|
19352
19370
|
if (to < total) pages.push(total);
|
|
19353
19371
|
return pages.map(String);
|
|
19354
19372
|
}
|
|
19373
|
+
/** Both dropdowns' panels may be wider than their 72px trigger: the longest
|
|
19374
|
+
value (`largest`), the row's 12px side padding, the 16px gap, the 18px
|
|
19375
|
+
check and 20px kept for a classic scrollbar (the page list scrolls past
|
|
19376
|
+
9 pages). */
|
|
19377
|
+
panelMinWidth(largest) {
|
|
19378
|
+
return `--rel-select-panel-min-width: calc(${String(Math.max(1, largest)).length}ch + 2 * var(--rel-spacing-sm) + var(--rel-spacing-md) + 38px)`;
|
|
19379
|
+
}
|
|
19355
19380
|
/* The inner rel-select fires its own composed `changed` / `rel-change`
|
|
19356
19381
|
({ value }). They must not reach the page as if the pagination had fired
|
|
19357
19382
|
them, so they stop at the select. */
|
|
@@ -19389,7 +19414,8 @@ var RelPagination = class extends RelElement {
|
|
|
19389
19414
|
size="medium"
|
|
19390
19415
|
label-style="none"
|
|
19391
19416
|
field-aria-label="Page (of ${total})"
|
|
19392
|
-
search
|
|
19417
|
+
no-search
|
|
19418
|
+
style=${this.panelMinWidth(total)}
|
|
19393
19419
|
.options=${this.pageOptions(total, current)}
|
|
19394
19420
|
.selected=${(0, import_live3.live)(String(current))}
|
|
19395
19421
|
.state=${this.disabled ? "disabled" : "default"}
|
|
@@ -19412,6 +19438,7 @@ var RelPagination = class extends RelElement {
|
|
|
19412
19438
|
label-style="none"
|
|
19413
19439
|
field-aria-label="${this.rowsPerPageLabel}"
|
|
19414
19440
|
no-search
|
|
19441
|
+
style=${this.panelMinWidth(Math.max(0, ...values.map(Number)))}
|
|
19415
19442
|
.options=${values}
|
|
19416
19443
|
.selected=${(0, import_live3.live)(String(this.perPage))}
|
|
19417
19444
|
.state=${this.disabled ? "disabled" : "default"}
|
|
@@ -19739,12 +19766,22 @@ RelPagination.styles = import_lit32.css`
|
|
|
19739
19766
|
}
|
|
19740
19767
|
}
|
|
19741
19768
|
|
|
19742
|
-
/*
|
|
19769
|
+
/* The ellipsis that marks a gap only the 480–768px window opens. */
|
|
19770
|
+
.pag-ellipsis.pag-ellipsis-narrow {
|
|
19771
|
+
display: none;
|
|
19772
|
+
}
|
|
19773
|
+
|
|
19774
|
+
/* 480–768px: shrink the number window to current ±1 plus first/last, with
|
|
19775
|
+
an ellipsis wherever that hides more than one page */
|
|
19743
19776
|
@container (min-width: 480px) and (max-width: 768px) {
|
|
19744
|
-
.pag-page-btn:not(.near):not(.edge):not([aria-current="page"]),
|
|
19777
|
+
.pag-page-btn:not(.near):not(.edge):not(.keep):not([aria-current="page"]),
|
|
19745
19778
|
.pag-ellipsis {
|
|
19746
19779
|
display: none;
|
|
19747
19780
|
}
|
|
19781
|
+
|
|
19782
|
+
.pag-numbers .pag-ellipsis.pag-ellipsis-narrow {
|
|
19783
|
+
display: inline-flex;
|
|
19784
|
+
}
|
|
19748
19785
|
}
|
|
19749
19786
|
|
|
19750
19787
|
/* <480px: swap to the compact layout automatically */
|
|
@@ -19768,10 +19805,14 @@ RelPagination.styles = import_lit32.css`
|
|
|
19768
19805
|
}
|
|
19769
19806
|
|
|
19770
19807
|
@media (min-width: 480px) and (max-width: 768px) {
|
|
19771
|
-
.pag-page-btn:not(.near):not(.edge):not([aria-current="page"]),
|
|
19808
|
+
.pag-page-btn:not(.near):not(.edge):not(.keep):not([aria-current="page"]),
|
|
19772
19809
|
.pag-ellipsis {
|
|
19773
19810
|
display: none;
|
|
19774
19811
|
}
|
|
19812
|
+
|
|
19813
|
+
.pag-numbers .pag-ellipsis.pag-ellipsis-narrow {
|
|
19814
|
+
display: inline-flex;
|
|
19815
|
+
}
|
|
19775
19816
|
}
|
|
19776
19817
|
|
|
19777
19818
|
@media (max-width: 479px) {
|
|
@@ -23360,27 +23401,23 @@ RelSignaturePad.styles = import_lit42.css`
|
|
|
23360
23401
|
border-color: var(--rel-border-strong);
|
|
23361
23402
|
}
|
|
23362
23403
|
|
|
23363
|
-
/* Error: the 2px danger border inside, at rest too, drawn
|
|
23364
|
-
|
|
23365
|
-
|
|
23366
|
-
focus stays visible
|
|
23404
|
+
/* Error: the 2px danger border inside, at rest too, drawn as ONE outline
|
|
23405
|
+
pulled 2px in like focus (outlines paint in forced colours). Focused in
|
|
23406
|
+
error, the same outline widens to 4px from 2px inside: a 2px danger
|
|
23407
|
+
ring outside on top of the inside edge, so focus stays visible
|
|
23408
|
+
(WCAG 2.4.7). One layer, so no seams between rings at any zoom (a
|
|
23409
|
+
border plus a pseudo element clipped by the pad's overflow plus an
|
|
23410
|
+
outline drew three bands with light gaps between them). */
|
|
23367
23411
|
.field.error .pad {
|
|
23368
23412
|
border-color: var(--rel-border-danger);
|
|
23369
|
-
|
|
23370
|
-
|
|
23371
|
-
.field.error .pad::after {
|
|
23372
|
-
content: "";
|
|
23373
|
-
position: absolute;
|
|
23374
|
-
inset: -1px;
|
|
23375
|
-
border: 2px solid var(--rel-border-danger);
|
|
23376
|
-
border-radius: inherit;
|
|
23377
|
-
pointer-events: none;
|
|
23413
|
+
outline: 2px solid var(--rel-border-danger);
|
|
23414
|
+
outline-offset: -2px;
|
|
23378
23415
|
}
|
|
23379
23416
|
|
|
23380
23417
|
.field.error .pad:focus,
|
|
23381
23418
|
.field.error.typing .pad:focus-within {
|
|
23382
|
-
outline
|
|
23383
|
-
outline-offset:
|
|
23419
|
+
outline: 4px solid var(--rel-border-danger);
|
|
23420
|
+
outline-offset: -2px;
|
|
23384
23421
|
}
|
|
23385
23422
|
|
|
23386
23423
|
/* Read-only: the edge on the page colour, one step fainter than subtle. */
|
|
@@ -25020,7 +25057,8 @@ RelSplitButton.styles = [RelButton.styles, import_lit45.css`
|
|
|
25020
25057
|
between the segments, so the pill is action + 1 + trigger wide. The
|
|
25021
25058
|
outlined segments drop their inner borders. Colours:
|
|
25022
25059
|
- secondary: the tone's outline border, and the outline's hover colour
|
|
25023
|
-
while
|
|
25060
|
+
while either segment is hovered or pressed, or the menu is open
|
|
25061
|
+
(decision Combo-G, extended to the chevron 2026-10-27);
|
|
25024
25062
|
- primary: the segment's label colour at full strength (Combo-B);
|
|
25025
25063
|
- static: the static label colour (white);
|
|
25026
25064
|
- ghost (no counterpart in the sandbox): --rel-border-subtle. */
|
|
@@ -25055,6 +25093,17 @@ RelSplitButton.styles = [RelButton.styles, import_lit45.css`
|
|
|
25055
25093
|
background: var(--rel-action-danger-border-outline-hover);
|
|
25056
25094
|
}
|
|
25057
25095
|
|
|
25096
|
+
/* The same for the chevron (Combo-G extended to the trigger, user
|
|
25097
|
+
2026-10-27): hovered, pressed or open, the divider takes its border
|
|
25098
|
+
colour, so the chevron shows four dark sides like the main action. */
|
|
25099
|
+
:host([variant="secondary"]) .divider:has(+ rel-popover button.toggle:is(:hover, :active, .is-open):not(:disabled)) {
|
|
25100
|
+
background: var(--rel-action-neutral-border-outline-hover);
|
|
25101
|
+
}
|
|
25102
|
+
|
|
25103
|
+
:host([variant="secondary"][tone="destructive"]) .divider:has(+ rel-popover button.toggle:is(:hover, :active, .is-open):not(:disabled)) {
|
|
25104
|
+
background: var(--rel-action-danger-border-outline-hover);
|
|
25105
|
+
}
|
|
25106
|
+
|
|
25058
25107
|
:host([variant="primary"]) .divider {
|
|
25059
25108
|
background: var(--rel-action-neutral-label-icons-fill-inverse);
|
|
25060
25109
|
}
|