@reliability-design/web 1.4.8 → 1.4.10
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 +214 -0
- package/custom-elements.json +18600 -0
- package/dist/components/rel-accordion/README.md +9 -2
- package/dist/components/rel-alert/README.md +5 -8
- package/dist/components/rel-autocomplete/README.md +209 -208
- package/dist/components/rel-avatar/README.md +228 -118
- package/dist/components/rel-breadcrumb/README.md +1 -0
- package/dist/components/rel-button/README.md +9 -9
- package/dist/components/rel-calendar/README.md +111 -109
- package/dist/components/rel-cardmedia/README.md +1 -1
- package/dist/components/rel-carousel/README.md +187 -186
- package/dist/components/rel-checkbox/README.md +159 -146
- package/dist/components/rel-chip/README.md +141 -138
- package/dist/components/rel-container/README.md +1 -1
- package/dist/components/rel-date-picker/README.md +221 -200
- package/dist/components/rel-drawer/README.md +4 -4
- package/dist/components/rel-kbd/README.md +188 -141
- package/dist/components/rel-layout/README.md +34 -34
- package/dist/components/rel-menu/README.md +17 -10
- package/dist/components/rel-menubar/README.md +218 -218
- package/dist/components/rel-otp/README.md +4 -8
- package/dist/components/rel-pagination/README.md +141 -100
- package/dist/components/rel-popover/README.md +220 -203
- package/dist/components/rel-radio/README.md +142 -131
- package/dist/components/rel-range-picker/README.md +194 -165
- package/dist/components/rel-resizable/README.md +220 -199
- package/dist/components/rel-segmented-button/README.md +158 -156
- package/dist/components/rel-select/README.md +22 -16
- package/dist/components/rel-sheet/README.md +3 -2
- package/dist/components/rel-signature-pad/README.md +161 -0
- package/dist/components/rel-slider/README.md +140 -131
- package/dist/components/rel-snackbar/README.md +170 -168
- package/dist/components/rel-split-button/README.md +129 -0
- package/dist/components/rel-stepper/README.md +171 -162
- package/dist/components/rel-switch/README.md +122 -117
- package/dist/components/rel-tab/README.md +184 -173
- package/dist/components/rel-textfield/README.md +23 -30
- package/dist/components/rel-time-picker/README.md +188 -164
- package/dist/components/rel-toast/README.md +20 -11
- package/dist/components/rel-tooltip/README.md +5 -4
- package/dist/components/rel-tree/README.md +157 -0
- package/dist/components/rel-upload/README.md +8 -5
- package/dist/index.d.mts +1698 -607
- package/dist/index.d.ts +1698 -607
- package/dist/index.js +12276 -6347
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +12218 -6296
- package/dist/index.mjs.map +1 -1
- package/dist/styles/motion.css +31 -0
- package/dist/styles/motion.tokens.json +38 -0
- package/dist/styles/vars.css +88 -64
- package/dist/{vars-DXX6QOAG.css → vars-E22LYFMV.css} +88 -64
- package/package.json +60 -37
- package/dist/styles/focus-ring.ts +0 -84
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,37 @@
|
|
|
1
1
|
import * as lit_html from 'lit-html';
|
|
2
2
|
import * as lit from 'lit';
|
|
3
|
-
import { LitElement, PropertyValues, TemplateResult } from 'lit';
|
|
3
|
+
import { LitElement, PropertyValues, PropertyDeclaration, TemplateResult } from 'lit';
|
|
4
4
|
export * from '@reliability-design/icons';
|
|
5
5
|
|
|
6
|
+
type KebabAlias = {
|
|
7
|
+
/** The kebab attribute that is observed in addition to the prop's own. */
|
|
8
|
+
kebab: string;
|
|
9
|
+
/** The reactive property it maps onto. */
|
|
10
|
+
prop: PropertyKey;
|
|
11
|
+
/** The prop's own (joined, legacy) attribute name, which keeps reflecting. */
|
|
12
|
+
legacy: string;
|
|
13
|
+
};
|
|
14
|
+
declare class RelElement extends LitElement {
|
|
15
|
+
/**
|
|
16
|
+
* Explicit kebab spellings the derivation can't reach, as
|
|
17
|
+
* `{ "kebab-name": "propName" }`; e.g. a prop whose own name is lowercase
|
|
18
|
+
* (`supportingtext`). Same behaviour as a derived alias, deprecation
|
|
19
|
+
* notice for the prop's own attribute included.
|
|
20
|
+
*/
|
|
21
|
+
static kebabAliases?: Readonly<Record<string, PropertyKey>>;
|
|
22
|
+
/** Props that must not get a derived kebab alias (adds to NO_KEBAB_ALIAS). */
|
|
23
|
+
static noKebabAlias?: readonly PropertyKey[];
|
|
24
|
+
/** The kebab aliases this class observes (for tests, docs and audit tools). */
|
|
25
|
+
static kebabAliasList(): KebabAlias[];
|
|
26
|
+
private static relAliasTables;
|
|
27
|
+
static get observedAttributes(): string[];
|
|
28
|
+
attributeChangedCallback(name: string, old: string | null, value: string | null): void;
|
|
29
|
+
private applyKebabAttribute;
|
|
30
|
+
protected update(changedProperties: PropertyValues): void;
|
|
31
|
+
static createProperty(name: PropertyKey, options?: PropertyDeclaration): void;
|
|
32
|
+
static getPropertyDescriptor(name: PropertyKey, key: string | symbol, options: PropertyDeclaration): PropertyDescriptor | undefined;
|
|
33
|
+
}
|
|
34
|
+
|
|
6
35
|
/**
|
|
7
36
|
* Single collapsible section (Figma "Accordion", 6021:1085): a clickable header
|
|
8
37
|
* that expands/collapses the slotted body with an animated chevron.
|
|
@@ -15,7 +44,7 @@ export * from '@reliability-design/icons';
|
|
|
15
44
|
* @csspart icon - The trailing icon wrapper
|
|
16
45
|
* @csspart content - The `role="region"` body that holds the default slot
|
|
17
46
|
*/
|
|
18
|
-
declare class RelAccordion extends
|
|
47
|
+
declare class RelAccordion extends RelElement {
|
|
19
48
|
/** Header text. Note it is also the native HTML `title` attribute, so browsers show it as a tooltip on hover. */
|
|
20
49
|
title: string;
|
|
21
50
|
/** Whether the body is expanded; toggled by the header and reported via `open-change`. Setting it from code does not fire the event. */
|
|
@@ -28,16 +57,12 @@ declare class RelAccordion extends LitElement {
|
|
|
28
57
|
size: "md" | "sm" | "large" | "medium" | "small";
|
|
29
58
|
/**
|
|
30
59
|
* Header layout (Figma "Type"): `default` = title + trailing rotating chevron; `action` = leading icon slot (rotating chevron by default) + static trailing arrow-expansion icon, with the body indented under the title.
|
|
31
|
-
*
|
|
32
|
-
* DELIBERATE DIVERGENCE — do not "fix" this to a button. For `Type=Action`
|
|
33
|
-
* Figma draws the trailing affordance as a full ghost icon Button instance
|
|
34
|
-
* (Size=Medium 40x40, Size=Small 32x32, Style=Ghost, Type=Icon Only); the
|
|
35
|
-
* code keeps a bare icon. Ruled by the user: our behaviour stands and the
|
|
36
|
-
* DESIGN FILE follows our docs here, not the other way round. The whole
|
|
37
|
-
* header is the click target, so a nested button would add a second
|
|
38
|
-
* focusable control inside it and two competing hit areas.
|
|
39
60
|
*/
|
|
40
61
|
type: "default" | "action";
|
|
62
|
+
/**
|
|
63
|
+
* Body treatment (Figma "Content Type"). `text` (default) styles the slotted body as copy: 0 / 16 / 16 / 16px padding, body-md type and the `--rel-text-body` colour. `custom` is for your own layout (a table, a form, a nested card): the body wrapper has no padding, sets no type or colour of its own (the slotted content inherits from the accordion's context), and has an 8px (`--rel-border-radius-sm`) corner radius. With `custom`, `type="action"` does not indent the body. Unknown values fall back to `text`.
|
|
64
|
+
*/
|
|
65
|
+
contentType: "text" | "custom";
|
|
41
66
|
/** Figma "Style" axis — named appearance because `style` collides with the HTML style attribute. `shadow` = 4px-radius card with the shadow-sm effect and no border; `plain` = square corners with a 1px border-subtle stroke and no elevation. */
|
|
42
67
|
appearance: "shadow" | "plain";
|
|
43
68
|
/** Figma "State=Disabled": dims the whole component to 40% and blocks toggling by pointer and keyboard. The header keeps its fill and stroke — the dulling is opacity alone, as Figma specifies. */
|
|
@@ -45,6 +70,18 @@ declare class RelAccordion extends LitElement {
|
|
|
45
70
|
static styles: lit.CSSResult;
|
|
46
71
|
/** Stable id prefix wiring the header to its panel. */
|
|
47
72
|
private accordionId;
|
|
73
|
+
/** Body geometry captured just before an open/close re-render: the start point of the animation. */
|
|
74
|
+
private bodyFrom?;
|
|
75
|
+
/** Bumped per toggle so a stale transitionend / timer cannot clear a newer animation's inline styles. */
|
|
76
|
+
private bodyAnimation;
|
|
77
|
+
protected willUpdate(changed: Map<string, unknown>): void;
|
|
78
|
+
protected updated(changed: Map<string, unknown>): void;
|
|
79
|
+
/**
|
|
80
|
+
* Animates max-height between the captured start and the measured end, then
|
|
81
|
+
* hands control back to the stylesheet (open = none, closed = 0). Measuring
|
|
82
|
+
* replaces the old fixed 1000px ceiling, which clipped taller bodies.
|
|
83
|
+
*/
|
|
84
|
+
private animateBody;
|
|
48
85
|
private toggle;
|
|
49
86
|
render(): lit_html.TemplateResult<1>;
|
|
50
87
|
}
|
|
@@ -64,7 +101,7 @@ type AlertToneInput = AlertTone | AlertToneAlias;
|
|
|
64
101
|
* @csspart action - The inline link; rendered only when both `url-text` and `url-href` are set
|
|
65
102
|
* @csspart close-button - The dismiss (✕) button; rendered only while `dismissible` is true
|
|
66
103
|
*/
|
|
67
|
-
declare class RelAlert extends
|
|
104
|
+
declare class RelAlert extends RelElement {
|
|
68
105
|
/**
|
|
69
106
|
* Semantic tone (Figma "Tone"): `"neutral"` (default) | `"info"` | `"success"` | `"warning"` | `"destructive"`. Drives the fill/border colour, the title colour and the leading icon (info, check-circle, alert-circle, error). `"error"`, `"danger"` and `"critical"` are deprecated aliases of `"destructive"` and log a one-time console notice. Takes precedence over the deprecated `type` prop.
|
|
70
107
|
*/
|
|
@@ -84,7 +121,7 @@ declare class RelAlert extends LitElement {
|
|
|
84
121
|
urlText?: string;
|
|
85
122
|
/** `href` of the inline link. The link appears only when both `urlText` and `urlHref` are set. */
|
|
86
123
|
urlHref?: string;
|
|
87
|
-
/** Shows the dismiss (✕) button. Defaults to true;
|
|
124
|
+
/** Shows the dismiss (✕) button. Defaults to true; `dismissible="false"` (or the property set to `false`) hides the button. */
|
|
88
125
|
dismissible: boolean;
|
|
89
126
|
/** True once the alert has been dismissed; hides the host via `:host([dismissed]) { display: none }`. Set it back to `false` to show the alert again. */
|
|
90
127
|
dismissed: boolean;
|
|
@@ -118,7 +155,7 @@ type FieldLabelStyle = "default" | "floating" | "none";
|
|
|
118
155
|
* @slot prefix - Custom content at the far left of the control (e.g. a unit dropdown); shares the prefix block with `prefixIcon` / `prefixText`. Hidden when `multiline` is set.
|
|
119
156
|
* @slot suffix - Custom content at the far right of the control (e.g. an action button); shares the suffix block with `rightIcon` / `suffixText`. Hidden when `multiline` is set.
|
|
120
157
|
* @csspart label - The visible label element (default and floating label styles)
|
|
121
|
-
* @csspart control - The bordered control box
|
|
158
|
+
* @csspart control - The bordered control box. **Changed in 1.4.9:** in `variant="legend"` this is now the same `div` as every other variant, not the `fieldset` — the fieldset was demoted to a decorative outline layer behind the content so the control sits on the 32/40/48 size ladder and centres its value like the other variants. `::part(control)` still matches; only rules that depended on it being a fieldset do not.
|
|
122
159
|
* @csspart input - The native input / textarea
|
|
123
160
|
* @csspart prefix - The prefix block (leading icon, prefix text and the `prefix` slot)
|
|
124
161
|
* @csspart suffix - The suffix block (suffix text, trailing icon and the `suffix` slot)
|
|
@@ -126,9 +163,9 @@ type FieldLabelStyle = "default" | "floating" | "none";
|
|
|
126
163
|
* @csspart helper - The helper / error text line below the control
|
|
127
164
|
* @csspart helper-icon - The leading `rel-icon` in the helper line; rendered only when `helper-icon` is set and there is helper text
|
|
128
165
|
* @cssprop --rel-field-label-reserve - Height held for the label row whenever no label renders above the control — `labelStyle="none"`, and `labelStyle="floating"` where the label sits inside the control — so the control still lines up with labelled siblings in a form row. Defaults to that size's label line-height plus the wrapper gap (24px at `small`, 26px at `medium` and `large`). Set to `0` to collapse the row entirely (toolbars, table cells).
|
|
129
|
-
* @cssprop --rel-textfield-surface - Colour the floating label's
|
|
166
|
+
* @cssprop --rel-textfield-surface - Colour of the strip the floating label lays over the control's top border and focus ring so the label appears to sit in a notch. It overshoots the band by 2px on the page side, so it must match the surface the field sits on; defaults to the control's own fill (`--rel-bg-neutral`). Set it on a tinted or elevated surface, otherwise the strip shows as a light dash across the border.
|
|
130
167
|
*/
|
|
131
|
-
declare class RelTextfield extends
|
|
168
|
+
declare class RelTextfield extends RelElement {
|
|
132
169
|
/**
|
|
133
170
|
* Visible label text. Rendered above the control (default), inside it as a
|
|
134
171
|
* floating label (`labelStyle="floating"`) or as the notch of the `legend`
|
|
@@ -271,11 +308,19 @@ type CheckboxDensity = "compact" | "comfortable";
|
|
|
271
308
|
type CheckboxAlignment = "leading" | "trailing";
|
|
272
309
|
/**
|
|
273
310
|
* Tri-state checkbox (Figma "Checkbox"): a hidden native checkbox behind a custom box, with label, optional prefix icon and supporting text.
|
|
311
|
+
* Form-associated, so an outer `<label>` (wrapping it, or `for=`) toggles it and names it; it still sets no form value and is not submitted.
|
|
274
312
|
* @csspart base - The outer wrapper that carries the `state` / `status` classes
|
|
275
313
|
* @csspart label - The visible label text
|
|
276
314
|
* @csspart helper - The supporting text (rendered beside the box in comfortable density, under the row in compact)
|
|
277
315
|
*/
|
|
278
|
-
declare class RelCheckbox extends
|
|
316
|
+
declare class RelCheckbox extends RelElement {
|
|
317
|
+
/** Form-associated only so an outer `<label>` has a control (see utils/outer-label.ts). No form value is set. */
|
|
318
|
+
static formAssociated: boolean;
|
|
319
|
+
/** `supporting-text` is the canonical attribute; the prop's own lowercase
|
|
320
|
+
* name means RelElement can't derive it, so it is declared here. */
|
|
321
|
+
static kebabAliases: {
|
|
322
|
+
"supporting-text": string;
|
|
323
|
+
};
|
|
279
324
|
/** Label text rendered next to the box. */
|
|
280
325
|
label: string;
|
|
281
326
|
/** rel-icon name rendered between the checkbox and the label (label prefix icon); scales with `size`. Unset renders no icon and reserves no space. */
|
|
@@ -284,16 +329,19 @@ declare class RelCheckbox extends LitElement {
|
|
|
284
329
|
supportingtext: string;
|
|
285
330
|
/** Visual and interaction state (Figma State): `"error"` swaps in the danger colours, `"disabled"` blocks input and dims the whole control to 0.4 opacity (colours unchanged, as Figma specifies). */
|
|
286
331
|
state: CheckboxState;
|
|
332
|
+
/** Disables the checkbox exactly as `state="disabled"` does (`state` stays the documented spelling). Either one disables it, and so does an ancestor `<fieldset disabled>`; none of them changes the others. New in 1.5.0. */
|
|
333
|
+
disabled: boolean;
|
|
287
334
|
/** Check state. `"indeterminate"` is programmatic-only — a user toggle always resolves to checked or unchecked. */
|
|
288
335
|
status: CheckboxStatus;
|
|
289
336
|
/** Value reported in the `rel-change` event detail (it is not submitted with a form). */
|
|
290
337
|
value: string;
|
|
291
338
|
/** Control scale (Figma Size), on Figma's four-step ramp of control frames:
|
|
292
339
|
* `"small"` 16px / body-sm, `"medium"` (default) 18px / body-md,
|
|
293
|
-
* `"large"` 20px / body-lg, `"extra-large"` 24px / body-xl.
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
340
|
+
* `"large"` 20px / body-lg, `"extra-large"` 24px / body-xl. Supporting
|
|
341
|
+
* text sits one body step below the label at every size (body-xs / sm /
|
|
342
|
+
* md / lg, i.e. 10 / 12 / 14 / 16px). The drawn square is inset to 80% of
|
|
343
|
+
* the frame, so the frame is the layout footprint (what the row gap and the
|
|
344
|
+
* compact indent measure from) rather than the visible square. */
|
|
297
345
|
size: CheckboxSize;
|
|
298
346
|
/** Supporting-text layout (Figma Density). `"compact"` (default) puts the
|
|
299
347
|
* supporting text on its own line under the row, indented past the box;
|
|
@@ -304,11 +352,44 @@ declare class RelCheckbox extends LitElement {
|
|
|
304
352
|
* Trailing has no compact layout in the spec, so it always renders with
|
|
305
353
|
* comfortable density. */
|
|
306
354
|
alignment: CheckboxAlignment;
|
|
355
|
+
/** Accessible name for the native checkbox, for when the visible `label` is
|
|
356
|
+
* absent or not a usable name on its own — a checkbox in a table row, or one
|
|
357
|
+
* whose meaning comes from its column header.
|
|
358
|
+
*
|
|
359
|
+
* Normally unnecessary: the input is wrapped in the `<label>` that
|
|
360
|
+
* renders `label`, so the visible text already names it natively. Setting
|
|
361
|
+
* this puts an `aria-label` on the input, which OVERRIDES that wrapping
|
|
362
|
+
* label — so set it only when the visible text is the wrong name, not to
|
|
363
|
+
* repeat it. Left unset the attribute is not emitted at all.
|
|
364
|
+
*
|
|
365
|
+
* An outer `<label>` (wrapping the checkbox, or `for=`) names it only when
|
|
366
|
+
* neither this nor a visible `label` is set. */
|
|
367
|
+
fieldAriaLabel?: string;
|
|
368
|
+
/**
|
|
369
|
+
* camelCase alias of `supportingtext`, matching rel-textfield and rel-select.
|
|
370
|
+
* The declared property is lowercase, so `el.supportingText = "…"`, lit
|
|
371
|
+
* `.supportingText=${…}` and Angular `[supportingText]` used to set an unused
|
|
372
|
+
* expando and render nothing. Reading or writing either name now hits the same
|
|
373
|
+
* reactive property; the attribute stays `supportingtext`.
|
|
374
|
+
*/
|
|
375
|
+
get supportingText(): string;
|
|
376
|
+
set supportingText(val: string);
|
|
307
377
|
/** Boolean view of `status`: `true` when `status === "checked"`; setting it writes `"checked"` / `"unchecked"`. */
|
|
308
378
|
get checked(): boolean;
|
|
309
379
|
set checked(val: boolean);
|
|
310
380
|
private _onChange;
|
|
311
381
|
private _onTouched;
|
|
382
|
+
private readonly internals;
|
|
383
|
+
/** A click on an outer label arrives at the host; route it through the
|
|
384
|
+
* native input so it runs the same `toggle()` a direct click does. */
|
|
385
|
+
private readonly outerLabel;
|
|
386
|
+
/** `state="disabled"`, the `disabled` property, or an ancestor `<fieldset disabled>`. */
|
|
387
|
+
private get isDisabled();
|
|
388
|
+
/** @internal Form-associated lifecycle: an ancestor `<fieldset disabled>` disables the control too (utils/outer-label.ts, 3). */
|
|
389
|
+
formDisabledCallback(): void;
|
|
390
|
+
/** fieldAriaLabel wins; then the visible label (native, via the inner
|
|
391
|
+
* <label>, so no attribute); then an outer <label>'s text. */
|
|
392
|
+
private get inputAriaLabel();
|
|
312
393
|
static styles: lit.CSSResult;
|
|
313
394
|
protected willUpdate(changed: PropertyValues<this>): void;
|
|
314
395
|
/** Trailing has no compact layout in the spec — trailing wins. */
|
|
@@ -323,6 +404,8 @@ declare class RelCheckbox extends LitElement {
|
|
|
323
404
|
render(): lit_html.TemplateResult<1>;
|
|
324
405
|
}
|
|
325
406
|
|
|
407
|
+
/** Status badge on the avatar's bottom-right edge (Figma ".Avatar Badge" Type). `""` = none. */
|
|
408
|
+
type AvatarBadge = "" | "dot" | "icon";
|
|
326
409
|
/** Diameter step, spelled out. */
|
|
327
410
|
type AvatarSize = "large" | "medium" | "small" | "extra-small";
|
|
328
411
|
/** Alternative spellings, not deprecations — the short names keep working. */
|
|
@@ -330,8 +413,11 @@ type AvatarSizeAlias = "lg" | "md" | "sm" | "xs";
|
|
|
330
413
|
type AvatarSizeInput = AvatarSize | AvatarSizeAlias;
|
|
331
414
|
/**
|
|
332
415
|
* Circular avatar (Figma "Avatar"): shows a photo, text initials or a slotted icon in one of four sizes and three fill variants.
|
|
333
|
-
* @slot - Icon content rendered when `type="icon"` (typically an inline SVG, sized 20 / 18 / 16 / 12px by `size`)
|
|
416
|
+
* @slot - Icon content rendered when `type="icon"` (typically an inline SVG, sized 20 / 18 / 16 / 12px by `size`); not rendered when the `icon` attribute is set
|
|
334
417
|
* @csspart base - The circular wrapper that carries the size, variant and inline `bg` / `color` overrides
|
|
418
|
+
* @csspart badge - The status badge on the bottom-right edge, rendered when `badge` is set (new in 1.5.0)
|
|
419
|
+
* @cssprop --rel-avatar-ring-color - Colour of the `ring`; defaults to `--rel-border-inverse` (new in 1.5.0)
|
|
420
|
+
* @cssprop --rel-avatar-badge-bg - Fill of the `badge`; defaults to `--rel-bg-success` for `dot` and `--rel-bg-neutral-elevated-2` for `icon` (new in 1.5.0)
|
|
335
421
|
* @csspart icon - The `<img>` (`type="image"`) or the icon wrapper span around the slot (`type="icon"`)
|
|
336
422
|
* @csspart label - The `<span>` holding the initials when `type="text"`
|
|
337
423
|
* @cssprop --rel-avatar-bg-fill - Background colour of the `fill` variant
|
|
@@ -345,7 +431,7 @@ type AvatarSizeInput = AvatarSize | AvatarSizeAlias;
|
|
|
345
431
|
* @cssprop --rel-avatar-size - Overrides the circle's width/height for sizes between (or below) the `size` presets; defaults to the preset's diameter
|
|
346
432
|
* @cssprop --rel-avatar-font-size - Overrides the initials' font-size, for use alongside `--rel-avatar-size`; defaults to the preset's text role
|
|
347
433
|
*/
|
|
348
|
-
declare class RelAvatar extends
|
|
434
|
+
declare class RelAvatar extends RelElement {
|
|
349
435
|
/** Diameter step: `large` 40px, `medium` 32px, `small` 24px, `extra-small` 20px; each binds the matching body-*-semibold text role for initials. `lg` / `md` / `sm` / `xs` are alternative spellings and stay supported — they are normalised to the full words, not deprecated. */
|
|
350
436
|
size: AvatarSizeInput;
|
|
351
437
|
/** What is rendered inside the circle: `image` shows `src`, `text` shows the `text` initials, `icon` shows the default slot. */
|
|
@@ -362,6 +448,16 @@ declare class RelAvatar extends LitElement {
|
|
|
362
448
|
bg: string;
|
|
363
449
|
/** Any CSS colour applied inline as `color` on the circle (initials / icon), overriding the variant text colour. */
|
|
364
450
|
color: string;
|
|
451
|
+
/** New in 1.5.0. rel-icon name shown for `type="icon"` (Figma's "Icon" swap, e.g. `person`), as an alternative to slotting an SVG. When set it replaces the slot. */
|
|
452
|
+
icon: string;
|
|
453
|
+
/** New in 1.5.0. Figma "Show Ring": a 2px ring in `--rel-border-inverse` just outside the circle, which separates overlapping avatars. It does not change the avatar's size. */
|
|
454
|
+
ring: boolean;
|
|
455
|
+
/** New in 1.5.0. Figma "Show Badge": a status badge on the bottom-right edge with a 1px `--rel-border-inverse` edge. `dot` is a `--rel-bg-success` disc; `icon` is a `--rel-bg-neutral-elevated-2` disc holding `badge-icon`. 12 / 10 / 8 / 6px for large / medium / small / extra-small. Empty (the default) renders none. */
|
|
456
|
+
badge: AvatarBadge;
|
|
457
|
+
/** New in 1.5.0. rel-icon name inside a `badge="icon"` badge. */
|
|
458
|
+
badgeIcon: string;
|
|
459
|
+
/** New in 1.5.0. What the badge means, for screen readers (e.g. "Online"). Without it the badge is decorative and hidden from assistive technology, because a dot conveys its meaning by colour alone. */
|
|
460
|
+
badgeLabel: string;
|
|
365
461
|
static styles: lit.CSSResult;
|
|
366
462
|
/** Alternative spellings, NOT deprecations — no console notice. Normalising
|
|
367
463
|
* the property rather than duplicating every selector keeps the reflected
|
|
@@ -369,6 +465,7 @@ declare class RelAvatar extends LitElement {
|
|
|
369
465
|
* the CSS. Same shape as rel-chip and rel-slider. */
|
|
370
466
|
protected willUpdate(changed: Map<string, unknown>): void;
|
|
371
467
|
render(): lit_html.TemplateResult<1>;
|
|
468
|
+
private renderBadge;
|
|
372
469
|
}
|
|
373
470
|
|
|
374
471
|
/** Canonical semantic tones (Figma "Tone"): neutral | destructive | warning | success | info. */
|
|
@@ -394,12 +491,15 @@ type ChipBorder = "default" | "rounded";
|
|
|
394
491
|
* @csspart base - The chip body (`.chip`) that carries size, tone, variant and border styling
|
|
395
492
|
* @csspart icon - The leading `<rel-icon>` (rendered only when `leading-icon` is set and no avatar)
|
|
396
493
|
* @csspart label - The label text
|
|
494
|
+
* @csspart remove - The remove `<button>` (rendered only when `removable`)
|
|
397
495
|
* @cssprop --rel-chip-focus-ring - Colour of the keyboard focus outline; default `var(--rel-border-focus)`
|
|
398
496
|
*/
|
|
399
|
-
declare class RelChip extends
|
|
497
|
+
declare class RelChip extends RelElement {
|
|
400
498
|
static shadowRootOptions: ShadowRootInit;
|
|
401
499
|
/** Text shown in the chip; also its accessible name and the drag payload. */
|
|
402
500
|
label: string;
|
|
501
|
+
/** Accessible name for an icon-only or intentionally unlabelled chip; overrides `label` for the chip and its remove button. */
|
|
502
|
+
fieldAriaLabel?: string;
|
|
403
503
|
/** Colour tone (Figma Tone): `neutral`, `destructive`, `warning`, `success` or `info`. Combined with `variant`. `"danger"` is a deprecated alias of `"destructive"`: it keeps working, logs a one-time console notice, and is normalised to `"destructive"` on the property and the reflected attribute. */
|
|
404
504
|
tone: ChipToneInput;
|
|
405
505
|
/** Emphasis (Figma Style): `fill` = solid tone background, `subtle` = tinted background with tone-coloured text. Figma's own spellings `primary` and `secondary` are accepted and normalised to `fill` / `subtle`. */
|
|
@@ -416,6 +516,8 @@ declare class RelChip extends LitElement {
|
|
|
416
516
|
avatar?: string;
|
|
417
517
|
/** Shows a remove (close) button after the label; clicking it sets `removed` and fires `removed`. */
|
|
418
518
|
removable: boolean;
|
|
519
|
+
/** New in 1.5.0. Makes the chip body plain text: no `button` role, no Tab stop, no Enter / Space / Delete handling and no host click re-dispatch. The remove button (when `removable`) stays a real button. For chips that only display a value inside another control, e.g. rel-select's multi-select chips. */
|
|
520
|
+
presentational: boolean;
|
|
419
521
|
/** `true` once the chip has been removed — the host is hidden via `:host([removed])`. Reflected so CSS and Angular can see it; reset to `false` to show the chip again. */
|
|
420
522
|
removed: boolean;
|
|
421
523
|
/** Opt-in native drag-and-drop: sets `draggable="true"` on the host, shows the Figma "Dragged" state during a real drag gesture, and makes Left/Right arrow keys fire `chip-move`. */
|
|
@@ -447,7 +549,7 @@ declare global {
|
|
|
447
549
|
* An item is a plain string or any object read through displayField/valueField.
|
|
448
550
|
* Two keys are read off objects directly, whatever those fields are named:
|
|
449
551
|
* `icon` (a `rel-icon` name shown before the label) and `disabled` (`true`
|
|
450
|
-
* renders the row
|
|
552
|
+
* renders the row's text in `--rel-text-disabled`, icon unchanged, and makes it unselectable by click or keyboard).
|
|
451
553
|
*/
|
|
452
554
|
type AutocompleteItem = string | Record<string, unknown>;
|
|
453
555
|
type AutocompleteFilter = "contains" | "starts-with" | "none";
|
|
@@ -486,8 +588,9 @@ type AutocompleteSearchFn = (query: string) => Promise<AutocompleteItem[]>;
|
|
|
486
588
|
* @cssprop --rel-autocomplete-icon-color - Colour of a row's leading `icon`
|
|
487
589
|
* @cssprop --rel-autocomplete-status-color - Colour of the loading / no-results status rows
|
|
488
590
|
* @cssprop --rel-autocomplete-menu-max-height - Scroll ceiling of the suggestion panel; default `360px`. Code-owned rather than Figma-derived — every Figma Menu variant hugs its content with no ceiling, which is not shippable for an unbounded result list.
|
|
591
|
+
* @cssprop --rel-overlay-fallback-z - z-index of the panel on the **no-Popover-API fallback path only**. Wherever the browser top layer is available the panel is promoted into it and this value is inert, because top-layer elements are not in the page stacking order at all. Shared with the other overlays (select, autocomplete, the three pickers) so the whole family can be moved from one place.
|
|
489
592
|
*/
|
|
490
|
-
declare class RelAutocomplete extends
|
|
593
|
+
declare class RelAutocomplete extends RelElement {
|
|
491
594
|
/** Local (or fallback initial) suggestion list. Ignored while searchFn drives results. Object items are read through `displayField` / `valueField` plus the fixed keys `icon`, `disabled` and `supportingText` (the last renamable via `supporting-field`); `supportingText` renders as a second line in the row and is matched by the filter alongside the label. */
|
|
492
595
|
items: AutocompleteItem[];
|
|
493
596
|
/** Committed value — the selected item's valueField string ("" = none). */
|
|
@@ -516,7 +619,7 @@ declare class RelAutocomplete extends LitElement {
|
|
|
516
619
|
* THE TEXT INPUT STAYS A SEARCH BOX. In single mode the input shows the
|
|
517
620
|
* selected label, which is the point of a type-ahead; in multi mode there is
|
|
518
621
|
* no single label to show, and writing a value list into the field would
|
|
519
|
-
* destroy the query the user is typing. `rel-select` can
|
|
622
|
+
* destroy the query the user is typing. `rel-select` can lay chips over its
|
|
520
623
|
* trigger because a trigger is not an editable surface — an input is. So the
|
|
521
624
|
* chips render beneath the field, the query clears after each toggle so the
|
|
522
625
|
* next search starts fresh, and the panel stays open.
|
|
@@ -601,7 +704,7 @@ declare class RelAutocomplete extends LitElement {
|
|
|
601
704
|
private addGlobalListeners;
|
|
602
705
|
private removeGlobalListeners;
|
|
603
706
|
private onOutsidePointerDown;
|
|
604
|
-
private
|
|
707
|
+
private scrollWatch;
|
|
605
708
|
private openPanel;
|
|
606
709
|
private closePanel;
|
|
607
710
|
private showNativePopover;
|
|
@@ -627,6 +730,11 @@ declare class RelAutocomplete extends LitElement {
|
|
|
627
730
|
* and once that ramp was realigned to Figma the compensation became the bug.
|
|
628
731
|
*/
|
|
629
732
|
private get optionCheckboxSize();
|
|
733
|
+
/** Native tooltip carrying the row's full text. Both lines truncate to one
|
|
734
|
+
* line with an ellipsis, so a long supporting line is otherwise unrecoverable
|
|
735
|
+
* by sight; hovering the row reveals it. Only rows that carry a second line
|
|
736
|
+
* get one, so plain lists do not sprout tooltips. */
|
|
737
|
+
private rowTitle;
|
|
630
738
|
private get selectAllStatus();
|
|
631
739
|
private toggleMultiOption;
|
|
632
740
|
private toggleSelectAll;
|
|
@@ -654,6 +762,38 @@ declare global {
|
|
|
654
762
|
}
|
|
655
763
|
}
|
|
656
764
|
|
|
765
|
+
/**
|
|
766
|
+
* New in 1.5.0. A row of overlapping avatars (Figma "Avatar Group", 9243:85), with an optional "+N" circle for the people not shown. Slot `rel-avatar` elements into it: the group gives each one its `size` and a `ring`, overlaps them by a quarter of the diameter, and hides those beyond `max`.
|
|
767
|
+
* @slot - The `rel-avatar` elements, in display order
|
|
768
|
+
* @csspart base - The `role="group"` row holding the avatars and the overflow circle
|
|
769
|
+
* @csspart overflow - The "+N" circle (a `rel-avatar` of `type="text"`, `variant="fill"`) shown when people are not displayed
|
|
770
|
+
* @cssprop --rel-avatar-group-overlap - How far each avatar overlaps the previous one (a positive length); defaults to Figma's 10 / 8 / 6 / 4px for large / medium / small / extra-small
|
|
771
|
+
*/
|
|
772
|
+
declare class RelAvatarGroup extends RelElement {
|
|
773
|
+
/** Diameter step given to every avatar in the group and to the "+N" circle: `large` 40px, `medium` 32px, `small` 24px, `extra-small` 20px. `lg` / `md` / `sm` / `xs` are accepted and normalised to the full words. */
|
|
774
|
+
size: AvatarSizeInput;
|
|
775
|
+
/** Most avatars to show; the rest are hidden and counted in the "+N" circle. `0` (the default) shows them all. */
|
|
776
|
+
max: number;
|
|
777
|
+
/** The full number of people when only some avatars are slotted (e.g. 3 slotted of 57). The "+N" circle then counts everyone not shown. `0` (the default) counts the slotted avatars only. */
|
|
778
|
+
total: number;
|
|
779
|
+
/** Accessible name of the group (e.g. "Project members"). No default: without it the group has no name. */
|
|
780
|
+
label: string;
|
|
781
|
+
/** Accessible name of the "+N" circle; `{n}` is replaced by the count. */
|
|
782
|
+
overflowLabel: string;
|
|
783
|
+
private avatarCount;
|
|
784
|
+
static styles: lit.CSSResult;
|
|
785
|
+
private get avatars();
|
|
786
|
+
private get visibleCount();
|
|
787
|
+
/** People counted in the "+N" circle. */
|
|
788
|
+
get overflowCount(): number;
|
|
789
|
+
protected willUpdate(changed: PropertyValues<this>): void;
|
|
790
|
+
protected updated(changed: PropertyValues<this>): void;
|
|
791
|
+
/** Give every slotted avatar the group's size and a ring, and hide the ones beyond `max`. */
|
|
792
|
+
private syncAvatars;
|
|
793
|
+
private onSlotChange;
|
|
794
|
+
render(): lit_html.TemplateResult<1>;
|
|
795
|
+
}
|
|
796
|
+
|
|
657
797
|
/** Canonical size steps — full words, as elsewhere in the library. */
|
|
658
798
|
type BadgeSize = "small" | "medium" | "large" | "extra-large";
|
|
659
799
|
/** Short size spellings, accepted as alternatives. */
|
|
@@ -666,7 +806,7 @@ type BadgeSizeInput = BadgeSize | BadgeSizeAlias;
|
|
|
666
806
|
* @cssprop --rel-badge-color - Text colour of the count; the `text-color` prop writes this on the host
|
|
667
807
|
* @cssprop --rel-badge-dot-size - Diameter of the `dot` variant; default 6px, the single dot size Figma draws. Set it to restore the larger discs shipped previously.
|
|
668
808
|
*/
|
|
669
|
-
declare class RelBadge extends
|
|
809
|
+
declare class RelBadge extends RelElement {
|
|
670
810
|
/** Text shown in the `number` variant (a count such as "5" or "99+"); not rendered by `variant="dot"` but still used to build the accessible name. */
|
|
671
811
|
number: string;
|
|
672
812
|
/** Explicit accessible name; when empty it is composed as "<number> <suffix>" or, with no number, "New <suffix>". Attribute is `arialabel`. */
|
|
@@ -708,9 +848,11 @@ interface BreadcrumbItem {
|
|
|
708
848
|
* @csspart base - The `<nav>` landmark wrapping the ordered list.
|
|
709
849
|
* @csspart label - The non-link current-page text (`aria-current="page"`), also used for any item without a `url`.
|
|
710
850
|
*/
|
|
711
|
-
declare class RelBreadcrumbs extends
|
|
851
|
+
declare class RelBreadcrumbs extends RelElement {
|
|
712
852
|
/** Ordered trail, root first: `{ label: string; url?: string }[]`. Items with a `url` render as links except the last one, which is always the current page (and never a link). Set as a property — arrays do not survive attribute serialisation. */
|
|
713
853
|
items: BreadcrumbItem[];
|
|
854
|
+
/** Name the trail when several breadcrumb landmarks share a page. */
|
|
855
|
+
ariaLabel: string;
|
|
714
856
|
static styles: lit.CSSResult;
|
|
715
857
|
render(): lit_html.TemplateResult<1>;
|
|
716
858
|
}
|
|
@@ -739,7 +881,7 @@ type ButtonTone = "default" | "primary" | "secondary" | "critical" | "success" |
|
|
|
739
881
|
* @csspart indicator - The loading spinner, rendered only while `loading` is set.
|
|
740
882
|
* @cssprop --rel-button-min-width - Overrides the per-size minimum width (Figma small/medium/large = 80/100/120px, ghost small = 56px). Ignored by `icon-only` and `link`.
|
|
741
883
|
*/
|
|
742
|
-
declare class RelButton extends
|
|
884
|
+
declare class RelButton extends RelElement {
|
|
743
885
|
/** Style axis (Figma "Style"). Canonical: `default` (legacy neutral fill), `primary`, `secondary` (outlined), `ghost` (text-only), `link` (underlined inline text), `static` (transparent, static-light label for dark/colored surfaces). Deprecated aliases still accepted: `outline` = secondary, `text` = ghost, and `icon` (pre-2.0 40px circular icon button — use `icon-only` with a style instead). */
|
|
744
886
|
variant: ButtonVariant;
|
|
745
887
|
/**
|
|
@@ -787,9 +929,10 @@ declare class RelButton extends LitElement {
|
|
|
787
929
|
* @csspart action - The previous-month and next-month buttons
|
|
788
930
|
* @csspart label - The month/year heading and each weekday column header
|
|
789
931
|
* @csspart list - The weekday-header row and the day grid
|
|
790
|
-
* @csspart item - Each day cell button
|
|
932
|
+
* @csspart item - Each day cell button (unavailable days also carry `unavailable`)
|
|
933
|
+
* @csspart unavailable - Day cells that cannot be picked (outside `min` / `max`, or blocked by `isDateDisabled`), alongside `item`. They are `aria-disabled` and stay focusable, so `::part(item):disabled` does not match them; style them with `::part(unavailable)`
|
|
791
934
|
*/
|
|
792
|
-
declare class RelCalendar extends
|
|
935
|
+
declare class RelCalendar extends RelElement {
|
|
793
936
|
/** Selected date as an ISO `YYYY-MM-DD` string, or `null` for no selection; setting it also moves the visible month. */
|
|
794
937
|
value: string | null;
|
|
795
938
|
/** Earliest selectable date (ISO `YYYY-MM-DD`); earlier days render disabled. */
|
|
@@ -823,13 +966,57 @@ declare class RelCalendar extends LitElement {
|
|
|
823
966
|
private announceMonth;
|
|
824
967
|
private previousMonth;
|
|
825
968
|
private nextMonth;
|
|
969
|
+
/**
|
|
970
|
+
* A click is an interaction with that day even when the day cannot be
|
|
971
|
+
* picked, so it takes the Tab stop first. Set explicitly rather than left to
|
|
972
|
+
* handleDayGridFocusin because Safari does not focus a button on click.
|
|
973
|
+
*/
|
|
974
|
+
private handleDayClick;
|
|
826
975
|
private selectDay;
|
|
827
|
-
private
|
|
976
|
+
private dayButtonHasFocus;
|
|
977
|
+
/**
|
|
978
|
+
* Day-grid keys. Movement is by DATE, never by grid index (an index
|
|
979
|
+
* addresses a different date once the view flips month). The key map is
|
|
980
|
+
* period-page's dayGridTarget, shared with rel-date-picker and
|
|
981
|
+
* rel-range-picker: arrows ±1/±7 days, Home/End the week (honouring
|
|
982
|
+
* `week-start`), PageUp/PageDown a month, Shift+PageUp/PageDown a year,
|
|
983
|
+
* clamped to the target month's last day.
|
|
984
|
+
*/
|
|
985
|
+
private handleDayKeydown;
|
|
986
|
+
/**
|
|
987
|
+
* Move the rove AND focus to `date`, flipping the view when the date has left
|
|
988
|
+
* the visible month. Same shape as the pickers' moveGridFocusTo, and the
|
|
989
|
+
* order matters: `focusedDate` is set from the date BEFORE focus moves,
|
|
990
|
+
* because lit reuses the day buttons across the month re-render, so the
|
|
991
|
+
* focused element may not change and no focus event would fire to record it.
|
|
992
|
+
*/
|
|
993
|
+
private moveGridFocusTo;
|
|
994
|
+
/**
|
|
995
|
+
* Focus arriving any other way — a click, Tab / Shift+Tab, or a programmatic
|
|
996
|
+
* focus() — moves the Tab stop to that day too, so Tab out of the grid and
|
|
997
|
+
* back returns to the day last interacted with. This catches every case in
|
|
998
|
+
* which the focused ELEMENT changes; the one case where it does not (a month
|
|
999
|
+
* flip that reuses the focused button) is covered by moveGridFocusTo setting
|
|
1000
|
+
* the date first.
|
|
1001
|
+
*/
|
|
1002
|
+
private handleDayGridFocusin;
|
|
828
1003
|
/**
|
|
829
|
-
* Index of the single grid cell carrying tabindex="0"
|
|
1004
|
+
* Index of the single grid cell carrying tabindex="0": the day last
|
|
1005
|
+
* interacted with (`focusedDate`), else the selection, else today, else the
|
|
1006
|
+
* first enabled day of the month, else the first cell. The old expression
|
|
830
1007
|
* (`isSelected || (index === 0 && !focusedDate)`) left the grid with ZERO
|
|
831
|
-
* tab stops once the user arrowed around without a selection
|
|
832
|
-
*
|
|
1008
|
+
* tab stops once the user arrowed around without a selection; the trailing
|
|
1009
|
+
* fallback keeps it at exactly one by construction.
|
|
1010
|
+
*
|
|
1011
|
+
* `focusedDate` is written by moveGridFocusTo (arrows / Home / End / Page
|
|
1012
|
+
* keys, from the date, before focus moves), handleDayClick and
|
|
1013
|
+
* handleDayGridFocusin (Tab or any other focus route), the same model as
|
|
1014
|
+
* rel-date-picker and rel-range-picker. It counts wherever it sits in the
|
|
1015
|
+
* 42-cell grid, out-of-month cells included: every date appears at most
|
|
1016
|
+
* once, so this cannot create a second Tab stop, and after a chevron the
|
|
1017
|
+
* day last used stays the Tab stop while it is still on screen. Unavailable
|
|
1018
|
+
* days are aria-disabled, not native disabled, so a Tab stop on one is still
|
|
1019
|
+
* reachable.
|
|
833
1020
|
*/
|
|
834
1021
|
private getRovingIndex;
|
|
835
1022
|
render(): lit_html.TemplateResult<1>;
|
|
@@ -844,7 +1031,7 @@ declare class RelCalendar extends LitElement {
|
|
|
844
1031
|
* @csspart header - The media region wrapper (present only when `type="media"`)
|
|
845
1032
|
* @csspart content - The padded body that wraps the default slot
|
|
846
1033
|
*/
|
|
847
|
-
declare class RelCard extends
|
|
1034
|
+
declare class RelCard extends RelElement {
|
|
848
1035
|
/**
|
|
849
1036
|
* Figma "Type" axis: custom (default) renders slotted content with card
|
|
850
1037
|
* padding; media adds a flush media region (slot name="media") above the
|
|
@@ -862,16 +1049,17 @@ declare class RelCard extends LitElement {
|
|
|
862
1049
|
* @csspart track - The flex row / column that translates to reveal the current slide.
|
|
863
1050
|
* @csspart ${direction}-button - The two arrow buttons, exposed as `prev-button` and `next-button` (`type="side-arrows"` overlays them on the viewport; `type="bottom-arrows"` inlines them in the dots row).
|
|
864
1051
|
* @csspart dots - The indicator row under the viewport (also hosts the arrows for `type="bottom-arrows"`).
|
|
865
|
-
* @csspart dot - One indicator button per reachable position (per slide at `panels="1"`); the active one carries the `active` class and `aria-current="true"`.
|
|
1052
|
+
* @csspart dot - One indicator button per reachable position (per slide at `panels="1"`); the active one carries the `active` class and `aria-current="true"`. Since 1.5.0 the button is a transparent target cell of at least 24 × 24px and the visible dot is its `::before` (style it with `::part(dot)::before`).
|
|
866
1053
|
* @csspart dot-group - The row of dots inside `dots` (for `type="bottom-arrows"` it is the middle child, between the two arrows).
|
|
867
1054
|
* @cssprop --rel-carousel-height - Viewport height in `orientation="vertical"` (default 320px); the horizontal viewport takes the height of its tallest slide.
|
|
868
1055
|
* @cssprop --rel-carousel-nav-size - Width / height of the arrow buttons (default 32px, matching Figma; applies to both side and bottom arrows).
|
|
869
|
-
* @cssprop --rel-carousel-dot-size - Diameter of an inactive dot (default 8px).
|
|
870
|
-
* @cssprop --rel-carousel-dot-size-active - Width of the active (brand-coloured, pill-shaped) dot (default 16px).
|
|
1056
|
+
* @cssprop --rel-carousel-dot-size - Diameter of an inactive dot (default 8px); its target cell is at least 24px.
|
|
1057
|
+
* @cssprop --rel-carousel-dot-size-active - Width of the active (brand-coloured, pill-shaped) dot (default 16px); its target cell is at least 24px.
|
|
871
1058
|
* @cssprop --rel-carousel-slide-width - Written by the component on its own host to the computed panel width (viewport width for `panels="1"`, a fraction of it above that); not meant to be set by consumers (an inline value is overwritten on resize).
|
|
1059
|
+
* @cssprop --rel-carousel-slide-display - `display` given to each slide in `orientation="vertical"` only, which is what centres the slide's content in the fixed-height viewport as Figma draws it. Set it to `block` to opt out if forcing flex reflows your slide's own children. Horizontal slides are never touched.
|
|
872
1060
|
* @cssprop --rel-carousel-slide-height - Written by the component on its own host to the computed panel height (used for vertical slides); not meant to be set by consumers.
|
|
873
1061
|
*/
|
|
874
|
-
declare class RelCarousel extends
|
|
1062
|
+
declare class RelCarousel extends RelElement {
|
|
875
1063
|
/** Index of the current slide (0-based). Set it to jump; it is clamped to the slide count and reflected as an attribute. */
|
|
876
1064
|
value: number;
|
|
877
1065
|
/** Wrap from the last slide to the first (and back) with a seamless clone transition instead of stopping at the ends. */
|
|
@@ -880,7 +1068,7 @@ declare class RelCarousel extends LitElement {
|
|
|
880
1068
|
autoplay: boolean;
|
|
881
1069
|
/** Autoplay delay between slides, in milliseconds (default 5000). */
|
|
882
1070
|
interval: number;
|
|
883
|
-
/** Pause autoplay while the pointer is over the carousel or while dragging (default true; switch off
|
|
1071
|
+
/** Pause autoplay while the pointer is over the carousel or while dragging (default true; switch off with `pause-on-hover="false"` or `el.pauseOnHover = false`). */
|
|
884
1072
|
pauseOnHover: boolean;
|
|
885
1073
|
/** Legacy toggle for the overlaid previous / next arrows; ignored whenever `type` is set. */
|
|
886
1074
|
showButtons: boolean;
|
|
@@ -987,7 +1175,7 @@ declare class RelCarousel extends LitElement {
|
|
|
987
1175
|
* @csspart icon - The image wrapper above the content, rendered only when `image-src` is set.
|
|
988
1176
|
* @csspart content - The padded area holding the title, subtitle and slotted body.
|
|
989
1177
|
*/
|
|
990
|
-
declare class RelCardMedia extends
|
|
1178
|
+
declare class RelCardMedia extends RelElement {
|
|
991
1179
|
/** URL of the hero image shown full-width at the top of the card. Empty (the default) omits the image section entirely. */
|
|
992
1180
|
imageSrc: string;
|
|
993
1181
|
/** Alternative text for the hero image. Replace the generic default with a real description, or an empty string for purely decorative images. */
|
|
@@ -1010,15 +1198,17 @@ declare class RelCardMedia extends LitElement {
|
|
|
1010
1198
|
* @csspart trigger - The field box that wraps the text input and the clear/calendar icons
|
|
1011
1199
|
* @csspart value - The editable text input inside the trigger
|
|
1012
1200
|
* @csspart shortcuts - The Today / Tomorrow / Yesterday chip row at the top of the popover
|
|
1201
|
+
* @csspart unavailable - Day cells that cannot be picked (outside `min-date` / `max-date`, or blocked by `isDateDisabled`). They are `aria-disabled` and stay focusable, so `:disabled` does not match them; style them with `::part(unavailable)`
|
|
1202
|
+
* @cssprop --rel-overlay-fallback-z - z-index of the panel on the **no-Popover-API fallback path only**. Wherever the browser top layer is available the panel is promoted into it and this value is inert, because top-layer elements are not in the page stacking order at all. Shared with the other overlays (select, autocomplete, the three pickers) so the whole family can be moved from one place.
|
|
1013
1203
|
*/
|
|
1014
|
-
declare class RelDatePicker extends
|
|
1204
|
+
declare class RelDatePicker extends RelElement {
|
|
1015
1205
|
/** Selected date as an ISO `YYYY-MM-DD` string, or `null` when empty; setting it also moves the popover to that month. */
|
|
1016
1206
|
value: string | null;
|
|
1017
1207
|
/** Placeholder text shown while the field is empty (visual only; the accessible name comes from `label`, or "Select date" when unset). */
|
|
1018
1208
|
placeholder: string;
|
|
1019
1209
|
/** Visible label rendered above the field and wired to the input via `aria-labelledby`; `null` renders no label. */
|
|
1020
1210
|
label: string | null;
|
|
1021
|
-
/** Disables the field, the icons and the popover
|
|
1211
|
+
/** Disables the field, the icons and the popover. The field looks exactly like a disabled `rel-textfield`: the whole field at 0.65 opacity, an elevated-2 box with the accent border, the label in `--rel-text-label` and the value and placeholder in `--rel-text-caption` (changed in 1.5.0: they were `--rel-text-disabled` under the 0.65, which left them barely readable). */
|
|
1022
1212
|
disabled: boolean;
|
|
1023
1213
|
/** Appends a `*` to the label and sets `aria-required`; no validation is performed. */
|
|
1024
1214
|
required: boolean;
|
|
@@ -1053,8 +1243,8 @@ declare class RelDatePicker extends LitElement {
|
|
|
1053
1243
|
/**
|
|
1054
1244
|
* Figma ".Date Picker Calendar" Show Shortcuts: renders the Today / Tomorrow /
|
|
1055
1245
|
* Yesterday chip row and its divider at the top of the popover. On by default —
|
|
1056
|
-
* write `show-shortcuts="false"` to hide both (a plain boolean attribute could
|
|
1057
|
-
*
|
|
1246
|
+
* write `show-shortcuts="false"` to hide both (a plain boolean attribute could not
|
|
1247
|
+
* express a default of `true`). The typed `T` / `T±N` shortcuts and the
|
|
1058
1248
|
* in-panel `T` key keep working either way.
|
|
1059
1249
|
*/
|
|
1060
1250
|
showShortcuts: boolean;
|
|
@@ -1070,7 +1260,7 @@ declare class RelDatePicker extends LitElement {
|
|
|
1070
1260
|
size: "small" | "medium" | "large";
|
|
1071
1261
|
/** Visual style of the field; `outlined` is the only variant today. */
|
|
1072
1262
|
variant: "outlined";
|
|
1073
|
-
/** Stretches the host to fill its parent's width (attribute `
|
|
1263
|
+
/** Stretches the host to fill its parent's width (attribute `full-width`); off by default so the field keeps its intrinsic inline width. */
|
|
1074
1264
|
fullWidth: boolean;
|
|
1075
1265
|
/** Custom predicate that disables individual days (return `true` to disable); applied on top of `minDate`/`maxDate` and also rejects typed input. Property only — assign it from JavaScript. */
|
|
1076
1266
|
isDateDisabled?: (date: Date) => boolean;
|
|
@@ -1106,12 +1296,14 @@ declare class RelDatePicker extends LitElement {
|
|
|
1106
1296
|
disconnectedCallback(): void;
|
|
1107
1297
|
private handleClickOutside;
|
|
1108
1298
|
private handleEscapeKey;
|
|
1299
|
+
protected willUpdate(changedProperties: Map<string, any>): void;
|
|
1109
1300
|
updated(changedProperties: Map<string, any>): void;
|
|
1110
1301
|
private showTopLayer;
|
|
1111
1302
|
private hideTopLayer;
|
|
1112
1303
|
private onReposition;
|
|
1304
|
+
private scrollWatch;
|
|
1113
1305
|
private updatePopoverPosition;
|
|
1114
|
-
/** Focus the roving day cell (
|
|
1306
|
+
/** Focus the roving day cell (the Tab stop — see getRovingIndex). */
|
|
1115
1307
|
private focusPanelSelection;
|
|
1116
1308
|
private parseISODate;
|
|
1117
1309
|
private formatISODate;
|
|
@@ -1139,6 +1331,12 @@ declare class RelDatePicker extends LitElement {
|
|
|
1139
1331
|
private closeCalendarPopover;
|
|
1140
1332
|
private previousMonth;
|
|
1141
1333
|
private nextMonth;
|
|
1334
|
+
/**
|
|
1335
|
+
* A click is an interaction with that day even when the day cannot be
|
|
1336
|
+
* picked, so it takes the Tab stop first. Set explicitly rather than left to
|
|
1337
|
+
* handleDayGridFocusin because Safari does not focus a button on click.
|
|
1338
|
+
*/
|
|
1339
|
+
private handleDayClick;
|
|
1142
1340
|
private selectDay;
|
|
1143
1341
|
/** Commit a date: set value, reset typed text/error, fire rel-change. */
|
|
1144
1342
|
private commitDate;
|
|
@@ -1163,7 +1361,29 @@ declare class RelDatePicker extends LitElement {
|
|
|
1163
1361
|
private handleInputBlur;
|
|
1164
1362
|
/** T inside the panel (grid/header focus) applies Today directly. */
|
|
1165
1363
|
private handlePanelKeydown;
|
|
1364
|
+
/**
|
|
1365
|
+
* Day-grid keys. Movement is by DATE (the key map is shared with
|
|
1366
|
+
* rel-range-picker via period-page's dayGridTarget), never by grid index:
|
|
1367
|
+
* an index addresses a different date once the view flips month.
|
|
1368
|
+
*/
|
|
1166
1369
|
private handleDayKeydown;
|
|
1370
|
+
/**
|
|
1371
|
+
* Move the rove AND focus to `date`, flipping the view when the date has left
|
|
1372
|
+
* the visible month. Same shape as rel-range-picker.moveGridFocusTo, and the
|
|
1373
|
+
* order matters: `focusedDate` is set from the date BEFORE focus moves,
|
|
1374
|
+
* because lit reuses the day buttons across the month re-render, so the
|
|
1375
|
+
* focused element may not change and no focus event would fire to record it.
|
|
1376
|
+
*/
|
|
1377
|
+
private moveGridFocusTo;
|
|
1378
|
+
/**
|
|
1379
|
+
* Focus arriving any other way — a click, Tab / Shift+Tab, or a programmatic
|
|
1380
|
+
* focus() — moves the Tab stop to that day too, so Tab out of the grid and
|
|
1381
|
+
* back returns to the day last interacted with. This catches every case in
|
|
1382
|
+
* which the focused ELEMENT changes; the one case where it does not (a month
|
|
1383
|
+
* flip that reuses the focused button) is covered by moveGridFocusTo setting
|
|
1384
|
+
* the date first.
|
|
1385
|
+
*/
|
|
1386
|
+
private handleDayGridFocusin;
|
|
1167
1387
|
/**
|
|
1168
1388
|
* The chevrons step by whatever the visible body is made of, so they stay
|
|
1169
1389
|
* useful in every view: a month, a year, or a whole 12-year page.
|
|
@@ -1190,9 +1410,32 @@ declare class RelDatePicker extends LitElement {
|
|
|
1190
1410
|
*/
|
|
1191
1411
|
private handlePeriodGridFocusin;
|
|
1192
1412
|
/**
|
|
1193
|
-
* Index of the single grid cell carrying tabindex="0"
|
|
1413
|
+
* Index of the single grid cell carrying tabindex="0": the day last
|
|
1414
|
+
* interacted with (`focusedDate`), else the selection, else today, else the
|
|
1415
|
+
* first enabled day of the month. The old expression
|
|
1194
1416
|
* (`isSelected || (index === 0 && !value)`) left the grid with ZERO tab
|
|
1195
|
-
* stops once the user arrowed around without a selection
|
|
1417
|
+
* stops once the user arrowed around without a selection; the trailing
|
|
1418
|
+
* fallback keeps it at exactly one by construction.
|
|
1419
|
+
*
|
|
1420
|
+
* `focusedDate` is written from three places, and all three are needed
|
|
1421
|
+
* (fixed 2026-10-03; the same model as rel-range-picker.getRovingIso):
|
|
1422
|
+
* - moveGridFocusTo, from the DATE, before focus moves. Arrow keys navigate
|
|
1423
|
+
* by date, not by grid index, so Sun 27 Sep + ArrowDown is Sun 4 Oct (the
|
|
1424
|
+
* old index+7 landed on Sun 1 Nov once the view flipped). It cannot be left
|
|
1425
|
+
* to a focus event: lit reuses the same buttons across the month
|
|
1426
|
+
* re-render, so the focused element may not change and NO focus event
|
|
1427
|
+
* fires for the move.
|
|
1428
|
+
* - handleDayClick, so a clicked day holds the Tab stop even where a click
|
|
1429
|
+
* does not focus the button (Safari).
|
|
1430
|
+
* - handleDayGridFocusin, for focus arriving by Tab or any other route.
|
|
1431
|
+
*
|
|
1432
|
+
* `focusedDate` counts wherever it sits in the 42-cell grid, out-of-month
|
|
1433
|
+
* cells included. Every date appears in the grid at most once, so this
|
|
1434
|
+
* cannot create a second Tab stop. It only matters after a chevron or a
|
|
1435
|
+
* month/year pick moves the view: the day last interacted with stays the
|
|
1436
|
+
* Tab stop while it is still on screen as a leading/trailing cell. Unavailable
|
|
1437
|
+
* days are aria-disabled, not native disabled, so a Tab stop on one is still
|
|
1438
|
+
* reachable (same as rel-range-picker).
|
|
1196
1439
|
*/
|
|
1197
1440
|
private getRovingIndex;
|
|
1198
1441
|
/** Days view: weekday header + the six week rows. */
|
|
@@ -1222,8 +1465,10 @@ type RangePickerSizeInput = RangePickerSize | RangePickerSizeAlias;
|
|
|
1222
1465
|
* @csspart option - Each quick-select preset button
|
|
1223
1466
|
* @csspart action - The header's previous and next buttons; they step a month, a year or a 12-year page depending on which view the panel is showing
|
|
1224
1467
|
* @csspart footer - The Reset / Cancel / Apply button row
|
|
1468
|
+
* @csspart unavailable - Day cells that cannot be picked (outside `min-date` / `max-date`). They are `aria-disabled` and stay focusable, so `:disabled` does not match them; style them with `::part(unavailable)`
|
|
1469
|
+
* @cssprop --rel-overlay-fallback-z - z-index of the panel on the **no-Popover-API fallback path only**. Wherever the browser top layer is available the panel is promoted into it and this value is inert, because top-layer elements are not in the page stacking order at all. Shared with the other overlays (select, autocomplete, the three pickers) so the whole family can be moved from one place.
|
|
1225
1470
|
*/
|
|
1226
|
-
declare class RelRangePicker extends
|
|
1471
|
+
declare class RelRangePicker extends RelElement {
|
|
1227
1472
|
/** Committed range start as an ISO `YYYY-MM-DD` string; empty string when no range is set. */
|
|
1228
1473
|
from: string;
|
|
1229
1474
|
/** Committed range end as an ISO `YYYY-MM-DD` string; empty string when no range is set. Always ≥ `from`. */
|
|
@@ -1236,7 +1481,7 @@ declare class RelRangePicker extends LitElement {
|
|
|
1236
1481
|
minDate: string;
|
|
1237
1482
|
/** Latest selectable date (ISO `YYYY-MM-DD`); later days are disabled and typed ranges ending after it are rejected. */
|
|
1238
1483
|
maxDate: string;
|
|
1239
|
-
/** Disables the trigger, the icons and the panel controls
|
|
1484
|
+
/** Disables the trigger, the icons and the panel controls. The field looks like a disabled `rel-textfield`: the whole field at 0.65 opacity, an elevated-2 box with the accent border, and the value and placeholder in `--rel-text-caption` (changed in 1.5.0: it was the enabled look at 60% opacity). */
|
|
1240
1485
|
disabled: boolean;
|
|
1241
1486
|
/** Whether the panel is open. Setting it directly shows/hides the panel but does not seed the draft from `from`/`to` or fire `rel-open-change` — user interaction does both. */
|
|
1242
1487
|
open: boolean;
|
|
@@ -1260,7 +1505,7 @@ declare class RelRangePicker extends LitElement {
|
|
|
1260
1505
|
triggerVariant: "default" | "icon";
|
|
1261
1506
|
/** Shows a clear (×) icon while a range is set; clearing fires `rel-change` with empty `from`/`to`. Only with the default trigger. */
|
|
1262
1507
|
clearable: boolean;
|
|
1263
|
-
/** Stretches the host to fill its parent's width (attribute `
|
|
1508
|
+
/** Stretches the host to fill its parent's width (attribute `full-width`),
|
|
1264
1509
|
* mirroring rel-time-picker / rel-date-picker. Off by default so the
|
|
1265
1510
|
* existing intrinsic-width (`inline-block`) rendering is unchanged. */
|
|
1266
1511
|
fullWidth: boolean;
|
|
@@ -1268,6 +1513,10 @@ declare class RelRangePicker extends LitElement {
|
|
|
1268
1513
|
size: RangePickerSizeInput;
|
|
1269
1514
|
private draftFrom;
|
|
1270
1515
|
private draftTo;
|
|
1516
|
+
/** Uncommitted text in the panel's From / To inputs; null → the input shows the draft date. */
|
|
1517
|
+
private panelText;
|
|
1518
|
+
/** Parse / availability error per panel input (cleared on the next edit). */
|
|
1519
|
+
private panelError;
|
|
1271
1520
|
private draftActivePreset;
|
|
1272
1521
|
/** Which grid the panel shows. Ported from rel-date-picker so the two
|
|
1273
1522
|
* calendars behave the same; reaching January 2023 was ~44 chevron clicks. */
|
|
@@ -1280,6 +1529,8 @@ declare class RelRangePicker extends LitElement {
|
|
|
1280
1529
|
private viewYear;
|
|
1281
1530
|
private viewMonth;
|
|
1282
1531
|
private isSelectingRange;
|
|
1532
|
+
/** A mouse click picked the start: the To box is marked as next (sandbox design, Range-A). Keyboard focus never moves for it. */
|
|
1533
|
+
private toMarkedNext;
|
|
1283
1534
|
private hoverDate;
|
|
1284
1535
|
/** ISO date of the cell that owns the grid's single Tab stop (roving tabindex). */
|
|
1285
1536
|
private focusedDate;
|
|
@@ -1297,6 +1548,7 @@ declare class RelRangePicker extends LitElement {
|
|
|
1297
1548
|
private showTopLayer;
|
|
1298
1549
|
private hideTopLayer;
|
|
1299
1550
|
private onReposition;
|
|
1551
|
+
private scrollWatch;
|
|
1300
1552
|
private updatePopoverPosition;
|
|
1301
1553
|
private handleClickOutside;
|
|
1302
1554
|
private handleGlobalKeydown;
|
|
@@ -1343,6 +1595,8 @@ declare class RelRangePicker extends LitElement {
|
|
|
1343
1595
|
private isSameDay;
|
|
1344
1596
|
private isDateDisabled;
|
|
1345
1597
|
private getQuickSelects;
|
|
1598
|
+
/** The preset shown as selected: the one clicked, or else the first whose range equals the draft (sandbox design: picking the days of "Next Week" checks it). */
|
|
1599
|
+
private activePresetLabel;
|
|
1346
1600
|
private selectQuickSelect;
|
|
1347
1601
|
private goPrev;
|
|
1348
1602
|
private goNext;
|
|
@@ -1393,15 +1647,67 @@ declare class RelRangePicker extends LitElement {
|
|
|
1393
1647
|
private formatDayLabel;
|
|
1394
1648
|
private getWeekdayLabels;
|
|
1395
1649
|
private getCalendarDays;
|
|
1650
|
+
/**
|
|
1651
|
+
* Picking an out-of-month day does NOT move the view, unlike rel-calendar
|
|
1652
|
+
* and rel-date-picker (a decision for this component, 2026-10-01). A range
|
|
1653
|
+
* is picked in two clicks, so jumping to the start day's month would send
|
|
1654
|
+
* the user paging back for the end day, and the grid would shift under the
|
|
1655
|
+
* pointer between the clicks. The leading and trailing cells already show
|
|
1656
|
+
* the band and the hover preview across the month boundary, so the range
|
|
1657
|
+
* stays readable without the jump.
|
|
1658
|
+
*
|
|
1659
|
+
* The clicked day takes the Tab stop first, even when it is disabled or out
|
|
1660
|
+
* of the month (see getRovingIso for why that cannot make a second stop).
|
|
1661
|
+
*/
|
|
1396
1662
|
private handleDayClick;
|
|
1663
|
+
private recordDayPick;
|
|
1664
|
+
/** The panel's From / To boxes: real text inputs over the draft. Typing
|
|
1665
|
+
* commits on Enter or blur through the same parser as the trigger
|
|
1666
|
+
* (parseDateInput: MM/DD/YYYY, month names, t / t±N), never to from/to —
|
|
1667
|
+
* Apply still commits the range and Cancel / Escape still discard it. */
|
|
1668
|
+
private renderPanelInput;
|
|
1669
|
+
private handlePanelInput;
|
|
1670
|
+
private handlePanelKeydown;
|
|
1671
|
+
private clearPanelEntry;
|
|
1672
|
+
/** Parse one side into the draft. Empty clears that side; unparseable or
|
|
1673
|
+
* unavailable text stays in the box with an error. A From after the To (or
|
|
1674
|
+
* a To before the From) swaps the two, as typed ranges and grid picks do. */
|
|
1675
|
+
private commitPanelInput;
|
|
1397
1676
|
private handleDayHover;
|
|
1398
1677
|
/**
|
|
1399
|
-
* The cell that carries tabindex="0". Prefers the last
|
|
1400
|
-
* draft start, then today, then the first selectable day — always
|
|
1401
|
-
* one Tab stop, even after arrowing away with nothing selected.
|
|
1678
|
+
* The cell that carries tabindex="0". Prefers the day last interacted with,
|
|
1679
|
+
* then the draft start, then today, then the first selectable day — always
|
|
1680
|
+
* exactly one Tab stop, even after arrowing away with nothing selected.
|
|
1681
|
+
*
|
|
1682
|
+
* `focusedDate` is written from three places, and all three are needed
|
|
1683
|
+
* (the same model as rel-date-picker.getRovingIndex; fixed for both
|
|
1684
|
+
* 2026-10-03):
|
|
1685
|
+
* - moveGridFocusTo sets it from the DATE before moving focus. That ordering
|
|
1686
|
+
* is what makes the arrow keys correct across a month boundary (Sep 27 →
|
|
1687
|
+
* Oct 4 → Oct 11). Do not "simplify" this to a focus listener alone: lit
|
|
1688
|
+
* reuses the same cell elements across the month re-render, so the focused
|
|
1689
|
+
* element may not change and no focus event fires.
|
|
1690
|
+
* - handleDayClick, so the clicked day holds the Tab stop.
|
|
1691
|
+
* - handleDayGridFocusin, for focus arriving by Tab or any other route.
|
|
1692
|
+
*
|
|
1693
|
+
* Out-of-month cells: picking one deliberately does NOT move the view (see
|
|
1694
|
+
* handleDayClick), so the clicked leading/trailing cell itself must be able
|
|
1695
|
+
* to hold the Tab stop, or Shift+Tab, Tab after the click would land on a
|
|
1696
|
+
* different day. `focusedDate` therefore counts wherever it sits in the
|
|
1697
|
+
* 42-cell grid. Every date appears in the grid at most once, so this cannot
|
|
1698
|
+
* create a second Tab stop. The fallbacks (draft start, today) stay
|
|
1699
|
+
* in-month, as before. Disabled cells are focusable (aria-disabled), so a
|
|
1700
|
+
* Tab stop on one is still reachable.
|
|
1402
1701
|
*/
|
|
1403
1702
|
private getRovingIso;
|
|
1404
1703
|
private handleGridKeydown;
|
|
1704
|
+
/**
|
|
1705
|
+
* Focus arriving by Tab, a click or any other route moves the Tab stop to
|
|
1706
|
+
* that day, so Tab out of the grid and back returns to it. Only catches moves
|
|
1707
|
+
* where the focused ELEMENT changes; a month flip that reuses the focused cell
|
|
1708
|
+
* is covered by moveGridFocusTo setting the date first.
|
|
1709
|
+
*/
|
|
1710
|
+
private handleDayGridFocusin;
|
|
1405
1711
|
private moveGridFocusTo;
|
|
1406
1712
|
render(): lit_html.TemplateResult<1>;
|
|
1407
1713
|
}
|
|
@@ -1426,14 +1732,15 @@ type ContainerBackground = "light" | "white" | "none";
|
|
|
1426
1732
|
* @csspart base - The padded surface `<div>` (same element as `container`)
|
|
1427
1733
|
* @csspart container - Alias of `base`, kept for existing `::part(container)` selectors
|
|
1428
1734
|
*/
|
|
1429
|
-
declare class RelContainer extends
|
|
1735
|
+
declare class RelContainer extends RelElement {
|
|
1430
1736
|
/** Inner padding step: `small` = spacing-xs, `medium` = spacing-md, `large` = spacing-lg. `extra-large` = spacing-2xl is a code-only extension — Figma publishes only the three steps above — and is supported, not deprecated. `sm` / `md` / `lg` / `xl` are alternative spellings and stay supported, normalised to the full words. */
|
|
1431
1737
|
padding: ContainerPaddingInput;
|
|
1432
1738
|
/** Adds the shadow-300 elevation box-shadow to the surface. */
|
|
1433
1739
|
shadow: boolean;
|
|
1434
1740
|
/**
|
|
1435
|
-
* Surface fill: default (page surface) | elevated
|
|
1436
|
-
* transparent
|
|
1741
|
+
* Surface fill: `"default"` (the default: page surface) | `"elevated"`
|
|
1742
|
+
* (raised surface) | `"transparent"`. Takes precedence over the deprecated
|
|
1743
|
+
* `background` prop.
|
|
1437
1744
|
*/
|
|
1438
1745
|
surface?: ContainerSurface;
|
|
1439
1746
|
/** @deprecated Deprecated since 1.4.7 — use `surface` (white→default, light→elevated, none→transparent). */
|
|
@@ -1451,7 +1758,7 @@ declare class RelContainer extends LitElement {
|
|
|
1451
1758
|
* @csspart base - The rendered rule — restyle thickness, colour or margin here.
|
|
1452
1759
|
* @cssprop --rel-divider-spacing - Cross-axis margin around the rule; default 16px. Figma specifies none, so set it to `0` for strict parity — the default is kept for back-compat and is planned to become `0` in 3.0.
|
|
1453
1760
|
*/
|
|
1454
|
-
declare class RelDivider extends
|
|
1761
|
+
declare class RelDivider extends RelElement {
|
|
1455
1762
|
/** Axis of the rule: `horizontal` spans the full width with vertical margin; `vertical` is a full-height line with horizontal margin (the parent needs a defined height or a flex row). Mirrored to `aria-orientation` on the host. */
|
|
1456
1763
|
orientation: "horizontal" | "vertical";
|
|
1457
1764
|
static styles: lit.CSSResult;
|
|
@@ -1465,7 +1772,7 @@ declare class RelDivider extends LitElement {
|
|
|
1465
1772
|
* row with an 8px gap. Can also be used standalone for a matching actions row.
|
|
1466
1773
|
* @slot - Footer actions (typically `<rel-button>`s)
|
|
1467
1774
|
*/
|
|
1468
|
-
declare class RelDrawerFooter extends
|
|
1775
|
+
declare class RelDrawerFooter extends RelElement {
|
|
1469
1776
|
static styles: lit.CSSResult;
|
|
1470
1777
|
render(): lit_html.TemplateResult<1>;
|
|
1471
1778
|
}
|
|
@@ -1482,7 +1789,7 @@ type DrawerCloseReason = "backdrop" | "escape" | "drag" | "programmatic";
|
|
|
1482
1789
|
* from the bottom, left or right over a scrim, with an optional drag handle
|
|
1483
1790
|
* (bottom only), a title/description header, a scrollable body and a footer.
|
|
1484
1791
|
* @slot - Body content of the drawer
|
|
1485
|
-
* @slot footer - Actions row; rendered inside a `<rel-drawer-footer>` (right-aligned, 8px gap)
|
|
1792
|
+
* @slot footer - Actions row; rendered inside a `<rel-drawer-footer>` (right-aligned, 8px gap). The footer only renders when this slot has content; its top divider shows only while the body scrolls
|
|
1486
1793
|
* @csspart overlay - The full-viewport scrim behind the panel
|
|
1487
1794
|
* @csspart panel - The sliding panel (role="dialog")
|
|
1488
1795
|
* @csspart handle - The drag-to-close grab bar (bottom drawers only)
|
|
@@ -1496,7 +1803,7 @@ type DrawerCloseReason = "backdrop" | "escape" | "drag" | "programmatic";
|
|
|
1496
1803
|
* @cssprop --rel-drawer-transition-timing - Slide/scrim animation easing; default `cubic-bezier(0.32, 0.72, 0, 1)`
|
|
1497
1804
|
* @cssprop --rel-drawer-scrim-opacity - Opacity of the scrim while open; default `1`
|
|
1498
1805
|
*/
|
|
1499
|
-
declare class RelDrawer extends
|
|
1806
|
+
declare class RelDrawer extends RelElement {
|
|
1500
1807
|
/** Whether the drawer is shown. Toggle it to open/close; every change fires `rel-open-change`. */
|
|
1501
1808
|
open: boolean;
|
|
1502
1809
|
/** Edge the panel slides in from. `bottom` is centred horizontally and supports the drag handle; `left`/`right` are full-height side panels. */
|
|
@@ -1533,25 +1840,36 @@ declare class RelDrawer extends LitElement {
|
|
|
1533
1840
|
private currentY;
|
|
1534
1841
|
/** Scrim opacity at rest, sampled once per drag so the fade starts from it. */
|
|
1535
1842
|
private scrimRestingOpacity;
|
|
1536
|
-
private originalBodyOverflow;
|
|
1537
|
-
private originalBodyPaddingRight;
|
|
1538
1843
|
static styles: lit.CSSResult;
|
|
1539
1844
|
connectedCallback(): void;
|
|
1540
1845
|
disconnectedCallback(): void;
|
|
1846
|
+
firstUpdated(): void;
|
|
1541
1847
|
updated(changed: Map<string, any>): void;
|
|
1542
1848
|
/**
|
|
1543
1849
|
* The footer divider is conditional: short content (a confirmation message)
|
|
1544
1850
|
* has no divider, but a body that scrolls does — it is a scroll affordance,
|
|
1545
1851
|
* not decoration (designer, confirmed). CSS cannot ask whether an element
|
|
1546
|
-
* scrolls, so it is measured and reflected onto the host as `body-scrolls
|
|
1547
|
-
*
|
|
1852
|
+
* scrolls, so it is measured and reflected onto the host as `body-scrolls`.
|
|
1853
|
+
*
|
|
1854
|
+
* What is observed matters. `.content` is a flex: 1 box in a fixed-height
|
|
1855
|
+
* panel, so its own size does not change when its content grows, and its
|
|
1856
|
+
* only shadow child is the slot, which has no box. So the observer also
|
|
1857
|
+
* watches every element assigned to the default slot (re-collected on
|
|
1858
|
+
* slotchange): content added later, a child growing in place, an image
|
|
1859
|
+
* loading, all resize one of those. Window resizes reach `.content` itself.
|
|
1548
1860
|
*/
|
|
1549
1861
|
private bodyScrollObserver?;
|
|
1550
|
-
private
|
|
1862
|
+
private bodyMeasureQueued;
|
|
1863
|
+
private measureBodyScroll;
|
|
1864
|
+
private queueBodyMeasure;
|
|
1865
|
+
private observeBody;
|
|
1551
1866
|
private handleOpen;
|
|
1552
1867
|
private handleClose;
|
|
1553
1868
|
private lockScroll;
|
|
1554
1869
|
private unlockScroll;
|
|
1870
|
+
/** Drops a drag in progress when the drawer closes or leaves the DOM, so the
|
|
1871
|
+
* document pointer listeners do not outlive it. */
|
|
1872
|
+
private endDrag;
|
|
1555
1873
|
private handleKeydown;
|
|
1556
1874
|
private handleOverlayClick;
|
|
1557
1875
|
private handleCloseButtonClick;
|
|
@@ -1575,15 +1893,41 @@ declare global {
|
|
|
1575
1893
|
* names; the full words are accepted as aliases (Trello 4).
|
|
1576
1894
|
*/
|
|
1577
1895
|
type KbdSize = "sm" | "md" | "lg" | "small" | "medium" | "large";
|
|
1896
|
+
/** Which keyboard convention named keys follow: `auto` detects it, `mac` / `other` force it. */
|
|
1897
|
+
type KbdPlatform = "auto" | "mac" | "other";
|
|
1898
|
+
/** A named key as drawn on one platform: the cap text and the name a screen reader speaks. */
|
|
1899
|
+
interface KeyFace {
|
|
1900
|
+
label: string;
|
|
1901
|
+
name: string;
|
|
1902
|
+
}
|
|
1903
|
+
/**
|
|
1904
|
+
* Platform detection for `platform="auto"`: User-Agent Client Hints first, then
|
|
1905
|
+
* `navigator.platform` (iPadOS reports "MacIntel" there). No `navigator`
|
|
1906
|
+
* (SSR, workers without it) means "other".
|
|
1907
|
+
*/
|
|
1908
|
+
declare function detectKbdPlatform(): "mac" | "other";
|
|
1909
|
+
/**
|
|
1910
|
+
* Resolves a key name to its cap text and spoken name. Names are matched
|
|
1911
|
+
* case-insensitively; anything that is not a named key (`K`, `F5`, `⌘`) comes
|
|
1912
|
+
* back exactly as typed.
|
|
1913
|
+
*/
|
|
1914
|
+
declare function resolveKbdKey(key: string, platform?: KbdPlatform): KeyFace;
|
|
1578
1915
|
/**
|
|
1579
1916
|
* Single key cap (Figma "Kbd", 6316:284) for showing a keyboard key or shortcut
|
|
1580
|
-
* inline with text; the key label is the slotted content
|
|
1581
|
-
*
|
|
1917
|
+
* inline with text; the key label is the slotted content, or a named key set
|
|
1918
|
+
* with `key-name`.
|
|
1919
|
+
* @slot - The key label (e.g. `Ctrl`, `K`, `⌘`), rendered exactly as written. Not rendered while `key-name` is set.
|
|
1582
1920
|
*/
|
|
1583
|
-
declare class RelKbd extends
|
|
1584
|
-
/**
|
|
1921
|
+
declare class RelKbd extends RelElement {
|
|
1922
|
+
/**
|
|
1923
|
+
* New in 1.5.0. A named key, drawn in the platform's convention instead of the slotted text: `mod` (⌘ on Mac, Ctrl elsewhere), `cmd` / `command` / `meta`, `ctrl` / `control`, `alt` / `option` / `opt`, `shift`, `enter` / `return`, `esc` / `escape`, `tab`, `backspace`, `delete`, `space`, `up` / `down` / `left` / `right`, `pageup` / `pagedown`, `home` / `end`, `capslock` (case-insensitive). Mac shows symbols (⌘ ⌃ ⌥ ⇧ ↩ ⎋ ⇥ ⌫ ⌦ ⇞ ⇟ ↖ ↘ ⇪); elsewhere the short words (Ctrl, Alt, Esc, PgUp…); arrows are ↑ ↓ ← → on both and Space is the word on both. The symbol is hidden from assistive technology and the key's full name (Command, Option…) is read instead. Any other value is shown as typed. While set, slotted content is not rendered.
|
|
1924
|
+
*/
|
|
1925
|
+
keyName?: string;
|
|
1926
|
+
/** New in 1.5.0. Keyboard convention for `key-name`: `auto` detects Mac / iPhone / iPad from the browser (no `navigator`, as in SSR, counts as `other`), `mac` and `other` force one. Has no effect on slotted text. */
|
|
1927
|
+
platform: KbdPlatform;
|
|
1928
|
+
/** Key-cap scale (Figma Size): `small` 20px tall / label-sm, `medium` 24px / label-md, `large` 28px / label-lg; 4px radius at every size. A single-symbol key (⌘ ⌥ ⇧ ⌃, `mod` when it shows ⌘, arrows…) is a square cap, 20 × 20 / 24 × 24 / 28 × 28px, with the symbol centred (new in 1.5.0). `sm` / `md` / `lg` are the legacy short spellings and stay accepted. */
|
|
1585
1929
|
size: KbdSize;
|
|
1586
|
-
/** Fill / text contrast: `default` = elevated-1 background with label text; `muted` = elevated-2 background with
|
|
1930
|
+
/** Fill / text contrast: `default` = elevated-1 background with label text; `muted` = elevated-2 background with caption-tone text for secondary shortcuts. Both carry a 0.5px stroke and the hard 2px bottom edge Figma draws on the key cap. */
|
|
1587
1931
|
variant: "default" | "muted";
|
|
1588
1932
|
/**
|
|
1589
1933
|
* Fully rounded corners. Logs a one-time console notice when set.
|
|
@@ -1591,10 +1935,14 @@ declare class RelKbd extends LitElement {
|
|
|
1591
1935
|
* 16); `pill` is kept working as an alias but logs a one-time notice.
|
|
1592
1936
|
*/
|
|
1593
1937
|
pill: boolean;
|
|
1594
|
-
/** Pressed look: border-strong stroke
|
|
1938
|
+
/** Pressed look: border-strong stroke and a 1px downward nudge; the fill stays the variant's. */
|
|
1595
1939
|
inset: boolean;
|
|
1596
1940
|
protected willUpdate(changed: PropertyValues<this>): void;
|
|
1597
|
-
static styles: lit.CSSResult;
|
|
1941
|
+
static styles: lit.CSSResult[];
|
|
1942
|
+
/** The visible label: the named key's cap text, or the slotted text. */
|
|
1943
|
+
private visibleLabel;
|
|
1944
|
+
private syncSymbol;
|
|
1945
|
+
protected updated(changed: PropertyValues<this>): void;
|
|
1598
1946
|
render(): lit_html.TemplateResult<1>;
|
|
1599
1947
|
}
|
|
1600
1948
|
/**
|
|
@@ -1602,23 +1950,25 @@ declare class RelKbd extends LitElement {
|
|
|
1602
1950
|
* entry in `items` with "+" separators between them. Slotted <rel-kbd>
|
|
1603
1951
|
* children may be used instead of the items array.
|
|
1604
1952
|
*
|
|
1605
|
-
* <rel-kbd-group .items=${["
|
|
1953
|
+
* <rel-kbd-group .items=${["mod", "Shift", "P"]} size="medium"></rel-kbd-group>
|
|
1606
1954
|
* @slot - Extra content rendered after the generated keys (e.g. hand-written `<rel-kbd>` children)
|
|
1607
1955
|
* @csspart item - Each generated `<rel-kbd>` key cap
|
|
1608
1956
|
* @csspart label - The `+` separator between generated keys
|
|
1609
1957
|
*/
|
|
1610
|
-
declare class RelKbdGroup extends
|
|
1611
|
-
/**
|
|
1958
|
+
declare class RelKbdGroup extends RelElement {
|
|
1959
|
+
/** Keys to render, one `<rel-kbd>` each, joined by `+` separators (read as "plus"). Set as a property or as a JSON array attribute (`items='["mod","K"]'`). Since 1.5.0 each entry is a `key-name`: named keys (`mod`, `ctrl`, `shift`, `enter`, arrows…, case-insensitive) follow the platform convention, so `"Ctrl"` shows ⌃ on a Mac; use `"mod"` for the primary modifier (⌘ on Mac, Ctrl elsewhere). Anything else is shown as typed. */
|
|
1612
1960
|
items: string[];
|
|
1961
|
+
/** New in 1.5.0. Passed through to every generated <rel-kbd>: `auto` (default) detects Mac from the browser, `mac` / `other` force a convention for named keys. */
|
|
1962
|
+
platform: KbdPlatform;
|
|
1613
1963
|
/** Passed through to every generated <rel-kbd>: `small` / `medium` / `large` (legacy `sm` / `md` / `lg` still accepted). */
|
|
1614
1964
|
size: KbdSize;
|
|
1615
1965
|
/** Passed through to every generated <rel-kbd>: `default` or `muted`. */
|
|
1616
1966
|
variant: "default" | "muted";
|
|
1617
|
-
static styles: lit.CSSResult;
|
|
1967
|
+
static styles: lit.CSSResult[];
|
|
1618
1968
|
render(): lit_html.TemplateResult<1>;
|
|
1619
1969
|
}
|
|
1620
1970
|
|
|
1621
|
-
declare class RelLayout extends
|
|
1971
|
+
declare class RelLayout extends RelElement {
|
|
1622
1972
|
gap: string;
|
|
1623
1973
|
columns: number;
|
|
1624
1974
|
responsive: boolean;
|
|
@@ -1633,6 +1983,9 @@ type Orientation = "horizontal" | "vertical";
|
|
|
1633
1983
|
type StepperSize = "small" | "large";
|
|
1634
1984
|
/** Figma "Type": indicator content — default (number, check when done), dot, number, icon. */
|
|
1635
1985
|
type StepperType = "default" | "dot" | "number" | "icon";
|
|
1986
|
+
/** How the line BETWEEN steps is drawn (Figma ".Line Types"). Distinct from
|
|
1987
|
+
* `StepperType`, which is the indicator disc — both spell one value "dot". */
|
|
1988
|
+
type StepperConnector = "solid" | "dot";
|
|
1636
1989
|
/** Figma "Typel": label placement relative to the indicator. */
|
|
1637
1990
|
type LabelPlacement = "top" | "centered" | "inverted";
|
|
1638
1991
|
interface Step {
|
|
@@ -1653,7 +2006,7 @@ interface Step {
|
|
|
1653
2006
|
* @cssprop --rel-stepper-connector-length-md - No longer applies. It parameterised the code-only `size` axis, and Figma has one connector geometry rather than a scale.
|
|
1654
2007
|
* @cssprop --rel-stepper-connector-length-sm - No longer applies, for the same reason as `-md`.
|
|
1655
2008
|
*/
|
|
1656
|
-
declare class RelStepper extends
|
|
2009
|
+
declare class RelStepper extends RelElement {
|
|
1657
2010
|
/** The steps in order, each `{ title: string; subtitle?: string; status: "done" | "progress" | "disabled" }`. Set as a property (or a JSON array attribute); the component never mutates it — update it from the `rel-step-change` handler. */
|
|
1658
2011
|
steps: Step[];
|
|
1659
2012
|
/**
|
|
@@ -1673,8 +2026,20 @@ declare class RelStepper extends LitElement {
|
|
|
1673
2026
|
* with `--rel-stepper-connector-length` instead. Logs a one-time notice.
|
|
1674
2027
|
*/
|
|
1675
2028
|
size: StepperSize;
|
|
1676
|
-
/**
|
|
2029
|
+
/**
|
|
2030
|
+
* Figma "Type" axis — what the INDICATOR shows: `default` (step number, check
|
|
2031
|
+
* mark once done), `dot` (8px dot, no glyph), `number` (always the number) or
|
|
2032
|
+
* `icon` (always the check mark). Not the same axis as `connector="dot"`, which
|
|
2033
|
+
* dashes the line between steps.
|
|
2034
|
+
*/
|
|
1677
2035
|
type: StepperType;
|
|
2036
|
+
/**
|
|
2037
|
+
* Figma ".Line Types" axis — how the line BETWEEN steps is drawn: `solid` (an
|
|
2038
|
+
* unbroken 1px rule) or `dot` (a 1px rule dashed 2px on, 2px off). Applies to
|
|
2039
|
+
* both orientations. Not the same axis as `type="dot"`, which is the indicator
|
|
2040
|
+
* disc; the two are independent and can be combined.
|
|
2041
|
+
*/
|
|
2042
|
+
connector: StepperConnector;
|
|
1678
2043
|
/** Figma "Typel" axis — where the label sits: `top` (top-aligned beside the indicator), `centered` (vertically centred beside it) or `inverted` (indicator above the label). When unset, the deprecated `textAlign` prop drives the layout (`below` ≈ `inverted`, `right` ≈ `centered`). Figma marks Top + Horizontal as an unsupported combination. */
|
|
1679
2044
|
labelPlacement?: LabelPlacement;
|
|
1680
2045
|
static styles: lit.CSSResult;
|
|
@@ -1710,10 +2075,15 @@ type RadioAlignment = "leading" | "trailing";
|
|
|
1710
2075
|
/**
|
|
1711
2076
|
* Single-select radio group (Figma "Radio"): renders one native radio input per
|
|
1712
2077
|
* entry in `options`, with optional supporting text, icon or avatar prefix.
|
|
2078
|
+
* Form-associated, so an outer `<label>` (wrapping it, or `for=`) names the
|
|
2079
|
+
* group; clicking that label focuses the selected (else first enabled) option
|
|
2080
|
+
* without selecting anything. It still sets no form value and is not submitted.
|
|
1713
2081
|
* @csspart base - The `role="radiogroup"` container that lays out the options
|
|
1714
2082
|
* @csspart label - The visible label text of each option
|
|
1715
2083
|
*/
|
|
1716
|
-
declare class RelRadio extends
|
|
2084
|
+
declare class RelRadio extends RelElement {
|
|
2085
|
+
/** Form-associated only so an outer `<label>` has a control (see utils/outer-label.ts). No form value is set. */
|
|
2086
|
+
static formAssociated: boolean;
|
|
1717
2087
|
/** The options to render, in order. Each entry is a `RadioOption` (`value`, `label`,
|
|
1718
2088
|
* optional `supportingText`, `disabled`, `icon` or `avatar`). Set as a property
|
|
1719
2089
|
* (`.options=`) or as a JSON attribute. */
|
|
@@ -1725,17 +2095,19 @@ declare class RelRadio extends LitElement {
|
|
|
1725
2095
|
/** Layout axis of the option list. `"vertical"` (default) stacks options in
|
|
1726
2096
|
* a column; `"horizontal"` lays them out in a wrapping row. */
|
|
1727
2097
|
orientation: Orientation;
|
|
1728
|
-
/** Control scale. `"
|
|
1729
|
-
*
|
|
1730
|
-
* `"
|
|
2098
|
+
/** Control scale, matching Figma's Size axis. `"small"` and `"medium"`
|
|
2099
|
+
* (default) both draw a 20px control — they differ by TYPE, body-md labels
|
|
2100
|
+
* against body-lg — and `"large"` steps the control to 24px with body-xl
|
|
2101
|
+
* labels. Supporting text sits one body step below the label at every
|
|
2102
|
+
* size (body-sm / md / lg, i.e. 12 / 14 / 16px). `sm` / `md` / `lg` are
|
|
1731
2103
|
* alternative spellings and stay supported — normalised to the full words,
|
|
1732
2104
|
* not deprecated.
|
|
1733
2105
|
*
|
|
1734
|
-
*
|
|
1735
|
-
*
|
|
1736
|
-
*
|
|
1737
|
-
*
|
|
1738
|
-
*
|
|
2106
|
+
* Small and Medium sharing a control is Figma's design, not an oversight:
|
|
2107
|
+
* verified against the live Published DS file on 2026-09-25, `.Radio
|
|
2108
|
+
* Control` measures 20x20 in all 15 Small variants and all 15 Medium ones.
|
|
2109
|
+
* v1.4.8 briefly gave Small its own 16px control on the mistaken premise
|
|
2110
|
+
* that the ramp was 16/20/24; 1.4.9 reverts that. */
|
|
1739
2111
|
size: RadioSizeInput;
|
|
1740
2112
|
/** Supporting-text layout (Figma Density). `"compact"` (default) puts the
|
|
1741
2113
|
* supporting text on its own line under the row, indented past the control;
|
|
@@ -1751,7 +2123,8 @@ declare class RelRadio extends LitElement {
|
|
|
1751
2123
|
* Set it to preselect an option; it is updated on every user selection. */
|
|
1752
2124
|
selectedValue: string | null;
|
|
1753
2125
|
/** Disables every option (Figma State=Disabled: the whole group at 40% opacity).
|
|
1754
|
-
* Individual options can also be disabled via `RadioOption.disabled`.
|
|
2126
|
+
* Individual options can also be disabled via `RadioOption.disabled`. An ancestor
|
|
2127
|
+
* `<fieldset disabled>` disables the group the same way, without changing this property. */
|
|
1755
2128
|
disabled: boolean;
|
|
1756
2129
|
/** Error state (Figma State=Error): rings, dots and supporting text turn danger.
|
|
1757
2130
|
* Applies to every option while nothing is selected, and only to the selected
|
|
@@ -1760,7 +2133,7 @@ declare class RelRadio extends LitElement {
|
|
|
1760
2133
|
/** Message rendered under the group (live region) while `error` is set; hidden
|
|
1761
2134
|
* when `error` is false or the text is empty. */
|
|
1762
2135
|
errorMessage: string;
|
|
1763
|
-
/** Accessible name for the radiogroup (it renders no visible group label). */
|
|
2136
|
+
/** Accessible name for the radiogroup (it renders no visible group label). Unset, an outer `<label>` (wrapping the group, or `for=`) names it instead. */
|
|
1764
2137
|
fieldAriaLabel?: string;
|
|
1765
2138
|
/** Value reported to the Angular forms bridge (`registerOnChange` callback) on each
|
|
1766
2139
|
* change and compared by `writeValue`. Not used for rendering; read `selectedValue`
|
|
@@ -1771,8 +2144,22 @@ declare class RelRadio extends LitElement {
|
|
|
1771
2144
|
checked: boolean;
|
|
1772
2145
|
private _onChange;
|
|
1773
2146
|
private _onTouched;
|
|
2147
|
+
private readonly internals;
|
|
2148
|
+
/** An outer label labels the GROUP, not an option, so its click picks
|
|
2149
|
+
* nothing: it moves focus where Tab would land (the selected option, else
|
|
2150
|
+
* the first enabled one) and the arrow keys choose from there. */
|
|
2151
|
+
private readonly outerLabel;
|
|
2152
|
+
/** Own `disabled`, or an ancestor `<fieldset disabled>`. */
|
|
2153
|
+
private get isDisabled();
|
|
2154
|
+
/** @internal Form-associated lifecycle: an ancestor `<fieldset disabled>` disables the control too (utils/outer-label.ts, 3). */
|
|
2155
|
+
formDisabledCallback(): void;
|
|
1774
2156
|
static styles: lit.CSSResult;
|
|
1775
2157
|
protected willUpdate(changed: PropertyValues<this>): void;
|
|
2158
|
+
/** Whether the author wrote `density` themselves, as opposed to inheriting
|
|
2159
|
+
* the default. Read once at connect: Lit reflects during update, which is
|
|
2160
|
+
* after this runs, so the attribute is present here only if authored. */
|
|
2161
|
+
private densityExplicit;
|
|
2162
|
+
connectedCallback(): void;
|
|
1776
2163
|
/** Trailing has no compact layout in the spec — trailing wins. */
|
|
1777
2164
|
private get effectiveDensity();
|
|
1778
2165
|
private onChange;
|
|
@@ -1801,6 +2188,8 @@ type MenuWidth = "fixed" | "fit";
|
|
|
1801
2188
|
type MenuSize = "large" | "medium" | "small";
|
|
1802
2189
|
interface MenuItem {
|
|
1803
2190
|
label: string;
|
|
2191
|
+
/** New in 1.5.0. `rel-icon` name drawn before the label on `list` and `arrow` rows, at 20 / 18 / 16px for the large / medium / small sizes. Checkbox and select-option rows ignore it. */
|
|
2192
|
+
icon?: string;
|
|
1804
2193
|
active?: boolean;
|
|
1805
2194
|
checked?: boolean;
|
|
1806
2195
|
disabled?: boolean;
|
|
@@ -1812,7 +2201,7 @@ interface MenuItem {
|
|
|
1812
2201
|
* currently read slotted children — menus are built from the `items` property.
|
|
1813
2202
|
* Registered so markup can carry item metadata for future declarative support.
|
|
1814
2203
|
*/
|
|
1815
|
-
declare class RelMenuItem extends
|
|
2204
|
+
declare class RelMenuItem extends RelElement {
|
|
1816
2205
|
/** Display text of the item. */
|
|
1817
2206
|
label: string;
|
|
1818
2207
|
/** Value that identifies the item (not used by `rel-menu` today). */
|
|
@@ -1832,11 +2221,11 @@ declare class RelMenuItem extends LitElement {
|
|
|
1832
2221
|
* @cssprop --rel-menu-width - Width of the menu in BOTH sizing modes; default 300px
|
|
1833
2222
|
* @cssprop --rel-menu-height - Height of the menu when `width="fixed"`, which then scrolls; default 500px. `fit` ignores it and hugs its rows.
|
|
1834
2223
|
*/
|
|
1835
|
-
declare class RelMenu extends
|
|
2224
|
+
declare class RelMenu extends RelElement {
|
|
1836
2225
|
/**
|
|
1837
2226
|
* Row shape (Figma ".Menu Item" Type). `list` (default) = plain rows;
|
|
1838
2227
|
* `checkbox` = toggling rows with a checkbox; `select-option` = single-select
|
|
1839
|
-
* rows with a
|
|
2228
|
+
* rows with a leading radio (`role="menuitemradio"`).
|
|
1840
2229
|
* `arrow` is a code-only extension with no Figma counterpart: rows whose
|
|
1841
2230
|
* `submenu` opens a flyout. Because it rides this axis, submenus cannot
|
|
1842
2231
|
* currently be combined with checkbox or select-option rows — see the README.
|
|
@@ -1866,20 +2255,38 @@ declare class RelMenu extends LitElement {
|
|
|
1866
2255
|
*/
|
|
1867
2256
|
size: MenuSize;
|
|
1868
2257
|
/** The rows to render, in order. Each entry is a `MenuItem` (`label`, optional
|
|
1869
|
-
* `active`, `checked`, `disabled`, `submenu`, `open
|
|
1870
|
-
* assignment, so mutate and reassign it to update
|
|
2258
|
+
* `active`, `checked`, `disabled`, `submenu`, `open`, and, new in 1.5.0, `icon`).
|
|
2259
|
+
* The array is copied on assignment, so mutate and reassign it to update
|
|
2260
|
+
* the menu. */
|
|
1871
2261
|
items: MenuItem[];
|
|
1872
2262
|
private focusedIndex;
|
|
1873
2263
|
/** Index inside the open submenu that virtual focus sits on; -1 = main list. */
|
|
1874
2264
|
private subFocusedIndex;
|
|
2265
|
+
/** A key has moved the virtual focus since the last pointer press or
|
|
2266
|
+
* movement in the list (or since it lost focus): draws the row ring even
|
|
2267
|
+
* when the list itself is not :focus-visible. */
|
|
2268
|
+
private keyboardNav;
|
|
1875
2269
|
private _items;
|
|
1876
2270
|
/** Stable id prefix for aria-activedescendant targets. */
|
|
1877
2271
|
private menuId;
|
|
1878
|
-
static readonly _css = "\n :host {\n color: var(--rel-text-default);\n display: inline-block;\n }\n\n .rel-menu {\n position: relative;\n display: inline-block;\n background: var(--rel-bg-neutral);\n color: var(--rel-text-default);\n /* Audit 17: 8px (border-radius/sm), was 16px; Figma Menu (6326:2931) = shadow/md */\n border-radius: var(--rel-border-radius-sm);\n box-shadow: var(--rel-shadows-md);\n /* Figma's Menu container is 300px around 288px rows. */\n min-width: 300px;\n /* No vertical padding: items fill edge-to-edge so a first/last-item hover\n reaches the menu's top/bottom. NOT overflow:hidden \u2014 that clips the\n type=arrow flyout (position:absolute at left:100%). Instead the first\n and last items carry the outer corner radius so hover backgrounds clip\n to the rounded shape without any overflow. */\n padding: 0;\n outline: none;\n overflow: visible;\n font-family: var(--rel-body-lg-regular-font-family);\n font-weight: var(--rel-body-lg-regular-font-weight);\n font-size: var(--rel-body-lg-regular-font-size);\n line-height: var(--rel-body-lg-regular-line-height);\n letter-spacing: var(--rel-body-lg-regular-letter-spacing);\n }\n\n .rel-menu:focus-visible,\n :host(:focus-visible) .rel-menu {\n outline: 2px solid var(--rel-border-focus);\n outline-offset: 0;\n }\n\n /* Rows follow Figma \".Menu Item\" (6326:616) per size:\n Large 48px = pad 12/12 + body-lg (24 line-height)\n Medium 40px = pad 8/12 + body-md (22)\n Small 32px = pad 4/8 + body-sm (20)\n (audit 17a \u2014 before 1.4.7 every row was 36px: pad 8/12 + a 20px line-height) */\n .rel-menu-item {\n position: relative;\n display: flex;\n align-items: center;\n gap: var(--rel-spacing-md);\n padding: var(--rel-spacing-sm) var(--rel-spacing-sm);\n line-height: var(--rel-body-lg-regular-line-height);\n min-height: 48px;\n cursor: pointer;\n transition: background 0.15s ease, color 0.15s ease;\n user-select: none;\n box-sizing: border-box;\n /* Figma strokes every item with --rel-border-subtle. Drawn as an inset\n shadow on the BOTTOM edge only (the pattern rel-menubar already uses)\n so the rows read as a divided list rather than 45 boxed cells, and so\n it costs no layout height. */\n box-shadow: inset 0 calc(-1 * var(--rel-stroke-sm)) 0 var(--rel-border-subtle);\n }\n\n .rel-menu-item:last-child {\n box-shadow: none;\n }\n\n /* Light-DOM component: :host never matches here, so size rules key off the\n reflected attribute on the <rel-menu> element itself. */\n rel-menu[size=\"medium\"] .rel-menu,\n rel-menu[size=\"medium\"] .rel-submenu {\n font-family: var(--rel-body-md-regular-font-family);\n font-weight: var(--rel-body-md-regular-font-weight);\n font-size: var(--rel-body-md-regular-font-size);\n line-height: var(--rel-body-md-regular-line-height);\n letter-spacing: var(--rel-body-md-regular-letter-spacing);\n }\n\n /* Figma Medium / Small frames are fixed at 40 / 32 (content sums to 38 / 28) */\n rel-menu[size=\"medium\"] .rel-menu-item {\n padding: var(--rel-spacing-xs) var(--rel-spacing-sm);\n line-height: var(--rel-body-md-regular-line-height);\n min-height: 40px;\n }\n\n rel-menu[size=\"small\"] .rel-menu,\n rel-menu[size=\"small\"] .rel-submenu {\n font-family: var(--rel-body-sm-regular-font-family);\n font-weight: var(--rel-body-sm-regular-font-weight);\n font-size: var(--rel-body-sm-regular-font-size);\n line-height: var(--rel-body-sm-regular-line-height);\n letter-spacing: var(--rel-body-sm-regular-letter-spacing);\n }\n\n rel-menu[size=\"small\"] .rel-menu-item {\n padding: var(--rel-spacing-2xs) var(--rel-spacing-xs);\n line-height: var(--rel-body-sm-regular-line-height);\n min-height: 32px;\n }\n\n /* First/last items carry the menu's outer radius so their hover fill clips\n to the rounded corners (replaces the removed overflow:hidden). */\n .rel-menu > .rel-menu-item:first-child {\n border-top-left-radius: var(--rel-border-radius-sm);\n border-top-right-radius: var(--rel-border-radius-sm);\n }\n\n .rel-menu > .rel-menu-item:last-child {\n border-bottom-left-radius: var(--rel-border-radius-sm);\n border-bottom-right-radius: var(--rel-border-radius-sm);\n }\n\n /* Figma states (6326:616): Hover = action overlay 0.05, Pressed = 0.10\n (nearest token: overlay-pressed), Active/selected list row = the hover\n overlay + medium label; Checkbox / Select Option rows keep no fill when\n selected. Disabled = 40% opacity. (audit 17) */\n .rel-menu-item:hover {\n background: var(--rel-action-overlay-hover);\n }\n\n .rel-menu-item:active {\n background: var(--rel-action-overlay-pressed);\n }\n\n .rel-menu-item.active {\n background: var(--rel-action-overlay-hover);\n }\n\n /* The active weight bump follows the row's own size, and applies to plain\n rows only \u2014 a checkbox row carries its state in the control, and Figma\n does not bold its label. */\n .rel-menu:not(.type-checkbox) .rel-menu-item.active {\n font-weight: var(--rel-body-lg-medium-font-weight);\n }\n\n rel-menu[size=\"medium\"] .rel-menu:not(.type-checkbox) .rel-menu-item.active {\n font-weight: var(--rel-body-md-medium-font-weight);\n }\n\n /* Small's active row is Figma's mixed tuple: an xs-medium WEIGHT with\n sm-medium METRICS on the sm-regular family. Large and Medium step only\n their weight and keep regular metrics, which is why they are one line\n each and this one is four. */\n rel-menu[size=\"small\"] .rel-menu:not(.type-checkbox) .rel-menu-item.active {\n font-weight: var(--rel-body-xs-medium-font-weight);\n font-size: var(--rel-body-sm-medium-font-size);\n line-height: var(--rel-body-sm-medium-line-height);\n letter-spacing: var(--rel-body-sm-medium-letter-spacing);\n }\n\n .rel-menu.type-checkbox .rel-menu-item.active,\n .rel-menu.type-select-option .rel-menu-item.active {\n background: transparent;\n }\n\n .rel-menu.type-checkbox .rel-menu-item.active:hover,\n .rel-menu.type-select-option .rel-menu-item.active:hover {\n background: var(--rel-action-overlay-hover);\n }\n\n .rel-menu-item.disabled {\n background-color: transparent;\n opacity: 0.4;\n /* Keep the item pointer-interactive so cursor:not-allowed actually\n renders; clicks are already neutralised by the item.disabled guard in\n onItemClick/onItemEnter. pointer-events:none here would make the row\n transparent to the pointer and suppress the cursor. */\n cursor: not-allowed;\n }\n\n /* [data-focused] (presence, not =\"true\"): the ?data-focused boolean\n binding renders the attribute with an EMPTY value, so a =\"true\"\n selector never matches. */\n /* Inset ring: items run the full width of the panel and butt against its\n padding, so an outside ring would cross the panel edge. rel-menu has no\n State=Focused variant in Figma; kept deliberately. */\n .rel-menu-item[data-focused] {\n outline: 2px solid var(--rel-border-focus);\n outline-offset: -2px;\n }\n\n /* Width modes (Figma Type=Fixed / Type=Fit). BOTH are 300px wide \u2014\n COMPONENT \"Type=Fixed\" is 300x500 sizing=FIXED/FIXED and\n COMPONENT \"Type=Fit\" is 300x48 sizing=FIXED/HUG \u2014 so the axis varies the\n HEIGHT, not the width: Fixed pins a scrolling panel, Fit hugs its rows.\n This had it inverted: fit varied the width (max-content) and neither mode\n constrained the height, so the two modes differed on the wrong dimension. */\n .rel-menu.fixed {\n width: var(--rel-menu-width, 300px);\n height: var(--rel-menu-height, 500px);\n overflow-y: auto;\n min-width: 0;\n box-sizing: border-box;\n }\n\n .rel-menu.fit {\n width: var(--rel-menu-width, 300px);\n min-width: 0;\n box-sizing: border-box;\n }\n\n /* Checkbox (Type=Checkbox) / radio (Type=Select Option) rows render the real\n rel-checkbox / rel-radio. pointer-events:none keeps the whole row the click\n target so onItemClick stays the single source of truth. */\n .menu-control {\n pointer-events: none;\n width: 100%;\n }\n\n .menu-label {\n flex: 1 1 auto;\n }\n\n /* Submenu affordance \u2014 same rel-icon chevron the menubar uses. */\n .submenu-chevron {\n margin-left: auto;\n display: inline-flex;\n align-items: center;\n opacity: 0.6;\n pointer-events: none;\n }\n\n /* Shortcut / hint text (Figma body-sm-regular, caption tone) */\n .menu-shortcut,\n ::slotted([slot=\"shortcut\"]) {\n font-family: var(--rel-body-sm-regular-font-family);\n font-weight: var(--rel-body-sm-regular-font-weight);\n font-size: var(--rel-body-sm-regular-font-size);\n line-height: var(--rel-body-sm-regular-line-height);\n letter-spacing: var(--rel-body-sm-regular-letter-spacing);\n color: var(--rel-text-caption);\n margin-left: auto;\n padding-left: var(--rel-spacing-md);\n }\n\n \n /* No border: the flyout is the same surface as the parent menu, which has\n none \u2014 overlapping surfaces are separated by shadow. Min-width tracks the\n parent's 300px rather than a narrower 200px. */\n .rel-submenu {\n position: absolute;\n top: calc(-1 * var(--rel-spacing-3xs));\n /* flush against the trigger (no gap) so moving the pointer into the flyout\n never crosses a dead zone that would fire the trigger's mouseleave */\n left: 100%;\n min-width: 300px;\n background: var(--rel-bg-neutral);\n color: var(--rel-text-default);\n border-radius: var(--rel-border-radius-sm);\n box-shadow: var(--rel-shadows-md);\n /* padding:0 + overflow:hidden \u2014 safe here (a submenu has no further nested\n flyout to clip) \u2014 so sub-item hovers fill fully and clip to the corners */\n padding: 0;\n overflow: hidden;\n visibility: hidden;\n pointer-events: none;\n z-index: 20;\n }\n\n .rel-submenu.visible {\n visibility: visible;\n pointer-events: auto;\n }\n\n .rel-submenu .rel-menu-item {\n padding: var(--rel-spacing-sm) var(--rel-spacing-sm);\n }\n\n rel-menu[size=\"medium\"] .rel-submenu .rel-menu-item {\n padding: var(--rel-spacing-xs) var(--rel-spacing-sm);\n }\n\n rel-menu[size=\"small\"] .rel-submenu .rel-menu-item {\n padding: var(--rel-spacing-2xs) var(--rel-spacing-xs);\n }\n ";
|
|
2272
|
+
static readonly _css = "\n :host {\n color: var(--rel-text-default);\n display: inline-block;\n }\n\n .rel-menu {\n position: relative;\n display: inline-block;\n background: var(--rel-bg-neutral);\n color: var(--rel-text-default);\n /* Audit 17: 8px (border-radius/sm), was 16px; Figma Menu (6326:2931) = shadow/md */\n border-radius: var(--rel-border-radius-sm);\n box-shadow: var(--rel-shadows-md);\n /* Figma's Menu container is 300px around 288px rows. */\n min-width: 300px;\n /* No vertical padding: items fill edge-to-edge so a first/last-item hover\n reaches the menu's top/bottom. NOT overflow:hidden \u2014 that clips the\n type=arrow flyout (position:absolute at left:100%). Instead the first\n and last items carry the outer corner radius so hover backgrounds clip\n to the rounded shape without any overflow. */\n padding: 0;\n outline: none;\n overflow: visible;\n font-family: var(--rel-body-lg-regular-font-family);\n font-weight: var(--rel-body-lg-regular-font-weight);\n font-size: var(--rel-body-lg-regular-font-size);\n line-height: var(--rel-body-lg-regular-line-height);\n letter-spacing: var(--rel-body-lg-regular-letter-spacing);\n }\n\n /* No ring on the container (designer, October 2026): while the list has\n keyboard focus, only the current row carries the ring (below). */\n\n /* Rows follow Figma \".Menu Item\" (6326:616) per size:\n Large 48px = pad 12/12 + body-lg (24 line-height)\n Medium 40px = pad 8/12 + body-md (22)\n Small 32px = pad 4/8 + body-sm (20)\n (audit 17a \u2014 before 1.4.7 every row was 36px: pad 8/12 + a 20px line-height) */\n .rel-menu-item {\n position: relative;\n display: flex;\n align-items: center;\n gap: var(--rel-spacing-md);\n padding: var(--rel-spacing-sm) var(--rel-spacing-sm);\n line-height: var(--rel-body-lg-regular-line-height);\n min-height: 48px;\n cursor: pointer;\n transition: background 0.15s ease, color 0.15s ease;\n user-select: none;\n box-sizing: border-box;\n /* Figma strokes every item with --rel-border-subtle. Drawn as an inset\n shadow on the BOTTOM edge only (the pattern rel-menubar already uses)\n so the rows read as a divided list rather than 45 boxed cells, and so\n it costs no layout height. */\n box-shadow: inset 0 calc(-1 * var(--rel-stroke-sm)) 0 var(--rel-border-subtle);\n }\n\n .rel-menu-item:last-child {\n box-shadow: none;\n }\n\n /* Light-DOM component: :host never matches here, so size rules key off the\n reflected attribute on the <rel-menu> element itself. */\n rel-menu[size=\"medium\"] .rel-menu,\n rel-menu[size=\"medium\"] .rel-submenu {\n font-family: var(--rel-body-md-regular-font-family);\n font-weight: var(--rel-body-md-regular-font-weight);\n font-size: var(--rel-body-md-regular-font-size);\n line-height: var(--rel-body-md-regular-line-height);\n letter-spacing: var(--rel-body-md-regular-letter-spacing);\n }\n\n /* Figma Medium / Small frames are fixed at 40 / 32 (content sums to 38 / 28) */\n rel-menu[size=\"medium\"] .rel-menu-item {\n padding: var(--rel-spacing-xs) var(--rel-spacing-sm);\n line-height: var(--rel-body-md-regular-line-height);\n min-height: 40px;\n }\n\n rel-menu[size=\"small\"] .rel-menu,\n rel-menu[size=\"small\"] .rel-submenu {\n font-family: var(--rel-body-sm-regular-font-family);\n font-weight: var(--rel-body-sm-regular-font-weight);\n font-size: var(--rel-body-sm-regular-font-size);\n line-height: var(--rel-body-sm-regular-line-height);\n letter-spacing: var(--rel-body-sm-regular-letter-spacing);\n }\n\n rel-menu[size=\"small\"] .rel-menu-item {\n padding: var(--rel-spacing-2xs) var(--rel-spacing-xs);\n line-height: var(--rel-body-sm-regular-line-height);\n min-height: 32px;\n }\n\n /* First/last items carry the menu's outer radius so their hover fill clips\n to the rounded corners (replaces the removed overflow:hidden). */\n .rel-menu > .rel-menu-item:first-child {\n border-top-left-radius: var(--rel-border-radius-sm);\n border-top-right-radius: var(--rel-border-radius-sm);\n }\n\n .rel-menu > .rel-menu-item:last-child {\n border-bottom-left-radius: var(--rel-border-radius-sm);\n border-bottom-right-radius: var(--rel-border-radius-sm);\n }\n\n /* Figma states (6326:616): Hover = action overlay 0.05, Pressed = 0.10\n (nearest token: overlay-pressed), Active/selected list row = the hover\n overlay + medium label; Checkbox / Select Option rows keep no fill when\n selected. Disabled = 40% opacity. (audit 17) */\n .rel-menu-item:hover {\n background: var(--rel-action-overlay-hover);\n }\n\n .rel-menu-item:active {\n background: var(--rel-action-overlay-pressed);\n }\n\n .rel-menu-item.active {\n background: var(--rel-action-overlay-hover);\n }\n\n /* The active weight bump follows the row's own size, and applies to plain\n rows only \u2014 a checkbox row carries its state in the control, and Figma\n does not bold its label. */\n .rel-menu:not(.type-checkbox) .rel-menu-item.active {\n font-weight: var(--rel-body-lg-medium-font-weight);\n }\n\n rel-menu[size=\"medium\"] .rel-menu:not(.type-checkbox) .rel-menu-item.active {\n font-weight: var(--rel-body-md-medium-font-weight);\n }\n\n /* Small's active row is Figma's mixed tuple: an xs-medium WEIGHT with\n sm-medium METRICS on the sm-regular family. Large and Medium step only\n their weight and keep regular metrics, which is why they are one line\n each and this one is four. */\n rel-menu[size=\"small\"] .rel-menu:not(.type-checkbox) .rel-menu-item.active {\n font-weight: var(--rel-body-xs-medium-font-weight);\n font-size: var(--rel-body-sm-medium-font-size);\n line-height: var(--rel-body-sm-medium-line-height);\n letter-spacing: var(--rel-body-sm-medium-letter-spacing);\n }\n\n .rel-menu.type-checkbox .rel-menu-item.active,\n .rel-menu.type-select-option .rel-menu-item.active {\n background: transparent;\n }\n\n .rel-menu.type-checkbox .rel-menu-item.active:hover,\n .rel-menu.type-select-option .rel-menu-item.active:hover {\n background: var(--rel-action-overlay-hover);\n }\n\n .rel-menu-item.disabled {\n background-color: transparent;\n opacity: 0.4;\n /* Keep the item pointer-interactive so cursor:not-allowed actually\n renders; clicks are already neutralised by the item.disabled guard in\n onItemClick/onItemEnter. pointer-events:none here would make the row\n transparent to the pointer and suppress the cursor. */\n cursor: not-allowed;\n }\n\n /* [data-focused] (presence, not =\"true\"): the ?data-focused boolean\n binding renders the attribute with an EMPTY value, so a =\"true\"\n selector never matches. */\n /* Inset ring: items run the full width of the panel and butt against its\n padding, so an outside ring would cross the panel edge. rel-menu has no\n State=Focused variant in Figma; kept deliberately \u2014 but ONLY while the\n list has keyboard focus. Virtual focus (data-focused) always sits on\n some row (row 0 at rest, the last clicked row after a click), so an\n ungated ring read as a permanent border on the selected item. */\n /* [data-keyboard]: a key moved the virtual focus. A list that took focus\n without a ring (a mouse press, or rel-popover opening on a pointer\n press with focusVisible: false) does not become :focus-visible on a\n later key press in Chromium, so the arrows would move an invisible\n focus. The flag clears on pointer movement or press and on blur, so\n mouse-only use still never shows the ring. */\n .rel-menu:focus-visible .rel-menu-item[data-focused],\n .rel-menu[data-keyboard]:focus .rel-menu-item[data-focused],\n :host(:focus-visible) .rel-menu-item[data-focused] {\n outline: 2px solid var(--rel-border-focus);\n outline-offset: -2px;\n }\n\n /* Width modes (Figma Type=Fixed / Type=Fit). BOTH are 300px wide \u2014\n COMPONENT \"Type=Fixed\" is 300x500 sizing=FIXED/FIXED and\n COMPONENT \"Type=Fit\" is 300x48 sizing=FIXED/HUG \u2014 so the axis varies the\n HEIGHT, not the width: Fixed pins a scrolling panel, Fit hugs its rows.\n This had it inverted: fit varied the width (max-content) and neither mode\n constrained the height, so the two modes differed on the wrong dimension. */\n .rel-menu.fixed {\n width: var(--rel-menu-width, 300px);\n height: var(--rel-menu-height, 500px);\n overflow-y: auto;\n min-width: 0;\n box-sizing: border-box;\n }\n\n .rel-menu.fit {\n width: var(--rel-menu-width, 300px);\n min-width: 0;\n box-sizing: border-box;\n }\n\n /* Checkbox (Type=Checkbox) / radio (Type=Select Option) rows render the real\n rel-checkbox / rel-radio. pointer-events:none keeps the whole row the click\n target so onItemClick stays the single source of truth. */\n .menu-control {\n pointer-events: none;\n width: 100%;\n }\n\n .menu-label {\n flex: 1 1 auto;\n }\n\n /* Leading item icon (MenuItem.icon): fixed size, never shrinks. */\n .menu-icon {\n flex: none;\n }\n\n /* Submenu affordance \u2014 same rel-icon chevron the menubar uses.\n\n No opacity here: verified against the live Figma file, \"Chevron Right\"\n is opacity 1 on both the instance and its vector, on every State and\n Size, bound to the same colour variable as the row label beside it.\n The 0.6 that used to sit here dulled it to a mid grey.\n\n The colour is declared rather than inherited on purpose. rel-menu\n renders to the LIGHT DOM (createRenderRoot returns this), so these\n selectors are unscoped globals and an inherited colour would travel\n through the consumer's page cascade \u2014 an app setting a colour on any\n ancestor would have been repainting this chevron. */\n .submenu-chevron {\n margin-left: auto;\n display: inline-flex;\n align-items: center;\n color: var(--rel-text-default);\n pointer-events: none;\n }\n\n /* Shortcut / hint text (Figma body-sm-regular, caption tone) */\n .menu-shortcut,\n ::slotted([slot=\"shortcut\"]) {\n font-family: var(--rel-body-sm-regular-font-family);\n font-weight: var(--rel-body-sm-regular-font-weight);\n font-size: var(--rel-body-sm-regular-font-size);\n line-height: var(--rel-body-sm-regular-line-height);\n letter-spacing: var(--rel-body-sm-regular-letter-spacing);\n color: var(--rel-text-caption);\n margin-left: auto;\n padding-left: var(--rel-spacing-md);\n }\n\n \n /* No border: the flyout is the same surface as the parent menu, which has\n none \u2014 overlapping surfaces are separated by shadow. Min-width tracks the\n parent's 300px rather than a narrower 200px. */\n .rel-submenu {\n position: absolute;\n top: calc(-1 * var(--rel-spacing-3xs));\n /* flush against the trigger (no gap) so moving the pointer into the flyout\n never crosses a dead zone that would fire the trigger's mouseleave */\n left: 100%;\n min-width: 300px;\n background: var(--rel-bg-neutral);\n color: var(--rel-text-default);\n border-radius: var(--rel-border-radius-sm);\n box-shadow: var(--rel-shadows-md);\n /* padding:0 + overflow:hidden \u2014 safe here (a submenu has no further nested\n flyout to clip) \u2014 so sub-item hovers fill fully and clip to the corners */\n padding: 0;\n margin: 0;\n border: 0;\n overflow: hidden;\n visibility: hidden;\n pointer-events: none;\n z-index: 20;\n }\n\n /* Top layer (Popover API): the flyout escapes every ancestor's overflow\n clip \u2014 the menu's own scroller in width=\"fixed\", cards, rel-modal,\n scrolling sidebars \u2014 and is placed in viewport coordinates by\n positionSubmenu(). It stays a DOM descendant of its row, so moving the\n pointer into it never fires the row's mouseleave. Without the Popover\n API the absolute left:100% placement above still applies. */\n .rel-submenu:popover-open {\n position: fixed;\n inset: auto;\n }\n\n .rel-submenu.visible {\n visibility: visible;\n pointer-events: auto;\n }\n\n .rel-submenu .rel-menu-item {\n padding: var(--rel-spacing-sm) var(--rel-spacing-sm);\n }\n\n rel-menu[size=\"medium\"] .rel-submenu .rel-menu-item {\n padding: var(--rel-spacing-xs) var(--rel-spacing-sm);\n }\n\n rel-menu[size=\"small\"] .rel-submenu .rel-menu-item {\n padding: var(--rel-spacing-2xs) var(--rel-spacing-xs);\n }\n ";
|
|
1879
2273
|
createRenderRoot(): this;
|
|
1880
2274
|
connectedCallback(): void;
|
|
1881
2275
|
disconnectedCallback(): void;
|
|
1882
2276
|
updated(changedProperties: Map<string, unknown>): void;
|
|
2277
|
+
/** The open flyout and its row while one is showing. */
|
|
2278
|
+
private openSubmenu;
|
|
2279
|
+
/** Outside scroll / resize: follow the row while it is visible, close once
|
|
2280
|
+
* it scrolls out of view (same rule as the select / picker panels). */
|
|
2281
|
+
private submenuScroll;
|
|
2282
|
+
private onSubmenuResize;
|
|
2283
|
+
/** Show / hide each flyout in the top layer to match the rendered state. */
|
|
2284
|
+
private syncSubmenus;
|
|
2285
|
+
private stopTrackingSubmenu;
|
|
2286
|
+
/** Beside the row, flush (no gap, so hover never crosses a dead zone):
|
|
2287
|
+
* to the right when it fits, else flipped to the left; shifted up when it
|
|
2288
|
+
* would run past the bottom; kept 8px inside the viewport. */
|
|
2289
|
+
private positionSubmenu;
|
|
1883
2290
|
/** Index of a submenu locked open by a click (survives hover-out). -1 = none. */
|
|
1884
2291
|
private lockedIndex;
|
|
1885
2292
|
private handleDocumentClick;
|
|
@@ -1891,8 +2298,19 @@ declare class RelMenu extends LitElement {
|
|
|
1891
2298
|
* virtual focus onto its first entry. */
|
|
1892
2299
|
private openSubmenuAt;
|
|
1893
2300
|
private closeSubmenus;
|
|
2301
|
+
/** Keys that move the virtual focus (rel-menu has no type-ahead). */
|
|
2302
|
+
private static readonly NAV_KEYS;
|
|
1894
2303
|
private onKeydown;
|
|
1895
2304
|
private renderMenuItem;
|
|
2305
|
+
/**
|
|
2306
|
+
* New in 1.5.0. Moves the virtual focus (the row `aria-activedescendant`
|
|
2307
|
+
* names) to `index`, clamped to the rows; a negative index counts from the
|
|
2308
|
+
* end, so `-1` is the last row. It moves neither DOM focus nor the ring: the
|
|
2309
|
+
* row ring still follows the list's own keyboard focus. A menu button uses it
|
|
2310
|
+
* to open on the first row (Enter, Space, ArrowDown) or the last (ArrowUp).
|
|
2311
|
+
*/
|
|
2312
|
+
focusItem(index: number): void;
|
|
2313
|
+
private clearKeyboardNav;
|
|
1896
2314
|
render(): lit_html.TemplateResult<1>;
|
|
1897
2315
|
}
|
|
1898
2316
|
|
|
@@ -1903,7 +2321,7 @@ type MenubarType = "fixed" | "fit";
|
|
|
1903
2321
|
* @cssprop --rel-menubar-width - Width of the bar when `type="fixed"`; default 100%
|
|
1904
2322
|
* @cssprop --rel-menubar-panel-width - Width of the dropdown and submenu panels; default 300px
|
|
1905
2323
|
*/
|
|
1906
|
-
declare class RelMenubar extends
|
|
2324
|
+
declare class RelMenubar extends RelElement {
|
|
1907
2325
|
/**
|
|
1908
2326
|
* Opt-in: actually bind the keys declared via `data-shortcut` on items (e.g. `data-shortcut="Ctrl+Z"`) instead of only displaying them; a "Mod" token means Cmd on Apple platforms and Ctrl elsewhere, and keystrokes that originate in inputs, textareas or contenteditable regions are ignored.
|
|
1909
2327
|
*/
|
|
@@ -1924,7 +2342,7 @@ declare class RelMenubar extends LitElement {
|
|
|
1924
2342
|
/** Stable id prefix for aria-activedescendant targets (light DOM, so ids
|
|
1925
2343
|
* must be unique per menubar instance on the page). */
|
|
1926
2344
|
private menubarId;
|
|
1927
|
-
static readonly _css = "\n /* This component renders into LIGHT DOM (createRenderRoot returns this), so\n :host / <slot> don't work here \u2014 the raw <rel-menubar-menu> definitions\n are data holders that must be hidden with a plain selector. Relying on the\n global rel-menubar-menu.css is not enough: it can't cross a consumer's\n shadow boundary AND it's a no-op in the tsup-built package (css:\"copy\"). */\n rel-menubar {\n color: var(--rel-text-default);\n display: block;\n /* Figma Menu Bar / .Menu Bar Item (8699:4, 8698:13) label = body/lg.\n Declared on the host, not on .menubar-container, so the position:fixed\n panels \u2014 siblings of the container, not descendants \u2014 inherit it too. */\n font-family: var(--rel-body-lg-regular-font-family);\n font-weight: var(--rel-body-lg-regular-font-weight);\n font-size: var(--rel-body-lg-regular-font-size);\n line-height: var(--rel-body-lg-regular-line-height);\n letter-spacing: var(--rel-body-lg-regular-letter-spacing);\n }\n\n rel-menubar-menu {\n display: none;\n }\n\n /* Figma Menu Bar (8699:4): bg/fill/neutral/default on border-radius/sm,\n clipping its children, gap spacing/none \u2014 no border and no shadow. */\n .menubar-container {\n display: flex;\n align-items: stretch;\n background: var(--rel-bg-neutral);\n border-radius: var(--rel-border-radius-sm);\n overflow: hidden;\n padding: 0;\n gap: 0;\n min-height: 40px;\n width: fit-content;\n }\n\n /* Type=Fit hugs its triggers (the default); Type=Fixed spans its container.\n Light-DOM component: :host never matches, so these key off the reflected\n attribute on the <rel-menubar> element itself. */\n rel-menubar[type=\"fixed\"] .menubar-container {\n width: var(--rel-menubar-width, 100%);\n }\n\n rel-menubar[type=\"fit\"] .menubar-container {\n width: fit-content;\n }\n\n /* Figma .Menu Bar Item (8698:13): spacing/xs vertical + spacing/md\n horizontal padding around a body/lg label = a 40px trigger. */\n .menubar-trigger {\n display: flex;\n align-items: center;\n justify-content: center;\n align-self: stretch;\n padding: var(--rel-spacing-xs) var(--rel-spacing-md);\n background: transparent;\n border: none;\n cursor: pointer;\n font: inherit;\n color: var(--rel-text-default);\n white-space: nowrap;\n transition: background 0.15s ease;\n user-select: none;\n outline: none;\n }\n\n /* State=Hover / State=Pressed / State=Active / State=Disabled. Active (the\n trigger whose menu is open) is the hover overlay plus a medium label \u2014\n hence the .open class rather than .active, which would collide with the\n :active pressed pseudo at equal specificity. */\n .menubar-trigger:hover:not(.disabled) {\n background: var(--rel-action-overlay-hover);\n }\n\n .menubar-trigger:active:not(.disabled) {\n background: var(--rel-action-overlay-pressed);\n }\n\n .menubar-trigger.open:not(.disabled) {\n background: var(--rel-action-overlay-hover);\n font-weight: var(--rel-body-lg-medium-font-weight);\n }\n\n .menubar-trigger.disabled {\n color: var(--rel-text-disabled);\n background: transparent;\n cursor: not-allowed;\n }\n\n /* Inset ring: the container clips (overflow:hidden), so a positive\n outline-offset would be cut off on the first and last trigger. */\n .menubar-trigger:focus-visible {\n outline: 2px solid var(--rel-border-focus);\n outline-offset: -2px;\n }\n\n /* Figma pairs the Menu Bar with the Menu component (6326:2932) for the\n panel each trigger opens: 300px, bg/fill/neutral/default, border\n radius/sm, shadow/md, clipped \u2014 no border. */\n .menubar-panel,\n .submenu-panel {\n position: fixed;\n width: var(--rel-menubar-panel-width, 300px);\n box-sizing: border-box;\n background: var(--rel-bg-neutral);\n border-radius: var(--rel-border-radius-sm);\n box-shadow: var(--rel-shadows-md);\n padding: 0;\n overflow: hidden;\n display: none;\n outline: none;\n }\n\n .menubar-panel {\n z-index: 1000;\n }\n\n .submenu-panel {\n z-index: 1001;\n }\n\n .menubar-panel.open,\n .submenu-panel.open {\n display: block;\n }\n\n /* Rows follow Figma .Menu Item Large (6326:616): spacing/sm padding all\n round on a body/lg label = 48px, with a border/neutral/subtle rule\n between rows. The rule is an INSET shadow, not a border: Figma strokes\n are drawn inside the 48px frame, so a real border-bottom would push\n every row to 49px. */\n .menu-item {\n position: relative;\n display: flex;\n align-items: center;\n gap: var(--rel-spacing-md);\n padding: var(--rel-spacing-sm);\n min-height: 48px;\n box-sizing: border-box;\n box-shadow: inset 0 calc(-1 * var(--rel-stroke-sm)) 0 var(--rel-border-subtle);\n cursor: pointer;\n transition: background 0.15s ease;\n user-select: none;\n color: var(--rel-text-default);\n line-height: var(--rel-body-lg-regular-line-height);\n }\n\n .menu-label {\n flex: 1 1 auto;\n }\n\n .menu-item:hover,\n .menu-item.focused {\n background: var(--rel-action-overlay-hover);\n }\n\n .menu-item:active {\n background: var(--rel-action-overlay-pressed);\n }\n\n .menu-item[data-disabled=\"true\"] {\n opacity: 0.4;\n cursor: not-allowed;\n }\n\n .menu-separator {\n height: var(--rel-stroke-sm);\n background: var(--rel-border-
|
|
2345
|
+
static readonly _css = "\n /* This component renders into LIGHT DOM (createRenderRoot returns this), so\n :host / <slot> don't work here \u2014 the raw <rel-menubar-menu> definitions\n are data holders that must be hidden with a plain selector. Relying on the\n global rel-menubar-menu.css is not enough: it can't cross a consumer's\n shadow boundary AND it's a no-op in the tsup-built package (css:\"copy\"). */\n rel-menubar {\n color: var(--rel-text-default);\n display: block;\n /* Figma Menu Bar / .Menu Bar Item (8699:4, 8698:13) label = body/lg.\n Declared on the host, not on .menubar-container, so the position:fixed\n panels \u2014 siblings of the container, not descendants \u2014 inherit it too. */\n font-family: var(--rel-body-lg-regular-font-family);\n font-weight: var(--rel-body-lg-regular-font-weight);\n font-size: var(--rel-body-lg-regular-font-size);\n line-height: var(--rel-body-lg-regular-line-height);\n letter-spacing: var(--rel-body-lg-regular-letter-spacing);\n }\n\n rel-menubar-menu {\n display: none;\n }\n\n /* Figma Menu Bar (8699:4): bg/fill/neutral/default on border-radius/sm,\n clipping its children, gap spacing/none \u2014 no border and no shadow. */\n .menubar-container {\n display: flex;\n align-items: stretch;\n background: var(--rel-bg-neutral);\n border-radius: var(--rel-border-radius-sm);\n overflow: hidden;\n padding: 0;\n gap: 0;\n min-height: 40px;\n width: fit-content;\n }\n\n /* Type=Fit hugs its triggers (the default); Type=Fixed spans its container.\n Light-DOM component: :host never matches, so these key off the reflected\n attribute on the <rel-menubar> element itself. */\n rel-menubar[type=\"fixed\"] .menubar-container {\n width: var(--rel-menubar-width, 100%);\n }\n\n rel-menubar[type=\"fit\"] .menubar-container {\n width: fit-content;\n }\n\n /* Figma .Menu Bar Item (8698:13): spacing/xs vertical + spacing/md\n horizontal padding around a body/lg label = a 40px trigger. */\n .menubar-trigger {\n display: flex;\n align-items: center;\n justify-content: center;\n align-self: stretch;\n padding: var(--rel-spacing-xs) var(--rel-spacing-md);\n background: transparent;\n border: none;\n cursor: pointer;\n font: inherit;\n color: var(--rel-text-default);\n white-space: nowrap;\n transition: background 0.15s ease;\n user-select: none;\n outline: none;\n }\n\n /* State=Hover / State=Pressed / State=Active / State=Disabled. Active (the\n trigger whose menu is open) is the hover overlay plus a medium label \u2014\n hence the .open class rather than .active, which would collide with the\n :active pressed pseudo at equal specificity. */\n .menubar-trigger:hover:not(.disabled) {\n background: var(--rel-action-overlay-hover);\n }\n\n .menubar-trigger:active:not(.disabled) {\n background: var(--rel-action-overlay-pressed);\n }\n\n .menubar-trigger.open:not(.disabled) {\n background: var(--rel-action-overlay-hover);\n font-weight: var(--rel-body-lg-medium-font-weight);\n }\n\n .menubar-trigger.disabled {\n color: var(--rel-text-disabled);\n background: transparent;\n cursor: not-allowed;\n }\n\n /* Inset ring: the container clips (overflow:hidden), so a positive\n outline-offset would be cut off on the first and last trigger. */\n .menubar-trigger:focus-visible {\n outline: 2px solid var(--rel-border-focus);\n outline-offset: -2px;\n }\n\n /* Figma pairs the Menu Bar with the Menu component (6326:2932) for the\n panel each trigger opens: 300px, bg/fill/neutral/default, border\n radius/sm, shadow/md, clipped \u2014 no border. */\n .menubar-panel,\n .submenu-panel {\n position: fixed;\n width: var(--rel-menubar-panel-width, 300px);\n box-sizing: border-box;\n background: var(--rel-bg-neutral);\n border-radius: var(--rel-border-radius-sm);\n box-shadow: var(--rel-shadows-md);\n padding: 0;\n overflow: hidden;\n display: none;\n outline: none;\n }\n\n .menubar-panel {\n z-index: 1000;\n }\n\n .submenu-panel {\n z-index: 1001;\n }\n\n .menubar-panel.open,\n .submenu-panel.open {\n display: block;\n }\n\n /* Rows follow Figma .Menu Item Large (6326:616): spacing/sm padding all\n round on a body/lg label = 48px, with a border/neutral/subtle rule\n between rows. The rule is an INSET shadow, not a border: Figma strokes\n are drawn inside the 48px frame, so a real border-bottom would push\n every row to 49px. */\n .menu-item {\n position: relative;\n display: flex;\n align-items: center;\n gap: var(--rel-spacing-md);\n padding: var(--rel-spacing-sm);\n min-height: 48px;\n box-sizing: border-box;\n box-shadow: inset 0 calc(-1 * var(--rel-stroke-sm)) 0 var(--rel-border-subtle);\n cursor: pointer;\n transition: background 0.15s ease;\n user-select: none;\n color: var(--rel-text-default);\n line-height: var(--rel-body-lg-regular-line-height);\n }\n\n .menu-label {\n flex: 1 1 auto;\n }\n\n .menu-item:hover,\n .menu-item.focused {\n background: var(--rel-action-overlay-hover);\n }\n\n .menu-item:active {\n background: var(--rel-action-overlay-pressed);\n }\n\n .menu-item[data-disabled=\"true\"] {\n opacity: 0.4;\n cursor: not-allowed;\n }\n\n /* border-subtle, like rel-menu's Figma-bound row strokes (Menu Bar binds\n no separator colour of its own). */\n .menu-separator {\n height: var(--rel-stroke-sm);\n background: var(--rel-border-subtle);\n margin: 0;\n padding: 0;\n }\n\n /* An explicit data-separator replaces the preceding row's subtle rule\n instead of stacking a second line on top of it. */\n .menu-item:has(+ .menu-separator),\n .menubar-panel > rel-checkbox:has(+ .menu-separator),\n .menubar-panel > rel-radio:has(+ .menu-separator) {\n box-shadow: none;\n }\n\n rel-icon {\n display: inline-flex;\n pointer-events: none;\n }\n\n .menu-submenu-trigger {\n position: relative;\n }\n\n /* Figma draws the 20px chevron at full contrast \u2014 no dimming. */\n .submenu-chevron {\n margin-left: auto;\n display: inline-flex;\n align-items: center;\n pointer-events: none;\n }\n\n .menu-shortcut {\n margin-left: auto;\n padding-left: var(--rel-spacing-md);\n display: flex;\n align-items: center;\n gap: var(--rel-spacing-3xs);\n color: var(--rel-text-caption);\n font-family: var(--rel-body-sm-regular-font-family);\n font-weight: var(--rel-body-sm-regular-font-weight);\n font-size: var(--rel-body-sm-regular-font-size);\n line-height: var(--rel-body-sm-regular-line-height);\n letter-spacing: var(--rel-body-sm-regular-letter-spacing);\n }\n\n /* Checkbox / radio rows are real rel-checkbox / rel-radio elements rendered\n straight into the panel, so they carry the .Menu Item row box themselves. */\n .menubar-panel > rel-checkbox,\n .menubar-panel > rel-radio {\n display: block;\n width: 100%;\n min-height: 48px;\n padding: var(--rel-spacing-sm);\n box-sizing: border-box;\n box-shadow: inset 0 calc(-1 * var(--rel-stroke-sm)) 0 var(--rel-border-subtle);\n }\n\n .menubar-panel > rel-checkbox {\n cursor: pointer;\n transition: background 0.15s ease;\n }\n\n .menubar-panel > rel-checkbox:hover {\n background: var(--rel-action-overlay-hover);\n }\n ";
|
|
1928
2346
|
createRenderRoot(): this;
|
|
1929
2347
|
connectedCallback(): void;
|
|
1930
2348
|
disconnectedCallback(): void;
|
|
@@ -1963,7 +2381,7 @@ declare class RelMenubar extends LitElement {
|
|
|
1963
2381
|
/**
|
|
1964
2382
|
* Declarative menu definition for `<rel-menubar>`: a hidden (`display: none`) light-DOM holder whose children (`data-item`, `data-separator`, `data-submenu`, `data-checkbox`, `data-radio-group`) the parent menubar reads and renders into a dropdown panel.
|
|
1965
2383
|
*/
|
|
1966
|
-
declare class RelMenubarMenu extends
|
|
2384
|
+
declare class RelMenubarMenu extends RelElement {
|
|
1967
2385
|
/** Text of the trigger button the parent menubar renders for this menu. */
|
|
1968
2386
|
label: string;
|
|
1969
2387
|
/**
|
|
@@ -1996,7 +2414,7 @@ type OtpSize = "small" | "medium" | "large" | "sm" | "md" | "lg";
|
|
|
1996
2414
|
* @csspart separator - The dash rendered between cell groups
|
|
1997
2415
|
* @csspart hidden-input - The hidden form input rendered when `name` is set
|
|
1998
2416
|
*/
|
|
1999
|
-
declare class RelOtp extends
|
|
2417
|
+
declare class RelOtp extends RelElement {
|
|
2000
2418
|
/** The concatenated code (all cells joined). Set it to fill the cells programmatically; it never exceeds `length` characters. */
|
|
2001
2419
|
value: string;
|
|
2002
2420
|
/** Total number of cells (characters in the code). */
|
|
@@ -2036,7 +2454,7 @@ declare class RelOtp extends LitElement {
|
|
|
2036
2454
|
ariaLabel: string | null;
|
|
2037
2455
|
/** Error styling (danger border on every cell) and `aria-invalid="true"`. */
|
|
2038
2456
|
invalid: boolean;
|
|
2039
|
-
/** Renders the dash separator between groups.
|
|
2457
|
+
/** Renders the dash separator between groups. Presence or `""` means true; `show-separator="false"` (or the property set to `false`) hides them. Even when on, separators appear only if `length` divides evenly by `group-size`; see `groupSize`. */
|
|
2040
2458
|
showSeparator: boolean;
|
|
2041
2459
|
/** Cell size on the shared field scale (square, border-box): `small` 32px, `medium` 40px, `large` 48px (the Figma OTP Input cell). `sm` / `md` / `lg` are deprecated aliases of the full words. */
|
|
2042
2460
|
size: OtpSize;
|
|
@@ -2077,415 +2495,84 @@ declare global {
|
|
|
2077
2495
|
}
|
|
2078
2496
|
}
|
|
2079
2497
|
|
|
2498
|
+
type SelectState = "default" | "error" | "disabled";
|
|
2499
|
+
type SelectSize = "small" | "medium" | "large";
|
|
2500
|
+
type SelectBorder = "rounded" | "sharp";
|
|
2501
|
+
/** Alias of the shared field type — kept so existing imports keep resolving. */
|
|
2502
|
+
type SelectLabelStyle = FieldLabelStyle;
|
|
2503
|
+
interface SelectOptionObject {
|
|
2504
|
+
value: string;
|
|
2505
|
+
label?: string;
|
|
2506
|
+
supportingText?: string;
|
|
2507
|
+
/** rel-icon name rendered as a prefix (leading icon) on the menu item. */
|
|
2508
|
+
icon?: string;
|
|
2509
|
+
}
|
|
2510
|
+
type SelectOption = string | SelectOptionObject;
|
|
2080
2511
|
/**
|
|
2081
|
-
*
|
|
2082
|
-
*
|
|
2083
|
-
* @csspart label - The
|
|
2512
|
+
* `<rel-select>` — combobox-style dropdown (Figma "Dropdown"): single- or multi-select
|
|
2513
|
+
* with an optional in-panel search field and width-adaptive selection chips.
|
|
2514
|
+
* @csspart label - The visible label above the trigger (default label style)
|
|
2515
|
+
* @csspart trigger - The button that opens the panel; styled like a text field
|
|
2516
|
+
* @csspart value - The value area: the selected label or placeholder inside the trigger. In multi-select with chips (since 1.5.0) it is the chip overlay, a sibling laid over the trigger's value area rather than a child of it
|
|
2517
|
+
* @csspart helper - The supporting / error text below the trigger
|
|
2518
|
+
* @csspart panel - The dropdown panel (a `role="group"` holding the search, Select-all and the options listbox; same node as `list`)
|
|
2519
|
+
* @csspart list - Alias of `panel`
|
|
2520
|
+
* @csspart input - The search input inside the panel
|
|
2521
|
+
* @csspart option - A single-select option row
|
|
2522
|
+
* @csspart option-label - A single-select row's first line (the option label)
|
|
2523
|
+
* @csspart option-supporting-text - A single-select row's optional second line; rendered only when the option supplies `supportingText`
|
|
2524
|
+
* @cssprop --rel-field-label-reserve - Height held for the label row whenever no label renders above the trigger — `labelStyle="none"`, and `labelStyle="floating"` where the label sits inside the trigger — so the trigger still lines up with labelled siblings in a form row. Defaults to that size's label line-height plus the wrapper gap (24px at `small`, 26px at `medium` and `large`). Set to `0` to collapse the row entirely (toolbars, table cells).
|
|
2525
|
+
* @cssprop --rel-select-bg - Background of the trigger, the panel and its sticky header. No longer paints behind the floating label — see `--rel-select-surface`.
|
|
2526
|
+
* @cssprop --rel-select-bg-disabled - Trigger background when `state="disabled"`
|
|
2527
|
+
* @cssprop --rel-select-surface - Colour of the strip the floating label lays over the trigger's top border and focus ring, so the label appears to sit in a notch. It overshoots the band by 2px on the page side, so it must match the surface the field sits on. Defaults to `--rel-select-bg`. Set it when the field sits on a surface that is not the trigger's own fill, otherwise the strip shows as a short dash of the wrong colour. Mirrors `--rel-textfield-surface`.
|
|
2528
|
+
* @cssprop --rel-select-surface-disabled - The same strip while `state="disabled"`, where the trigger fill changes. Defaults to `--rel-select-bg-disabled`.
|
|
2529
|
+
* @cssprop --rel-select-border-default - Trigger border colour at rest
|
|
2530
|
+
* @cssprop --rel-select-border-disabled - Trigger border colour when `state="disabled"`
|
|
2531
|
+
* @cssprop --rel-select-border-focus - Trigger border colour on hover, while focused (where it also thickens to 2px) and while the panel is open
|
|
2532
|
+
* @cssprop --rel-select-border-error - Trigger border colour when `state="error"`
|
|
2533
|
+
* @cssprop --rel-select-radius - Trigger corner radius when `border="rounded"`
|
|
2534
|
+
* @cssprop --rel-select-icon-color - Colour of the trigger icons, the search icon and option prefix icons
|
|
2535
|
+
* @cssprop --rel-select-label-color - Colour of the static label and of the floated label
|
|
2536
|
+
* @cssprop --rel-select-value-color - Colour of the selected value, the search text, option labels and the check mark
|
|
2537
|
+
* @cssprop --rel-select-placeholder-color - Placeholder colour (trigger, resting floating label, search field, empty-list message)
|
|
2538
|
+
* @cssprop --rel-select-placeholder-disabled-color - Placeholder colour when disabled
|
|
2539
|
+
* @cssprop --rel-select-supporting-color - Supporting text colour (non-error)
|
|
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
|
+
* @cssprop --rel-select-menu-radius - Panel corner radius
|
|
2542
|
+
* @cssprop --rel-select-menu-shadow - Panel box-shadow
|
|
2543
|
+
* @cssprop --rel-select-search-border - Border colour of the search field inside the panel
|
|
2544
|
+
* @cssprop --rel-select-divider - Hairline under the search field, the Select-all row and every option row
|
|
2545
|
+
* @cssprop --rel-select-option-hover - Background of the hovered / keyboard-highlighted / selected option and Select-all row
|
|
2546
|
+
* @cssprop --rel-select-option-pressed - Background of an option row while it is being pressed
|
|
2547
|
+
* @cssprop --rel-overlay-fallback-z - z-index of the panel on the **no-Popover-API fallback path only**. Wherever the browser top layer is available the panel is promoted into it and this value is inert, because top-layer elements are not in the page stacking order at all. Shared with the other overlays (select, autocomplete, the three pickers) so the whole family can be moved from one place.
|
|
2084
2548
|
*/
|
|
2085
|
-
declare class
|
|
2086
|
-
/**
|
|
2087
|
-
|
|
2088
|
-
/** Controlled current page (1-based). When set, the element only emits `rel-change` and waits for the parent to update `page`; leave unset for uncontrolled behaviour. */
|
|
2089
|
-
page?: number;
|
|
2090
|
-
/** Starting page for uncontrolled use (ignored when `page` is set). Attribute `defaultPage`, also read once as `default-page` on connect. */
|
|
2091
|
-
defaultPage: number;
|
|
2092
|
-
/** Total number of pages. `0` (the default) lets `totalItems` / `perPage` compute the page count instead. Attribute `totalPages`, also read once as `total-pages` on connect. */
|
|
2093
|
-
totalPages: number;
|
|
2094
|
-
/** Total item count; with `perPage` it computes the page count when `totalPages` is `0` and is the "of N" figure in the count-text readout. Attribute `totalItems`, also read once as `total-items` on connect. */
|
|
2095
|
-
totalItems: number;
|
|
2096
|
-
/** Items per page, used to compute the page count from `totalItems` and the "start–end" range in the count-text readout. Attribute `perPage`, also read once as `per-page` on connect. */
|
|
2097
|
-
perPage: number;
|
|
2098
|
-
/** Shows a "Viewing page X of Y" caption under the extended layout (ignored by the other types). */
|
|
2549
|
+
declare class RelSelect extends RelElement {
|
|
2550
|
+
/** Visible label. Rendered above the trigger (`labelStyle="default"`) or floating inside it; omitted under `labelStyle="none"`. */
|
|
2551
|
+
label: string;
|
|
2099
2552
|
/**
|
|
2100
|
-
*
|
|
2101
|
-
*
|
|
2102
|
-
*
|
|
2103
|
-
* their 78px height (40 + spacing-md + 22). Here it stays opt-in. Ruled by
|
|
2104
|
-
* the user: our behaviour stands and the DESIGN FILE follows our docs.
|
|
2105
|
-
* Defaulting it on would silently add 38px to every existing extended
|
|
2106
|
-
* pagination.
|
|
2553
|
+
* Label presentation: `default` static label above the trigger; `floating` label
|
|
2554
|
+
* rests in the value area and floats onto the border when focused, open or filled;
|
|
2555
|
+
* `none` renders no label (supply `fieldAriaLabel` / `fieldAriaLabelledby`).
|
|
2107
2556
|
*/
|
|
2108
|
-
|
|
2109
|
-
/** Dims the whole control to 40% opacity, shows a `not-allowed` cursor and ignores every page change. */
|
|
2110
|
-
disabled: boolean;
|
|
2111
|
-
/** Reserved for link-mode pagination. Currently accepted but not rendered: every page control is a `<button>`, so navigate in your `rel-change` handler instead. */
|
|
2112
|
-
hrefTemplate: string;
|
|
2113
|
-
/** Accessible name of the `role="navigation"` landmark (attribute `ariaLabel`). Set it when a page contains more than one pagination control. */
|
|
2114
|
-
ariaLabel: string;
|
|
2115
|
-
private currentPage;
|
|
2116
|
-
static styles: lit.CSSResult;
|
|
2117
|
-
connectedCallback(): void;
|
|
2118
|
-
updated(changedProperties: Map<string, unknown>): void;
|
|
2119
|
-
private get activePage();
|
|
2120
|
-
private get computedTotalPages();
|
|
2121
|
-
private generatePageNumbers;
|
|
2122
|
-
/** Abbreviate large page numbers (368178 → "368k") so buttons stay compact.
|
|
2123
|
-
Exact below 10,000; floored to k up to 1M; then M with one decimal. */
|
|
2124
|
-
private formatPageLabel;
|
|
2125
|
-
private handlePageChange;
|
|
2126
|
-
private renderChevronLeft;
|
|
2127
|
-
private renderChevronRight;
|
|
2128
|
-
private renderNavBtn;
|
|
2129
|
-
private renderExtended;
|
|
2130
|
-
private renderCompact;
|
|
2131
|
-
private renderCountText;
|
|
2132
|
-
render(): lit_html.TemplateResult<1>;
|
|
2133
|
-
}
|
|
2134
|
-
|
|
2135
|
-
type SideType = "top" | "right" | "bottom" | "left";
|
|
2136
|
-
type AlignType = "start" | "center" | "end";
|
|
2137
|
-
/**
|
|
2138
|
-
* Click-to-open floating panel anchored to a trigger (Figma "Popover"): the first child is the trigger, the `content` slot is the panel, which is promoted to the browser top layer and positioned in viewport coordinates.
|
|
2139
|
-
* @slot - The trigger: the first slotted element toggles the panel on pointer down / Enter / Space and receives `aria-haspopup`, `aria-expanded` and `aria-controls` (a bare `<div>` / `<span>` also gets `tabindex="0"` and `role="button"`).
|
|
2140
|
-
* @slot content - The panel body, usually a `<rel-popover-content>`; rendered inside the fixed, top-layer wrapper only while open.
|
|
2141
|
-
* @csspart arrow - The 14×14 chevron box rendered on the panel edge facing the trigger when `arrow` is set (absent otherwise).
|
|
2142
|
-
* @cssprop --rel-popover-arrow-bg - Fill of the `arrow` chevron (default `--rel-bg-neutral`, matching `<rel-popover-content>`).
|
|
2143
|
-
* @cssprop --rel-popover-arrow-border - **Deprecated.** Stroke of the `arrow` chevron's two slanted edges. The panel no longer draws a border — overlapping surfaces are separated by shadow — so this defaults to `transparent` and the chevron has no edge. Set it to restore a stroke.
|
|
2144
|
-
*/
|
|
2145
|
-
declare class RelPopover extends LitElement {
|
|
2146
|
-
/** Controlled open state. Leave unset for uncontrolled mode; once set (true or false) the component only emits `rel-open-change` and you must update `open` yourself. */
|
|
2147
|
-
open?: boolean;
|
|
2148
|
-
/** Initial state in uncontrolled mode (attribute `defaultopen`); ignored when `open` is set. */
|
|
2149
|
-
defaultOpen: boolean;
|
|
2150
|
-
/** Blocks trigger interaction and dims the host to 60% opacity; does not close an already-open panel. */
|
|
2151
|
-
disabled: boolean;
|
|
2152
|
-
/** Which side of the trigger the panel opens on: `top`, `right`, `bottom` (default) or `left`. The panel is clamped 8px inside the viewport but never flips to another side. */
|
|
2153
|
-
side: SideType;
|
|
2154
|
-
/** Alignment along the cross axis: `start` (left / top edge of the trigger), `center` (default) or `end` (right / bottom edge). */
|
|
2155
|
-
align: AlignType;
|
|
2156
|
-
/** Gap between trigger and panel in pixels (attribute `sideoffset`, default 8). With `arrow` the effective gap is at least 13px. */
|
|
2157
|
-
sideOffset: number;
|
|
2158
|
-
/** Extra shift along the alignment axis in pixels (attribute `alignoffset`, default 0); positive moves right / down. */
|
|
2159
|
-
alignOffset: number;
|
|
2160
|
-
/** Keep Tab / Shift+Tab cycling inside the panel while open (attribute `trapfocus`); use for forms. */
|
|
2161
|
-
trapFocus: boolean;
|
|
2162
|
-
/** Close on Escape (attribute `closeonescape`, default true; switch off via the property, e.g. `el.closeOnEscape = false`). */
|
|
2163
|
-
closeOnEscape: boolean;
|
|
2164
|
-
/** Close on a pointer-down outside the trigger and panel (attribute `closeonoutsideclick`, default true; switch off via the property). Also lets another popover's opening dismiss this one. */
|
|
2165
|
-
closeOnOutsideClick: boolean;
|
|
2557
|
+
labelStyle: SelectLabelStyle;
|
|
2166
2558
|
/**
|
|
2167
|
-
*
|
|
2168
|
-
*
|
|
2169
|
-
* the trigger's centre along the cross axis (clamped inside the panel).
|
|
2170
|
-
* It is drawn with the panel's tokens (`--rel-popover-arrow-bg` /
|
|
2171
|
-
* `--rel-popover-arrow-border`, defaulting to rel-popover-content's
|
|
2172
|
-
* background and border). With the arrow on, the panel keeps at least the
|
|
2173
|
-
* arrow's height plus 2px away from the trigger so the tip never overlaps
|
|
2174
|
-
* it; larger `sideOffset` values still apply. Default off — existing
|
|
2175
|
-
* popovers render exactly as before.
|
|
2559
|
+
* Accessible name for the trigger. Required when `labelStyle="none"`, since no
|
|
2560
|
+
* `<label>` renders and a placeholder is not a valid naming mechanism.
|
|
2176
2561
|
*/
|
|
2177
|
-
|
|
2178
|
-
/**
|
|
2179
|
-
|
|
2180
|
-
private static readonly ARROW_HEIGHT;
|
|
2181
|
-
private internalOpen;
|
|
2182
|
-
private contentStyle;
|
|
2183
|
-
private contentWrapper;
|
|
2184
|
-
private triggerEl;
|
|
2185
|
-
private returnFocusEl;
|
|
2186
|
-
private uniqueId;
|
|
2187
|
-
static styles: lit.CSSResult;
|
|
2188
|
-
connectedCallback(): void;
|
|
2189
|
-
disconnectedCallback(): void;
|
|
2190
|
-
firstUpdated(): void;
|
|
2191
|
-
updated(changed: Map<string, unknown>): void;
|
|
2192
|
-
private isControlled;
|
|
2193
|
-
private get activeOpen();
|
|
2194
|
-
private setOpen;
|
|
2195
|
-
private onHostPointerDown;
|
|
2196
|
-
private onHostKeyDown;
|
|
2197
|
-
private onOpen;
|
|
2198
|
-
private onClose;
|
|
2562
|
+
fieldAriaLabel?: string;
|
|
2563
|
+
/** IDREF list of external element(s) naming the trigger. Wins over `fieldAriaLabel`. */
|
|
2564
|
+
fieldAriaLabelledby?: string;
|
|
2199
2565
|
/**
|
|
2200
|
-
*
|
|
2201
|
-
*
|
|
2202
|
-
*
|
|
2203
|
-
*
|
|
2204
|
-
*
|
|
2205
|
-
*
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
private addGlobalListeners;
|
|
2211
|
-
private removeGlobalListeners;
|
|
2212
|
-
private onOutsidePointerDown;
|
|
2213
|
-
private onKeyDown;
|
|
2214
|
-
private focusFirst;
|
|
2215
|
-
private restoreFocus;
|
|
2216
|
-
private trapFocusLoop;
|
|
2217
|
-
private getFocusable;
|
|
2218
|
-
private updatePosition;
|
|
2219
|
-
private onTriggerSlotChange;
|
|
2220
|
-
private applyTriggerAria;
|
|
2221
|
-
render(): lit_html.TemplateResult<1>;
|
|
2222
|
-
}
|
|
2223
|
-
declare global {
|
|
2224
|
-
interface HTMLElementTagNameMap {
|
|
2225
|
-
"rel-popover": RelPopover;
|
|
2226
|
-
}
|
|
2227
|
-
}
|
|
2228
|
-
|
|
2229
|
-
/** Figma Size axis, spelled out. */
|
|
2230
|
-
type PopoverContentSize = "small" | "medium" | "large";
|
|
2231
|
-
/** Alternative spellings, not deprecations — the short names keep working. */
|
|
2232
|
-
type PopoverContentSizeAlias = "sm" | "md" | "lg";
|
|
2233
|
-
type PopoverContentSizeInput = PopoverContentSize | PopoverContentSizeAlias;
|
|
2234
|
-
/**
|
|
2235
|
-
* Styled panel body for `<rel-popover>` (Figma "Popover" surface): neutral background, 1px border, 8px radius, shadow-300, max-width 400px, with heading / paragraph typography for slotted content. Place it in the popover's `content` slot; any other element works there too.
|
|
2236
|
-
* @slot - The panel content (headings, paragraphs, form controls, buttons).
|
|
2237
|
-
* @csspart content - The padded `role="dialog"` box that carries the surface, border, shadow and size padding.
|
|
2238
|
-
*/
|
|
2239
|
-
declare class RelPopoverContent extends LitElement {
|
|
2240
|
-
/** Accessible name applied to the inner `role="dialog"` box (attribute `aria-label`); describe what the panel is for. */
|
|
2241
|
-
ariaLabel: string;
|
|
2242
|
-
/** Figma Size axis: panel padding 12px (`small`), 16px (`medium`, default) or 20px (`large`). `sm` / `md` / `lg` are alternative spellings and stay supported — they are normalised to the full words, not deprecated. */
|
|
2243
|
-
size: PopoverContentSizeInput;
|
|
2244
|
-
/** Alternative spellings, NOT deprecations — no console notice. Normalising
|
|
2245
|
-
* keeps the reflected attribute canonical, so the :host([size=…]) rules only
|
|
2246
|
-
* need the full words. */
|
|
2247
|
-
protected willUpdate(changed: Map<string, unknown>): void;
|
|
2248
|
-
static styles: lit.CSSResult;
|
|
2249
|
-
render(): lit_html.TemplateResult<1>;
|
|
2250
|
-
}
|
|
2251
|
-
|
|
2252
|
-
type ProgressMode = "linear-determinate" | "linear-indeterminate" | "circular-determinate" | "circular-indeterminate";
|
|
2253
|
-
/**
|
|
2254
|
-
* Progress indicator (Figma "Progress"): a linear bar or a circular ring, each either value-driven (determinate) or looping (indeterminate).
|
|
2255
|
-
* @csspart track - The linear track `<div>` that carries `role="progressbar"` (linear modes only)
|
|
2256
|
-
* @csspart indicator - The filled / sliding bar inside the linear track (linear modes only)
|
|
2257
|
-
*/
|
|
2258
|
-
declare class RelProgress extends LitElement {
|
|
2259
|
-
/** Shape and behaviour: `linear-*` is a full-width 2px bar, `circular-*` a 36px ring; `*-determinate` fills to `value`, `*-indeterminate` loops an animation and ignores `value`. */
|
|
2260
|
-
mode: ProgressMode;
|
|
2261
|
-
/** Completion percentage 0–100 for the determinate modes; out-of-range values are clamped before rendering and before `aria-valuenow`. */
|
|
2262
|
-
value: number;
|
|
2263
|
-
/** Accessible name of the progressbar (not rendered visually); defaults to "Progress" for determinate and "Loading" for indeterminate modes. */
|
|
2264
|
-
label: string;
|
|
2265
|
-
private radius;
|
|
2266
|
-
private circumference;
|
|
2267
|
-
static styles: lit.CSSResult;
|
|
2268
|
-
private get safeValue();
|
|
2269
|
-
private get accessibleName();
|
|
2270
|
-
private renderLinearDeterminate;
|
|
2271
|
-
private renderLinearIndeterminate;
|
|
2272
|
-
private renderCircularDeterminate;
|
|
2273
|
-
private renderCircularIndeterminate;
|
|
2274
|
-
render(): lit_html.TemplateResult<1>;
|
|
2275
|
-
}
|
|
2276
|
-
|
|
2277
|
-
/**
|
|
2278
|
-
* Flex container that lays out direct-child `<rel-resizable-panel>`s along one axis and lets the user drag or keyboard-nudge the `<rel-resizable-handle>` between two neighbours to trade percentage width/height between them.
|
|
2279
|
-
* @slot - The panels and handles, as direct children in display order (panel, handle, panel, …)
|
|
2280
|
-
* @fires rel-resize - Fired continuously while a handle is dragged. Detail: `{ direction, sizes: number[] }` with one percentage per panel.
|
|
2281
|
-
* @fires rel-resize-end - Fired once when a drag ends (pointerup) and after every keyboard resize step. Detail: `{ direction, sizes: number[] }` with one percentage per panel.
|
|
2282
|
-
*/
|
|
2283
|
-
declare class RelResizableGroup extends LitElement {
|
|
2284
|
-
/** Layout axis: `horizontal` places panels side by side and resizes widths, `vertical` stacks them and resizes heights; also pushed to every child handle's `orientation`. */
|
|
2285
|
-
direction: "horizontal" | "vertical";
|
|
2286
|
-
private panels;
|
|
2287
|
-
private handles;
|
|
2288
|
-
private isDragging;
|
|
2289
|
-
private activeHandleIndex;
|
|
2290
|
-
private startPointerPos;
|
|
2291
|
-
private startSizes;
|
|
2292
|
-
static styles: lit.CSSResult;
|
|
2293
|
-
connectedCallback(): void;
|
|
2294
|
-
disconnectedCallback(): void;
|
|
2295
|
-
firstUpdated(): void;
|
|
2296
|
-
private initializeLayout;
|
|
2297
|
-
private calculateInitialSizes;
|
|
2298
|
-
private onPointerDown;
|
|
2299
|
-
private startDrag;
|
|
2300
|
-
private onPointerMove;
|
|
2301
|
-
private onPointerUp;
|
|
2302
|
-
private applyDragResize;
|
|
2303
|
-
private onKeyDown;
|
|
2304
|
-
private applyKeyboardResize;
|
|
2305
|
-
private applySizes;
|
|
2306
|
-
private dispatchResizeEvent;
|
|
2307
|
-
private addGlobalListeners;
|
|
2308
|
-
private removeGlobalListeners;
|
|
2309
|
-
render(): lit_html.TemplateResult<1>;
|
|
2310
|
-
}
|
|
2311
|
-
declare global {
|
|
2312
|
-
interface HTMLElementTagNameMap {
|
|
2313
|
-
"rel-resizable-group": RelResizableGroup;
|
|
2314
|
-
}
|
|
2315
|
-
}
|
|
2316
|
-
|
|
2317
|
-
/**
|
|
2318
|
-
* One resizable region inside a `<rel-resizable-group>`: a padded, scrollable (`overflow: auto`) flex column whose size along the group axis is a percentage managed by the group.
|
|
2319
|
-
* @slot - The panel's content; slotted `h1`–`h4` get the headings-md role
|
|
2320
|
-
*/
|
|
2321
|
-
declare class RelResizablePanel extends LitElement {
|
|
2322
|
-
/** Initial size as a percentage of the group; panels without one share whatever is left of 100%, then all sizes are normalised to sum to 100. Attribute is `defaultsize`. */
|
|
2323
|
-
defaultSize?: number;
|
|
2324
|
-
/** Smallest size (percentage) the panel can be resized to. Attribute is `minsize`. */
|
|
2325
|
-
minSize: number;
|
|
2326
|
-
/** Largest size (percentage) the panel can be resized to. Attribute is `maxsize`. */
|
|
2327
|
-
maxSize: number;
|
|
2328
|
-
/** Current size as a percentage of the group (also written to the host's `flex-basis`); read-only — the parent group updates it on every resize. */
|
|
2329
|
-
currentSize: number;
|
|
2330
|
-
static styles: lit.CSSResult;
|
|
2331
|
-
render(): lit_html.TemplateResult<1>;
|
|
2332
|
-
}
|
|
2333
|
-
declare global {
|
|
2334
|
-
interface HTMLElementTagNameMap {
|
|
2335
|
-
"rel-resizable-panel": RelResizablePanel;
|
|
2336
|
-
}
|
|
2337
|
-
}
|
|
2338
|
-
|
|
2339
|
-
/**
|
|
2340
|
-
* Focusable `role="separator"` splitter placed between two `<rel-resizable-panel>`s inside a `<rel-resizable-group>`; the group owns the drag and keyboard logic, the handle only renders the grab bar and exposes the split via ARIA.
|
|
2341
|
-
*/
|
|
2342
|
-
declare class RelResizableHandle extends LitElement {
|
|
2343
|
-
/** Axis the handle separates: `horizontal` = 8px-wide vertical bar with `col-resize` cursor, `vertical` = 8px-tall bar with `row-resize`; set automatically from the parent group's `direction` on first render and mirrored to `aria-orientation`. */
|
|
2344
|
-
orientation: "horizontal" | "vertical";
|
|
2345
|
-
/** @internal Index of this handle in the parent group; assigned by the group on first render. */
|
|
2346
|
-
handleIndex: number;
|
|
2347
|
-
/** Current split of the two neighbouring panels as a percentage 0–100 (share held by the leading panel); read-only — the parent group updates it and mirrors it to `aria-valuenow`. */
|
|
2348
|
-
splitValue: number;
|
|
2349
|
-
static styles: lit.CSSResult;
|
|
2350
|
-
connectedCallback(): void;
|
|
2351
|
-
updated(changed: Map<string, unknown>): void;
|
|
2352
|
-
private updateAriaOrientation;
|
|
2353
|
-
/** @internal Called by the parent group after every resize to store `splitValue` and write `aria-valuenow` / `aria-valuemin` / `aria-valuemax`. */
|
|
2354
|
-
updateAriaValue(value: number): void;
|
|
2355
|
-
render(): lit_html.TemplateResult<1>;
|
|
2356
|
-
}
|
|
2357
|
-
declare global {
|
|
2358
|
-
interface HTMLElementTagNameMap {
|
|
2359
|
-
"rel-resizable-handle": RelResizableHandle;
|
|
2360
|
-
}
|
|
2361
|
-
}
|
|
2362
|
-
|
|
2363
|
-
type SegmentSize = "small" | "medium" | "large";
|
|
2364
|
-
type SegmentAlign = "left" | "middle" | "right";
|
|
2365
|
-
interface SegmentOption {
|
|
2366
|
-
label: string;
|
|
2367
|
-
value: string;
|
|
2368
|
-
disabled?: boolean;
|
|
2369
|
-
/** `rel-icon` name rendered before the label (Figma "Left Icon"), sized 16 / 18 / 20 with the control. */
|
|
2370
|
-
icon?: string;
|
|
2371
|
-
/**
|
|
2372
|
-
* Trailing badge (Figma "Show Badge" / "Badge"), rendered after the label
|
|
2373
|
-
* inside the segment's own 8px gap. A number or string shows the count at
|
|
2374
|
-
* `medium` and `large`; at `small` Figma switches to the 6px dot, so the
|
|
2375
|
-
* value is not displayed there. Use `true` for a dot at any size.
|
|
2376
|
-
*/
|
|
2377
|
-
badge?: number | string | boolean;
|
|
2378
|
-
}
|
|
2379
|
-
/**
|
|
2380
|
-
* Single-select segmented button group: renders one `<button role="radio">` per entry in `options` on a 2px-inset track (`role="radiogroup"`), with exactly one segment active at a time.
|
|
2381
|
-
* @csspart base - The `role="radiogroup"` track that lays out the segments.
|
|
2382
|
-
* @csspart option - Each segment's native `<button role="radio">`; the active one carries the `active` class and `aria-checked="true"`.
|
|
2383
|
-
* @csspart icon - A segment's optional leading `rel-icon` element.
|
|
2384
|
-
* @csspart badge - A segment's optional trailing `rel-badge`; rendered only when the option sets `badge`.
|
|
2385
|
-
* @csspart label - The wrapper around a segment's label text.
|
|
2386
|
-
*/
|
|
2387
|
-
declare class RelSegmentedButton extends LitElement {
|
|
2388
|
-
/** The segments in order, each `{ label: string; value: string; disabled?: boolean; icon?: string; badge?: number | string | boolean }`. Set as a property (or a JSON array attribute); a disabled entry is rendered but cannot be selected, and `icon` names a `rel-icon` drawn before the label. */
|
|
2389
|
-
options: SegmentOption[];
|
|
2390
|
-
/** `value` of the currently selected segment. Updated by the component on click / arrow keys; set it to pre-select a segment (an unknown value selects nothing). */
|
|
2391
|
-
active: string;
|
|
2392
|
-
/** Control height, matching the TextField ramp: `small` (32px — 28px segments, `action-md` 12px text, 16px icons), `medium` (default, 40px — 36px segments, `action-lg` 14px text, 18px icons) or `large` (48px — 44px segments, `action-xl` 16px text, 20px icons). */
|
|
2393
|
-
size: SegmentSize;
|
|
2394
|
-
/** `justify-content` of the group's inline-flex container: `left` (default), `middle` or `right`. Only visible when the host is made wider than its content. */
|
|
2395
|
-
align: SegmentAlign;
|
|
2396
|
-
/** Accessible name for the radiogroup (it renders no visible group label). */
|
|
2397
|
-
fieldAriaLabel?: string;
|
|
2398
|
-
static styles: lit.CSSResult;
|
|
2399
|
-
private setActive;
|
|
2400
|
-
/** APG radio-group navigation: arrows move focus AND select, the group is
|
|
2401
|
-
* one Tab stop (roving tabindex on the selected segment). */
|
|
2402
|
-
private onKeyDown;
|
|
2403
|
-
private renderSegment;
|
|
2404
|
-
/**
|
|
2405
|
-
* Figma's Show Badge axis: a 20x20 numeric badge at medium and large, and a
|
|
2406
|
-
* 6px dot at small — where the count is not shown at all, so a numeric value
|
|
2407
|
-
* degrades to a dot rather than being squeezed in. `badge: true` asks for the
|
|
2408
|
-
* dot at any size.
|
|
2409
|
-
*/
|
|
2410
|
-
private renderBadge;
|
|
2411
|
-
render(): lit_html.TemplateResult<1>;
|
|
2412
|
-
}
|
|
2413
|
-
|
|
2414
|
-
type SelectState = "default" | "error" | "disabled";
|
|
2415
|
-
type SelectSize = "small" | "medium" | "large";
|
|
2416
|
-
type SelectBorder = "rounded" | "sharp";
|
|
2417
|
-
/** Alias of the shared field type — kept so existing imports keep resolving. */
|
|
2418
|
-
type SelectLabelStyle = FieldLabelStyle;
|
|
2419
|
-
interface SelectOptionObject {
|
|
2420
|
-
value: string;
|
|
2421
|
-
label?: string;
|
|
2422
|
-
supportingText?: string;
|
|
2423
|
-
/** rel-icon name rendered as a prefix (leading icon) on the menu item. */
|
|
2424
|
-
icon?: string;
|
|
2425
|
-
}
|
|
2426
|
-
type SelectOption = string | SelectOptionObject;
|
|
2427
|
-
/**
|
|
2428
|
-
* `<rel-select>` — combobox-style dropdown (Figma "Dropdown"): single- or multi-select
|
|
2429
|
-
* with an optional in-panel search field and width-adaptive selection chips.
|
|
2430
|
-
* @csspart label - The visible label above the trigger (default label style)
|
|
2431
|
-
* @csspart trigger - The button that opens the panel; styled like a text field
|
|
2432
|
-
* @csspart value - The value area inside the trigger (selected label, placeholder or chips)
|
|
2433
|
-
* @csspart helper - The supporting / error text below the trigger
|
|
2434
|
-
* @csspart panel - The dropdown listbox container (same node as `list`)
|
|
2435
|
-
* @csspart list - Alias of `panel`
|
|
2436
|
-
* @csspart input - The search input inside the panel
|
|
2437
|
-
* @csspart option - A single-select option row
|
|
2438
|
-
* @csspart option-label - A single-select row's first line (the option label)
|
|
2439
|
-
* @csspart option-supporting-text - A single-select row's optional second line; rendered only when the option supplies `supportingText`
|
|
2440
|
-
* @cssprop --rel-field-label-reserve - Height held for the label row whenever no label renders above the trigger — `labelStyle="none"`, and `labelStyle="floating"` where the label sits inside the trigger — so the trigger still lines up with labelled siblings in a form row. Defaults to that size's label line-height plus the wrapper gap (24px at `small`, 26px at `medium` and `large`). Set to `0` to collapse the row entirely (toolbars, table cells).
|
|
2441
|
-
* @cssprop --rel-select-bg - Background of the trigger, the floating label, the panel and its sticky header
|
|
2442
|
-
* @cssprop --rel-select-bg-disabled - Trigger background when `state="disabled"`
|
|
2443
|
-
* @cssprop --rel-select-border-default - Trigger border colour at rest
|
|
2444
|
-
* @cssprop --rel-select-border-disabled - Trigger border colour when `state="disabled"`
|
|
2445
|
-
* @cssprop --rel-select-border-focus - Trigger border colour on hover, while focused (where it also thickens to 2px) and while the panel is open
|
|
2446
|
-
* @cssprop --rel-select-border-error - Trigger border colour when `state="error"`
|
|
2447
|
-
* @cssprop --rel-select-radius - Trigger corner radius when `border="rounded"`
|
|
2448
|
-
* @cssprop --rel-select-icon-color - Colour of the trigger icons, the search icon and option prefix icons
|
|
2449
|
-
* @cssprop --rel-select-label-color - Colour of the static label and of the floated label
|
|
2450
|
-
* @cssprop --rel-select-value-color - Colour of the selected value, the search text, option labels and the check mark
|
|
2451
|
-
* @cssprop --rel-select-placeholder-color - Placeholder colour (trigger, resting floating label, search field, empty-list message)
|
|
2452
|
-
* @cssprop --rel-select-placeholder-disabled-color - Placeholder colour when disabled
|
|
2453
|
-
* @cssprop --rel-select-supporting-color - Supporting text colour (non-error)
|
|
2454
|
-
* @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.
|
|
2455
|
-
* @cssprop --rel-select-menu-radius - Panel corner radius
|
|
2456
|
-
* @cssprop --rel-select-menu-shadow - Panel box-shadow
|
|
2457
|
-
* @cssprop --rel-select-search-border - Border colour of the search field inside the panel
|
|
2458
|
-
* @cssprop --rel-select-divider - Hairline under the search field, the Select-all row and every option row
|
|
2459
|
-
* @cssprop --rel-select-option-hover - Background of the hovered / keyboard-highlighted / selected option and Select-all row
|
|
2460
|
-
* @cssprop --rel-select-option-pressed - Background of an option row while it is being pressed
|
|
2461
|
-
*/
|
|
2462
|
-
declare class RelSelect extends LitElement {
|
|
2463
|
-
/** Visible label. Rendered above the trigger (`labelStyle="default"`) or floating inside it; omitted under `labelStyle="none"`. */
|
|
2464
|
-
label: string;
|
|
2465
|
-
/**
|
|
2466
|
-
* Label presentation: `default` static label above the trigger; `floating` label
|
|
2467
|
-
* rests in the value area and floats onto the border when focused, open or filled;
|
|
2468
|
-
* `none` renders no label (supply `fieldAriaLabel` / `fieldAriaLabelledby`).
|
|
2469
|
-
*/
|
|
2470
|
-
labelStyle: SelectLabelStyle;
|
|
2471
|
-
/**
|
|
2472
|
-
* Accessible name for the trigger. Required when `labelStyle="none"`, since no
|
|
2473
|
-
* `<label>` renders and a placeholder is not a valid naming mechanism.
|
|
2474
|
-
*/
|
|
2475
|
-
fieldAriaLabel?: string;
|
|
2476
|
-
/** IDREF list of external element(s) naming the trigger. Wins over `fieldAriaLabel`. */
|
|
2477
|
-
fieldAriaLabelledby?: string;
|
|
2478
|
-
/**
|
|
2479
|
-
* Options to list. Each entry is a plain string (used as both value and label) or
|
|
2480
|
-
* `{ value, label?, supportingText?, icon? }`; `icon` is a `rel-icon` name rendered
|
|
2481
|
-
* before the label, `supportingText` renders as a second line in both single- and multi-select rows.
|
|
2482
|
-
*
|
|
2483
|
-
* NOTE — the panel's search matches the LABEL ONLY. `supportingText` is displayed but not
|
|
2484
|
-
* searched, so an option is not findable by its second line here. This differs deliberately from
|
|
2485
|
-
* `rel-autocomplete`, whose filter matches the supporting line as well: there the second line
|
|
2486
|
-
* carries identifying data (a DOT or MC number) that a user types to find the row, whereas a
|
|
2487
|
-
* select's is descriptive ("Read-only", "Can edit, not delete") and matching it would return rows
|
|
2488
|
-
* whose visible label has nothing to do with the query.
|
|
2566
|
+
* Options to list. Each entry is a plain string (used as both value and label) or
|
|
2567
|
+
* `{ value, label?, supportingText?, icon? }`; `icon` is a `rel-icon` name rendered
|
|
2568
|
+
* before the label, `supportingText` renders as a second line in both single- and multi-select rows.
|
|
2569
|
+
*
|
|
2570
|
+
* NOTE — the panel's search matches the LABEL ONLY. `supportingText` is displayed but not
|
|
2571
|
+
* searched, so an option is not findable by its second line here. This differs deliberately from
|
|
2572
|
+
* `rel-autocomplete`, whose filter matches the supporting line as well: there the second line
|
|
2573
|
+
* carries identifying data (a DOT or MC number) that a user types to find the row, whereas a
|
|
2574
|
+
* select's is descriptive ("Read-only", "Can edit, not delete") and matching it would return rows
|
|
2575
|
+
* whose visible label has nothing to do with the query.
|
|
2489
2576
|
*/
|
|
2490
2577
|
options: SelectOption[];
|
|
2491
2578
|
/** Enables multi-select: selected values render as removable chips, options as checkboxes, and a Select-all row appears in the panel. */
|
|
@@ -2529,17 +2616,7 @@ declare class RelSelect extends LitElement {
|
|
|
2529
2616
|
* one by one instead of wrapping to a second line.
|
|
2530
2617
|
*/
|
|
2531
2618
|
maxVisibleChips: number;
|
|
2532
|
-
/** Hides the in-panel search field. Figma's "Single Option" dropdown has no search bar
|
|
2533
|
-
/**
|
|
2534
|
-
* DELIBERATE DIVERGENCE — do not default this to `!multiple`. Figma's
|
|
2535
|
-
* `.Menu Dropdown` shows the search row only on `Type=Multioption`; its
|
|
2536
|
-
* `Type=Single Option` panels contain five Select Option items and nothing
|
|
2537
|
-
* else. Here the search row renders for single-select too unless this is set.
|
|
2538
|
-
* Ruled by the user: our behaviour stands and the DESIGN FILE follows our
|
|
2539
|
-
* docs. A long single-select list is unusable without search, and making the
|
|
2540
|
-
* default depend on `multiple` would change the panel of every existing
|
|
2541
|
-
* single-select.
|
|
2542
|
-
*/
|
|
2619
|
+
/** Hides the in-panel search field. The search row shows in single- and multi-select panels alike unless this is set; use it for short lists that don't need searching (Figma's "Single Option" dropdown has no search bar). */
|
|
2543
2620
|
noSearch: boolean;
|
|
2544
2621
|
private open;
|
|
2545
2622
|
private highlightedIndex;
|
|
@@ -2596,48 +2673,486 @@ declare class RelSelect extends LitElement {
|
|
|
2596
2673
|
* through their own padding and min-height.
|
|
2597
2674
|
*/
|
|
2598
2675
|
private get optionCheckboxSize();
|
|
2676
|
+
/** Native tooltip carrying the row's full text. Both lines truncate to one
|
|
2677
|
+
* line with an ellipsis, so a long supporting line is otherwise unrecoverable
|
|
2678
|
+
* by sight; hovering the row reveals it. Only rows that carry a second line
|
|
2679
|
+
* get one, so plain lists do not sprout tooltips. */
|
|
2680
|
+
private rowTitle;
|
|
2599
2681
|
private get selectAllStatus();
|
|
2600
2682
|
private addGlobalListeners;
|
|
2601
2683
|
private removeGlobalListeners;
|
|
2602
|
-
private onOutsidePointerDown;
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
private
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
*
|
|
2621
|
-
*
|
|
2622
|
-
|
|
2623
|
-
private
|
|
2624
|
-
private
|
|
2625
|
-
private
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
private
|
|
2684
|
+
private onOutsidePointerDown;
|
|
2685
|
+
/** Outside scroll: reposition while the trigger is still visible, close
|
|
2686
|
+
* once it has scrolled out of view or under a sticky header; scrolls of
|
|
2687
|
+
* the list itself and of unrelated elements are ignored. See
|
|
2688
|
+
* utils/overlay-scroll.ts. The scroll close keeps focus on the trigger
|
|
2689
|
+
* without scrolling the page back to it. */
|
|
2690
|
+
private scrollWatch;
|
|
2691
|
+
/**
|
|
2692
|
+
* BOTH events fire, deliberately — do not delete either.
|
|
2693
|
+
*
|
|
2694
|
+
* This repo is split down the middle on the convention, not inconsistent in
|
|
2695
|
+
* one place: rel-select and rel-segmented-button emit `changed`, while
|
|
2696
|
+
* rel-switch, rel-checkbox and rel-radio emit `rel-change`. Renaming
|
|
2697
|
+
* `changed` would break every existing rel-select consumer, so 1.4.9 adds
|
|
2698
|
+
* the prefixed name alongside it rather than moving anyone. New code should
|
|
2699
|
+
* listen for `rel-change`; `changed` stays for as long as 1.x does.
|
|
2700
|
+
*
|
|
2701
|
+
* One `detail` object is shared by both dispatches so the two events cannot
|
|
2702
|
+
* drift apart — a listener on one sees exactly what a listener on the other
|
|
2703
|
+
* sees.
|
|
2704
|
+
*/
|
|
2705
|
+
private emitChange;
|
|
2706
|
+
private openListbox;
|
|
2707
|
+
private closeListbox;
|
|
2708
|
+
private showNativePopover;
|
|
2709
|
+
private hideNativePopover;
|
|
2710
|
+
private updatePosition;
|
|
2711
|
+
private selectSingleOption;
|
|
2712
|
+
private toggleMultiOption;
|
|
2713
|
+
private toggleSelectAll;
|
|
2714
|
+
private removeChip;
|
|
2715
|
+
/**
|
|
2716
|
+
* A chip's remove button fired `removed`. When that button had keyboard
|
|
2717
|
+
* focus, the chip is about to disappear and focus would drop to <body>, so
|
|
2718
|
+
* hand it to the next chip's remove button, else the previous one, else the
|
|
2719
|
+
* trigger.
|
|
2720
|
+
*/
|
|
2721
|
+
private onChipRemoved;
|
|
2722
|
+
private onTriggerClick;
|
|
2723
|
+
private onTriggerKeyDown;
|
|
2724
|
+
private onSearchInput;
|
|
2725
|
+
private onSearchKeyDown;
|
|
2726
|
+
private handleListNavigation;
|
|
2727
|
+
/** APG typeahead for the no-search mode (with a search field, typing
|
|
2728
|
+
* filters instead). Accumulates printable keys for 500 ms and jumps the
|
|
2729
|
+
* highlight to the next option whose label starts with the buffer. */
|
|
2730
|
+
private handleTypeahead;
|
|
2731
|
+
private activateHighlighted;
|
|
2732
|
+
private scrollHighlightedIntoView;
|
|
2733
|
+
private renderChips;
|
|
2734
|
+
/**
|
|
2735
|
+
* Hidden, unconstrained copy of every selected chip used purely for width
|
|
2736
|
+
* measurement (see computeVisibleChips). Chips mirror the visible ones'
|
|
2737
|
+
* width-affecting props (removable adds the ✕ icon). The trailing chip is
|
|
2738
|
+
* the widest "+N" badge that could ever be needed.
|
|
2739
|
+
*/
|
|
2740
|
+
private renderChipsMeasure;
|
|
2741
|
+
render(): lit_html.TemplateResult<1>;
|
|
2742
|
+
}
|
|
2743
|
+
declare global {
|
|
2744
|
+
interface HTMLElementTagNameMap {
|
|
2745
|
+
"rel-select": RelSelect;
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
|
|
2749
|
+
/** The layouts of Figma's Pagination "Type" axis. "Extended with Rows" is `extended` plus `show-rows-per-page`. */
|
|
2750
|
+
type PaginationType = "extended" | "compact" | "count-text" | "page-select";
|
|
2751
|
+
/**
|
|
2752
|
+
* Page navigation (Figma "Pagination"): prev/next ghost buttons with numbered pages, a compact "Page X of Y" readout, a "1–10 of 50" item-range readout, or a "Page [select] of Y" jump-to-page dropdown, optionally followed by a rows-per-page selector. Use it under tables and lists that load one page of results at a time; it never fetches data itself — listen for `rel-change` (and `rel-per-page-change`).
|
|
2753
|
+
* @csspart base - The `role="navigation"` root of the extended layout (page buttons plus the optional "Viewing page" label).
|
|
2754
|
+
* @csspart label - The `role="navigation"` root row of the count-text layout (item-range text plus prev/next nav).
|
|
2755
|
+
* @csspart page-select - The `rel-select` of the `page-select` layout (the jump-to-page dropdown). New in 1.5.0.
|
|
2756
|
+
* @csspart rows-per-page - The rows-per-page block (its text plus the `rel-select`), rendered with `show-rows-per-page`. New in 1.5.0.
|
|
2757
|
+
*/
|
|
2758
|
+
declare class RelPagination extends RelElement {
|
|
2759
|
+
/** Figma "Type": `extended` = prev/next + numbered page buttons (auto-collapses to compact under 480px container width), `compact` = prev/next + "Page X of Y", `count-text` = "start–end of total" item range + prev/next around the current page number, `page-select` = prev/next around "Page [select] of Y", a dropdown that jumps to any page (new in 1.5.0). Every type except `page-select` has no jump-to-page control. */
|
|
2760
|
+
type: PaginationType;
|
|
2761
|
+
/** Controlled current page (1-based). When set, the element only emits `rel-change` and waits for the parent to update `page`; leave unset for uncontrolled behaviour. */
|
|
2762
|
+
page?: number;
|
|
2763
|
+
/** Starting page for uncontrolled use (ignored when `page` is set). */
|
|
2764
|
+
defaultPage: number;
|
|
2765
|
+
/** Total number of pages. `0` (the default) lets `totalItems` / `perPage` compute the page count instead. */
|
|
2766
|
+
totalPages: number;
|
|
2767
|
+
/** Total item count; with `perPage` it computes the page count when `totalPages` is `0` and is the "of N" figure in the count-text readout. */
|
|
2768
|
+
totalItems: number;
|
|
2769
|
+
/** Items per page, used to compute the page count from `totalItems` and the "start–end" range in the count-text readout. */
|
|
2770
|
+
perPage: number;
|
|
2771
|
+
/** Shows a "Viewing page X of Y" caption under the extended layout (ignored by the other types). Off by default. */
|
|
2772
|
+
showLabel: boolean;
|
|
2773
|
+
/** Dims the whole control to 40% opacity, shows a `not-allowed` cursor and ignores every page change. */
|
|
2774
|
+
disabled: boolean;
|
|
2775
|
+
/** Reserved for link-mode pagination. Currently accepted but not rendered: every page control is a `<button>`, so navigate in your `rel-change` handler instead. */
|
|
2776
|
+
hrefTemplate: string;
|
|
2777
|
+
/** Accessible name of the `role="navigation"` landmark (attribute `ariaLabel`). Set it when a page contains more than one pagination control. */
|
|
2778
|
+
ariaLabel: string;
|
|
2779
|
+
/** New in 1.5.0. Adds a rows-per-page selector after the navigation, with any `type` (Figma "Extended with Rows" is `type="extended"` with this set). Choosing a value sets `perPage`, fires `rel-per-page-change` and returns to page 1. Off by default: no rows-per-page selector. */
|
|
2780
|
+
showRowsPerPage: boolean;
|
|
2781
|
+
/** New in 1.5.0. The values the rows-per-page selector offers (a number array, or a JSON array in the attribute). The current `perPage` is added to the list when it is not in it. */
|
|
2782
|
+
rowsPerPageOptions: number[];
|
|
2783
|
+
/** New in 1.5.0. Text before the rows-per-page selector, also its accessible name. */
|
|
2784
|
+
rowsPerPageLabel: string;
|
|
2785
|
+
private currentPage;
|
|
2786
|
+
static styles: lit.CSSResult;
|
|
2787
|
+
connectedCallback(): void;
|
|
2788
|
+
updated(changedProperties: Map<string, unknown>): void;
|
|
2789
|
+
private get activePage();
|
|
2790
|
+
private get computedTotalPages();
|
|
2791
|
+
private generatePageNumbers;
|
|
2792
|
+
/** Abbreviate large page numbers (368178 → "368k") so buttons stay compact.
|
|
2793
|
+
Exact below 10,000; floored to k up to 1M; then M with one decimal. */
|
|
2794
|
+
private formatPageLabel;
|
|
2795
|
+
private handlePageChange;
|
|
2796
|
+
private renderChevronLeft;
|
|
2797
|
+
private renderChevronRight;
|
|
2798
|
+
private renderNavBtn;
|
|
2799
|
+
private renderExtended;
|
|
2800
|
+
private renderCompact;
|
|
2801
|
+
private renderCountText;
|
|
2802
|
+
/** Pages offered by the page-select dropdown: every page, or for very long
|
|
2803
|
+
ranges a window around the current page plus the first and last. */
|
|
2804
|
+
private pageOptions;
|
|
2805
|
+
private stopInner;
|
|
2806
|
+
private onPageSelect;
|
|
2807
|
+
private onRowsPerPage;
|
|
2808
|
+
private renderPageSelect;
|
|
2809
|
+
private renderRowsPerPage;
|
|
2810
|
+
private renderLayout;
|
|
2811
|
+
render(): lit_html.TemplateResult<1>;
|
|
2812
|
+
}
|
|
2813
|
+
|
|
2814
|
+
type SideType = "top" | "right" | "bottom" | "left";
|
|
2815
|
+
type AlignType = "start" | "center" | "end";
|
|
2816
|
+
/**
|
|
2817
|
+
* Click-to-open floating panel anchored to a trigger (Figma "Popover"): the first child is the trigger, the `content` slot is the panel, which is promoted to the browser top layer and positioned in viewport coordinates.
|
|
2818
|
+
* @slot - The trigger: the first slotted element toggles the panel on pointer down / Enter / Space and receives `aria-haspopup` (from `has-popup`), `aria-expanded` and `aria-controls` (a bare `<div>` / `<span>` also gets `tabindex="0"` and `role="button"`).
|
|
2819
|
+
* @slot content - The panel body, usually a `<rel-popover-content>`; rendered inside the fixed, top-layer wrapper only while open.
|
|
2820
|
+
* @csspart arrow - The 14×14 chevron box rendered on the panel edge facing the trigger when `arrow` is set (absent otherwise).
|
|
2821
|
+
* @cssprop --rel-popover-arrow-bg - Fill of the `arrow` chevron (default `--rel-bg-neutral`, matching `<rel-popover-content>`).
|
|
2822
|
+
* @cssprop --rel-popover-arrow-border - **Deprecated.** Stroke of the `arrow` chevron's two slanted edges. The panel no longer draws a border — overlapping surfaces are separated by shadow — so this defaults to `transparent` and the chevron has no edge. Set it to restore a stroke.
|
|
2823
|
+
*/
|
|
2824
|
+
declare class RelPopover extends RelElement {
|
|
2825
|
+
/** Controlled open state. Leave unset for uncontrolled mode; once set (true or false) the component only emits `rel-open-change` and you must update `open` yourself. */
|
|
2826
|
+
open?: boolean;
|
|
2827
|
+
/** Initial state in uncontrolled mode (attribute `default-open`); ignored when `open` is set. */
|
|
2828
|
+
defaultOpen: boolean;
|
|
2829
|
+
/** Blocks trigger interaction and dims the host to 60% opacity; does not close an already-open panel. */
|
|
2830
|
+
disabled: boolean;
|
|
2831
|
+
/** Which side of the trigger the panel opens on: `top`, `right`, `bottom` (default) or `left`. The panel is clamped 8px inside the viewport but never flips to another side. */
|
|
2832
|
+
side: SideType;
|
|
2833
|
+
/** Alignment along the cross axis: `start` (left / top edge of the trigger), `center` (default) or `end` (right / bottom edge). */
|
|
2834
|
+
align: AlignType;
|
|
2835
|
+
/** Gap between trigger and panel in pixels (attribute `side-offset`, default 8). With `arrow` the effective gap is at least 13px. */
|
|
2836
|
+
sideOffset: number;
|
|
2837
|
+
/** Extra shift along the alignment axis in pixels (attribute `align-offset`, default 0); positive moves right / down. */
|
|
2838
|
+
alignOffset: number;
|
|
2839
|
+
/** Keep Tab / Shift+Tab cycling inside the panel while open (attribute `trap-focus`); use for forms. */
|
|
2840
|
+
trapFocus: boolean;
|
|
2841
|
+
/** Close on Escape (attribute `close-on-escape`, default true; switch off with `close-on-escape="false"` or `el.closeOnEscape = false`). */
|
|
2842
|
+
closeOnEscape: boolean;
|
|
2843
|
+
/** Close on a pointer-down outside the trigger and panel (attribute `close-on-outside-click`, default true; switch off with `close-on-outside-click="false"` or the property). Also lets another popover's opening dismiss this one. */
|
|
2844
|
+
closeOnOutsideClick: boolean;
|
|
2845
|
+
/**
|
|
2846
|
+
* Opt-in pointer (audit 23a): a 14×11 triangle on the panel edge that faces
|
|
2847
|
+
* the trigger — the Figma Popover "Chevron" — following `side` and tracking
|
|
2848
|
+
* the trigger's centre along the cross axis (clamped inside the panel).
|
|
2849
|
+
* It is drawn with the panel's tokens (`--rel-popover-arrow-bg` /
|
|
2850
|
+
* `--rel-popover-arrow-border`, defaulting to rel-popover-content's
|
|
2851
|
+
* background and border). With the arrow on, the panel keeps at least the
|
|
2852
|
+
* arrow's height plus 2px away from the trigger so the tip never overlaps
|
|
2853
|
+
* it; larger `sideOffset` values still apply. Default off — existing
|
|
2854
|
+
* popovers render exactly as before.
|
|
2855
|
+
*/
|
|
2856
|
+
arrow: boolean;
|
|
2857
|
+
/** New in 1.5.0. Value written to the trigger's `aria-haspopup` (attribute `has-popup`): `dialog` (default) for a panel of content, or `menu`, `listbox`, `tree`, `grid` or `true` when the panel holds that widget. A panel holding a `rel-menu` takes `menu`. */
|
|
2858
|
+
hasPopup: "dialog" | "menu" | "listbox" | "tree" | "grid" | "true";
|
|
2859
|
+
/** Figma Popover (6338:563) chevron: 14 wide × 11 tall. */
|
|
2860
|
+
private static readonly ARROW_WIDTH;
|
|
2861
|
+
private static readonly ARROW_HEIGHT;
|
|
2862
|
+
private internalOpen;
|
|
2863
|
+
private contentStyle;
|
|
2864
|
+
private contentWrapper;
|
|
2865
|
+
private contentSlot?;
|
|
2866
|
+
private triggerEl;
|
|
2867
|
+
private wasOpen;
|
|
2868
|
+
/** The last interaction with this popover (trigger, panel or an outside
|
|
2869
|
+
* dismiss) was a pointer press, not a key. Decides whether the focus moves
|
|
2870
|
+
* on open and close may draw a focus ring (see focusOptions). */
|
|
2871
|
+
private pointerInteraction;
|
|
2872
|
+
private uniqueId;
|
|
2873
|
+
static styles: lit.CSSResult;
|
|
2874
|
+
connectedCallback(): void;
|
|
2875
|
+
disconnectedCallback(): void;
|
|
2876
|
+
firstUpdated(): void;
|
|
2877
|
+
updated(changed: Map<string, unknown>): void;
|
|
2878
|
+
private isControlled;
|
|
2879
|
+
private get activeOpen();
|
|
2880
|
+
private setOpen;
|
|
2881
|
+
private onHostPointerDown;
|
|
2882
|
+
private onHostKeyDown;
|
|
2883
|
+
private onOpen;
|
|
2884
|
+
private onClose;
|
|
2885
|
+
/**
|
|
2886
|
+
* Light-dismiss every other open popover that isn't an ancestor of this
|
|
2887
|
+
* one (nested popovers keep their parent open). This is what the outside-
|
|
2888
|
+
* pointerdown listener would do for a click on our trigger — except the
|
|
2889
|
+
* trigger handler stops that pointerdown in the capture phase, and a
|
|
2890
|
+
* keyboard (Enter/Space) or programmatic open never produces one at all.
|
|
2891
|
+
* Honors each popover's own `closeOnOutsideClick` setting.
|
|
2892
|
+
*/
|
|
2893
|
+
private closeOtherPopovers;
|
|
2894
|
+
private showNativePopover;
|
|
2895
|
+
private hideNativePopover;
|
|
2896
|
+
private addGlobalListeners;
|
|
2897
|
+
private removeGlobalListeners;
|
|
2898
|
+
private onOutsidePointerDown;
|
|
2899
|
+
private onKeyDown;
|
|
2900
|
+
/** The panel content is SLOTTED light DOM, often nested inside other
|
|
2901
|
+
* components' shadow roots (a rel-button in rel-popover-content), so the
|
|
2902
|
+
* search walks the composed tree — a querySelectorAll on the wrapper never
|
|
2903
|
+
* saw it, and focus never entered the panel. With nothing focusable, the
|
|
2904
|
+
* panel itself takes focus so it is announced: a rel-popover-content
|
|
2905
|
+
* focuses its named role="dialog" box; any other element falls back to the
|
|
2906
|
+
* wrapper (tabindex="-1"). */
|
|
2907
|
+
private focusFirst;
|
|
2908
|
+
/** After a pointer press the trigger never takes focus (onHostPointerDown
|
|
2909
|
+
* prevents it), so Chromium counts our scripted focus as :focus-visible and
|
|
2910
|
+
* a mouse open drew a focus ring in the panel (and on the trigger after a
|
|
2911
|
+
* mouse close). `focusVisible: false` keeps those moves ring-free; a key
|
|
2912
|
+
* press inside the panel still shows the focused control's own ring (a
|
|
2913
|
+
* rel-menu row: its data-keyboard rule). Keyboard and scripted opens pass
|
|
2914
|
+
* nothing, so the browser decides as before. A browser that doesn't know
|
|
2915
|
+
* the `focusVisible` option ignores the unknown dictionary member and
|
|
2916
|
+
* behaves exactly as before this change. */
|
|
2917
|
+
private focusOptions;
|
|
2918
|
+
/** Focus returns to the trigger's own control (APG: back to the invoking
|
|
2919
|
+
* element) — a rel-button host is not focusable, its inner <button> is.
|
|
2920
|
+
* Only when focus is in the popover or was dropped to <body> (the panel
|
|
2921
|
+
* hiding blurs it): a close caused by focus moving elsewhere, or a
|
|
2922
|
+
* programmatic close, must not pull focus away from where the user is. */
|
|
2923
|
+
private restoreFocus;
|
|
2924
|
+
private triggerControl;
|
|
2925
|
+
/** Whether the deep active element is inside the panel (the wrapper or the
|
|
2926
|
+
* slotted content) or anywhere in the popover (the trigger included),
|
|
2927
|
+
* walking the composed tree. */
|
|
2928
|
+
private focusIn;
|
|
2929
|
+
private trapFocusLoop;
|
|
2930
|
+
private updatePosition;
|
|
2931
|
+
private onTriggerSlotChange;
|
|
2932
|
+
private applyTriggerAria;
|
|
2933
|
+
render(): lit_html.TemplateResult<1>;
|
|
2934
|
+
}
|
|
2935
|
+
declare global {
|
|
2936
|
+
interface HTMLElementTagNameMap {
|
|
2937
|
+
"rel-popover": RelPopover;
|
|
2938
|
+
}
|
|
2939
|
+
}
|
|
2940
|
+
|
|
2941
|
+
/** Figma Size axis, spelled out. */
|
|
2942
|
+
type PopoverContentSize = "small" | "medium" | "large";
|
|
2943
|
+
/** Alternative spellings, not deprecations — the short names keep working. */
|
|
2944
|
+
type PopoverContentSizeAlias = "sm" | "md" | "lg";
|
|
2945
|
+
type PopoverContentSizeInput = PopoverContentSize | PopoverContentSizeAlias;
|
|
2946
|
+
/**
|
|
2947
|
+
* Styled panel body for `<rel-popover>` (Figma "Popover" surface): neutral background, no border, 8px radius, shadow/lg, max-width 400px, with heading / paragraph typography for slotted content. Place it in the popover's `content` slot; any other element works there too.
|
|
2948
|
+
* @slot - The panel content (headings, paragraphs, form controls, buttons).
|
|
2949
|
+
* @csspart content - The padded `role="dialog"` box that carries the surface, shadow and size padding.
|
|
2950
|
+
*/
|
|
2951
|
+
declare class RelPopoverContent extends RelElement {
|
|
2952
|
+
/** Accessible name applied to the inner `role="dialog"` box (attribute `aria-label`); describe what the panel is for. */
|
|
2953
|
+
ariaLabel: string;
|
|
2954
|
+
/** Figma Size axis: panel padding 12px (`small`), 16px (`medium`, default) or 20px (`large`). `sm` / `md` / `lg` are alternative spellings and stay supported — they are normalised to the full words, not deprecated. */
|
|
2955
|
+
size: PopoverContentSizeInput;
|
|
2956
|
+
/** Alternative spellings, NOT deprecations — no console notice. Normalising
|
|
2957
|
+
* keeps the reflected attribute canonical, so the :host([size=…]) rules only
|
|
2958
|
+
* need the full words. */
|
|
2959
|
+
protected willUpdate(changed: Map<string, unknown>): void;
|
|
2960
|
+
static styles: lit.CSSResult;
|
|
2961
|
+
/** Focuses the `role="dialog"` box rather than the host (which is not
|
|
2962
|
+
* focusable). rel-popover lands focus here when the panel has nothing
|
|
2963
|
+
* focusable, so a screen reader announces the dialog by its `aria-label`. */
|
|
2964
|
+
focus(options?: FocusOptions): void;
|
|
2965
|
+
render(): lit_html.TemplateResult<1>;
|
|
2966
|
+
}
|
|
2967
|
+
|
|
2968
|
+
type ProgressMode = "linear-determinate" | "linear-indeterminate" | "circular-determinate" | "circular-indeterminate";
|
|
2969
|
+
/**
|
|
2970
|
+
* Progress indicator (Figma "Progress"): a linear bar or a circular ring, each either value-driven (determinate) or looping (indeterminate).
|
|
2971
|
+
* @csspart track - The linear track `<div>` that carries `role="progressbar"` (linear modes only)
|
|
2972
|
+
* @csspart indicator - The filled / sliding bar inside the linear track (linear modes only)
|
|
2973
|
+
*/
|
|
2974
|
+
declare class RelProgress extends RelElement {
|
|
2975
|
+
/** Shape and behaviour: `linear-*` is a full-width 2px bar, `circular-*` a 36px ring; `*-determinate` fills to `value`, `*-indeterminate` loops an animation and ignores `value`. */
|
|
2976
|
+
mode: ProgressMode;
|
|
2977
|
+
/** Completion percentage 0–100 for the determinate modes; out-of-range values are clamped before rendering and before `aria-valuenow`. */
|
|
2978
|
+
value: number;
|
|
2979
|
+
/** Accessible name of the progressbar (not rendered visually); defaults to "Progress" for determinate and "Loading" for indeterminate modes. */
|
|
2980
|
+
label: string;
|
|
2981
|
+
private radius;
|
|
2982
|
+
private circumference;
|
|
2983
|
+
static styles: lit.CSSResult;
|
|
2984
|
+
private get safeValue();
|
|
2985
|
+
private get accessibleName();
|
|
2986
|
+
private renderLinearDeterminate;
|
|
2987
|
+
private renderLinearIndeterminate;
|
|
2988
|
+
private renderCircularDeterminate;
|
|
2989
|
+
private renderCircularIndeterminate;
|
|
2990
|
+
render(): lit_html.TemplateResult<1>;
|
|
2991
|
+
}
|
|
2992
|
+
|
|
2993
|
+
/**
|
|
2994
|
+
* Flex container that lays out direct-child `<rel-resizable-panel>`s along one axis and lets the user drag or keyboard-nudge the `<rel-resizable-handle>` between two neighbours to trade percentage width/height between them.
|
|
2995
|
+
* @slot - The panels and handles, as direct children in display order (panel, handle, panel, …)
|
|
2996
|
+
* @fires rel-resize - Fired continuously while a handle is dragged. Detail: `{ direction, sizes: number[] }` with one percentage per panel.
|
|
2997
|
+
* @fires rel-resize-end - Fired once when a drag ends (pointerup) and after every keyboard resize step. Detail: `{ direction, sizes: number[] }` with one percentage per panel.
|
|
2998
|
+
*/
|
|
2999
|
+
declare class RelResizableGroup extends RelElement {
|
|
3000
|
+
/** Layout axis: `horizontal` places panels side by side and resizes widths, `vertical` stacks them and resizes heights; also pushed to every child handle's `orientation`. */
|
|
3001
|
+
direction: "horizontal" | "vertical";
|
|
3002
|
+
private panels;
|
|
3003
|
+
private handles;
|
|
3004
|
+
private isDragging;
|
|
3005
|
+
private activeHandleIndex;
|
|
3006
|
+
private startPointerPos;
|
|
3007
|
+
private startSizes;
|
|
3008
|
+
static styles: lit.CSSResult;
|
|
3009
|
+
connectedCallback(): void;
|
|
3010
|
+
disconnectedCallback(): void;
|
|
3011
|
+
firstUpdated(): void;
|
|
3012
|
+
private initializeLayout;
|
|
3013
|
+
private calculateInitialSizes;
|
|
3014
|
+
private onPointerDown;
|
|
3015
|
+
private startDrag;
|
|
3016
|
+
private onPointerMove;
|
|
3017
|
+
private onPointerUp;
|
|
3018
|
+
private applyDragResize;
|
|
3019
|
+
private onKeyDown;
|
|
3020
|
+
private applyKeyboardResize;
|
|
3021
|
+
private applySizes;
|
|
3022
|
+
private dispatchResizeEvent;
|
|
3023
|
+
private addGlobalListeners;
|
|
3024
|
+
private removeGlobalListeners;
|
|
2633
3025
|
render(): lit_html.TemplateResult<1>;
|
|
2634
3026
|
}
|
|
2635
3027
|
declare global {
|
|
2636
3028
|
interface HTMLElementTagNameMap {
|
|
2637
|
-
"rel-
|
|
3029
|
+
"rel-resizable-group": RelResizableGroup;
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
|
|
3033
|
+
/**
|
|
3034
|
+
* One resizable region inside a `<rel-resizable-group>`: a padded, scrollable (`overflow: auto`) flex column whose size along the group axis is a percentage managed by the group. While its content overflows, the panel becomes a keyboard-focusable named region so it can be scrolled without a mouse.
|
|
3035
|
+
* @slot - The panel's content; slotted `h1`–`h4` get the headings-md role
|
|
3036
|
+
*/
|
|
3037
|
+
declare class RelResizablePanel extends RelElement {
|
|
3038
|
+
/** Initial size as a percentage of the group; panels without one share whatever is left of 100%, then all sizes are normalised to sum to 100. */
|
|
3039
|
+
defaultSize?: number;
|
|
3040
|
+
/** Smallest size (percentage) the panel can be resized to. */
|
|
3041
|
+
minSize: number;
|
|
3042
|
+
/** Largest size (percentage) the panel can be resized to. */
|
|
3043
|
+
maxSize: number;
|
|
3044
|
+
/** New in 1.5.0. Accessible name the panel carries while its content overflows (it is then a focusable `role="region"`). Defaults to "Panel N", N being its position among the group's panels. Ignored when the page sets its own `aria-label` / `aria-labelledby`. */
|
|
3045
|
+
panelLabel?: string;
|
|
3046
|
+
/** Current size as a percentage of the group (also written to the host's `flex-basis`); read-only — the parent group updates it on every resize. */
|
|
3047
|
+
currentSize: number;
|
|
3048
|
+
/** True while the content overflows the panel in either axis; read-only, kept current by a ResizeObserver. */
|
|
3049
|
+
get scrollable(): boolean;
|
|
3050
|
+
private overflowing;
|
|
3051
|
+
private resizeObserver?;
|
|
3052
|
+
private mutationObserver?;
|
|
3053
|
+
private observedChildren;
|
|
3054
|
+
private frame;
|
|
3055
|
+
/** The page set `tabindex` itself: never touch it, nor role / name. */
|
|
3056
|
+
private pageOwnsTabindex;
|
|
3057
|
+
/** The tabindex value this panel last wrote, or null when it wrote none. */
|
|
3058
|
+
private writtenTabindex;
|
|
3059
|
+
private ownsRole;
|
|
3060
|
+
private ownsLabel;
|
|
3061
|
+
static styles: lit.CSSResult;
|
|
3062
|
+
connectedCallback(): void;
|
|
3063
|
+
disconnectedCallback(): void;
|
|
3064
|
+
protected updated(changed: PropertyValues<this>): void;
|
|
3065
|
+
private onSlotChange;
|
|
3066
|
+
private onFocusOut;
|
|
3067
|
+
/** Measures one frame after the change: no layout in the observer callback, no ResizeObserver loop errors. */
|
|
3068
|
+
private scheduleMeasure;
|
|
3069
|
+
private defaultLabel;
|
|
3070
|
+
private applyScrollable;
|
|
3071
|
+
render(): lit_html.TemplateResult<1>;
|
|
3072
|
+
}
|
|
3073
|
+
declare global {
|
|
3074
|
+
interface HTMLElementTagNameMap {
|
|
3075
|
+
"rel-resizable-panel": RelResizablePanel;
|
|
3076
|
+
}
|
|
3077
|
+
}
|
|
3078
|
+
|
|
3079
|
+
/**
|
|
3080
|
+
* Focusable `role="separator"` splitter placed between two `<rel-resizable-panel>`s inside a `<rel-resizable-group>`; the group owns the drag and keyboard logic, the handle only renders the grab bar and exposes the split via ARIA.
|
|
3081
|
+
*/
|
|
3082
|
+
declare class RelResizableHandle extends RelElement {
|
|
3083
|
+
/** Axis the handle separates: `horizontal` = 8px-wide vertical bar with `col-resize` cursor, `vertical` = 8px-tall bar with `row-resize`; set automatically from the parent group's `direction` on first render and mirrored to `aria-orientation`. */
|
|
3084
|
+
orientation: "horizontal" | "vertical";
|
|
3085
|
+
/** @internal Index of this handle in the parent group; assigned by the group on first render. */
|
|
3086
|
+
handleIndex: number;
|
|
3087
|
+
/** Current split of the two neighbouring panels as a percentage 0–100 (share held by the leading panel); read-only — the parent group updates it and mirrors it to `aria-valuenow`. */
|
|
3088
|
+
splitValue: number;
|
|
3089
|
+
static styles: lit.CSSResult;
|
|
3090
|
+
connectedCallback(): void;
|
|
3091
|
+
updated(changed: Map<string, unknown>): void;
|
|
3092
|
+
private updateAriaOrientation;
|
|
3093
|
+
/** @internal Called by the parent group after every resize to store `splitValue` and write `aria-valuenow` / `aria-valuemin` / `aria-valuemax`. */
|
|
3094
|
+
updateAriaValue(value: number): void;
|
|
3095
|
+
render(): lit_html.TemplateResult<1>;
|
|
3096
|
+
}
|
|
3097
|
+
declare global {
|
|
3098
|
+
interface HTMLElementTagNameMap {
|
|
3099
|
+
"rel-resizable-handle": RelResizableHandle;
|
|
2638
3100
|
}
|
|
2639
3101
|
}
|
|
2640
3102
|
|
|
3103
|
+
type SegmentSize = "small" | "medium" | "large";
|
|
3104
|
+
type SegmentAlign = "left" | "middle" | "right";
|
|
3105
|
+
interface SegmentOption {
|
|
3106
|
+
label: string;
|
|
3107
|
+
value: string;
|
|
3108
|
+
disabled?: boolean;
|
|
3109
|
+
/** `rel-icon` name rendered before the label (Figma "Left Icon"), sized 16 / 18 / 20 with the control. */
|
|
3110
|
+
icon?: string;
|
|
3111
|
+
/**
|
|
3112
|
+
* Trailing badge (Figma "Show Badge" / "Badge"), rendered after the label
|
|
3113
|
+
* inside the segment's own 8px gap. A number or string shows the count at
|
|
3114
|
+
* `medium` and `large`; at `small` Figma switches to the 6px dot, so the
|
|
3115
|
+
* value is not displayed there. Use `true` for a dot at any size.
|
|
3116
|
+
*/
|
|
3117
|
+
badge?: number | string | boolean;
|
|
3118
|
+
}
|
|
3119
|
+
/**
|
|
3120
|
+
* Single-select segmented button group: renders one `<button role="radio">` per entry in `options` on a 2px-inset track (`role="radiogroup"`), with exactly one segment active at a time.
|
|
3121
|
+
* @csspart base - The `role="radiogroup"` track that lays out the segments.
|
|
3122
|
+
* @csspart option - Each segment's native `<button role="radio">`; the active one carries the `active` class and `aria-checked="true"`.
|
|
3123
|
+
* @csspart icon - A segment's optional leading `rel-icon` element.
|
|
3124
|
+
* @csspart badge - A segment's optional trailing `rel-badge`; rendered only when the option sets `badge`.
|
|
3125
|
+
* @csspart label - The wrapper around a segment's label text.
|
|
3126
|
+
*/
|
|
3127
|
+
declare class RelSegmentedButton extends RelElement {
|
|
3128
|
+
/** The segments in order, each `{ label: string; value: string; disabled?: boolean; icon?: string; badge?: number | string | boolean }`. Set as a property (or a JSON array attribute); a disabled entry is rendered but cannot be selected, and `icon` names a `rel-icon` drawn before the label. */
|
|
3129
|
+
options: SegmentOption[];
|
|
3130
|
+
/** `value` of the currently selected segment. Updated by the component on click / arrow keys; set it to pre-select a segment (an unknown value selects nothing). */
|
|
3131
|
+
active: string;
|
|
3132
|
+
/** Disables the whole group (click and keyboard) without changing individual `options[].disabled` settings. Angular `control.disable()` uses it. New in 1.5.0. */
|
|
3133
|
+
disabled: boolean;
|
|
3134
|
+
/** Control height, matching the TextField ramp: `small` (32px — 28px segments, `action-md` 12px text, 16px icons), `medium` (default, 40px — 36px segments, `action-lg` 14px text, 18px icons) or `large` (48px — 44px segments, `action-xl` 16px text, 20px icons). */
|
|
3135
|
+
size: SegmentSize;
|
|
3136
|
+
/** `justify-content` of the group's inline-flex container: `left` (default), `middle` or `right`. Only visible when the host is made wider than its content. */
|
|
3137
|
+
align: SegmentAlign;
|
|
3138
|
+
/** Accessible name for the radiogroup (it renders no visible group label). */
|
|
3139
|
+
fieldAriaLabel?: string;
|
|
3140
|
+
static styles: lit.CSSResult;
|
|
3141
|
+
private setActive;
|
|
3142
|
+
/** APG radio-group navigation: arrows move focus AND select, the group is
|
|
3143
|
+
* one Tab stop (roving tabindex on the selected segment). */
|
|
3144
|
+
private onKeyDown;
|
|
3145
|
+
private renderSegment;
|
|
3146
|
+
/**
|
|
3147
|
+
* Figma's Show Badge axis: a 20x20 numeric badge at medium and large, and a
|
|
3148
|
+
* 6px dot at small — where the count is not shown at all, so a numeric value
|
|
3149
|
+
* degrades to a dot rather than being squeezed in. `badge: true` asks for the
|
|
3150
|
+
* dot at any size.
|
|
3151
|
+
*/
|
|
3152
|
+
private renderBadge;
|
|
3153
|
+
render(): lit_html.TemplateResult<1>;
|
|
3154
|
+
}
|
|
3155
|
+
|
|
2641
3156
|
type SkeletonShape = "line" | "circle" | "block";
|
|
2642
3157
|
type SkeletonAnimation = "pulse" | "shimmer" | "none";
|
|
2643
3158
|
/**
|
|
@@ -2647,7 +3162,7 @@ type SkeletonAnimation = "pulse" | "shimmer" | "none";
|
|
|
2647
3162
|
* @cssprop --rel-skeleton-line-height - Height of each text bar when `shape="line"`; default 16px (Figma's Line shape).
|
|
2648
3163
|
* @cssprop --rel-skeleton-highlight - Lighter band that sweeps across the placeholder when `animation="shimmer"` (defaults to the elevated-2 neutral background token).
|
|
2649
3164
|
*/
|
|
2650
|
-
declare class RelSkeleton extends
|
|
3165
|
+
declare class RelSkeleton extends RelElement {
|
|
2651
3166
|
/** Placeholder shape: `block` fills the host (min 16px tall), `circle` is a square-aspect disc sized by the host width, `line` renders `lines` 16px text bars with the last one at 65% width. */
|
|
2652
3167
|
shape: SkeletonShape;
|
|
2653
3168
|
/** Number of text bars when `shape="line"` (minimum 1, --rel-spacing-xs apart); ignored by the other shapes. */
|
|
@@ -2702,7 +3217,7 @@ type ModalVariant = "default" | "text";
|
|
|
2702
3217
|
* @cssprop --rel-modal-transition-duration - Open/close animation duration; default `0.3s`
|
|
2703
3218
|
* @cssprop --rel-modal-transition-timing - Open/close animation easing; default `cubic-bezier(0.32, 0.72, 0, 1)`
|
|
2704
3219
|
*/
|
|
2705
|
-
declare class RelModal extends
|
|
3220
|
+
declare class RelModal extends RelElement {
|
|
2706
3221
|
/** Whether the modal is shown. Toggle it to open/close; every change fires `rel-open-change`. */
|
|
2707
3222
|
open: boolean;
|
|
2708
3223
|
/** Where the panel is anchored: `bottom` (48px above the bottom edge, slides up), `top` (48px below the top edge, slides down) or `center` (fades and scales in). Below 480px with `breakpoint="responsive"` every side collapses to a full-width bottom sheet. */
|
|
@@ -2749,20 +3264,29 @@ declare class RelModal extends LitElement {
|
|
|
2749
3264
|
private overlayElement;
|
|
2750
3265
|
private panelElement;
|
|
2751
3266
|
private previousFocus;
|
|
2752
|
-
private originalBodyOverflow;
|
|
2753
|
-
private originalBodyPaddingRight;
|
|
2754
3267
|
static styles: lit.CSSResult;
|
|
2755
3268
|
connectedCallback(): void;
|
|
3269
|
+
firstUpdated(): void;
|
|
2756
3270
|
/**
|
|
2757
3271
|
* The footer divider is conditional: the designer confirmed that short
|
|
2758
3272
|
* content (a confirmation message) has no divider, but a body that scrolls
|
|
2759
3273
|
* does — it is a scroll affordance, not decoration. There is no CSS way to
|
|
2760
3274
|
* ask "does this element scroll", so it is measured and reflected onto the
|
|
2761
|
-
* host as `body-scrolls
|
|
2762
|
-
*
|
|
3275
|
+
* host as `body-scrolls`.
|
|
3276
|
+
*
|
|
3277
|
+
* What is observed matters. Once the panel reaches its max height (or is
|
|
3278
|
+
* fullscreen, where it is always fixed) `.content` stops resizing as its
|
|
3279
|
+
* content grows, and its only shadow child is the slot, which has no box.
|
|
3280
|
+
* So the observer also watches every element assigned to the default slot
|
|
3281
|
+
* (re-collected on slotchange): content added later, a child growing in
|
|
3282
|
+
* place, an image loading, all resize one of those. Window resizes reach
|
|
3283
|
+
* `.content` itself.
|
|
2763
3284
|
*/
|
|
2764
3285
|
private bodyScrollObserver?;
|
|
2765
|
-
private
|
|
3286
|
+
private bodyMeasureQueued;
|
|
3287
|
+
private measureBodyScroll;
|
|
3288
|
+
private queueBodyMeasure;
|
|
3289
|
+
private observeBody;
|
|
2766
3290
|
disconnectedCallback(): void;
|
|
2767
3291
|
protected willUpdate(changed: Map<string, unknown>): void;
|
|
2768
3292
|
updated(changed: Map<string, unknown>): void;
|
|
@@ -2781,6 +3305,206 @@ declare global {
|
|
|
2781
3305
|
}
|
|
2782
3306
|
}
|
|
2783
3307
|
|
|
3308
|
+
/** One point of a stroke: `x` and `y` in CSS pixels of the pad (see `strokes`), `t` in epoch milliseconds, and the pointer's `pressure` (0–1; 0.5 for a pressed mouse). */
|
|
3309
|
+
type SignaturePoint = [x: number, y: number, t: number, pressure: number];
|
|
3310
|
+
/** One pen-down to pen-up stroke of a `rel-signature-pad`. */
|
|
3311
|
+
interface SignatureStroke {
|
|
3312
|
+
points: SignaturePoint[];
|
|
3313
|
+
/** The `PointerEvent.pointerType` that drew it. Only `"pen"` strokes vary their width with pressure. */
|
|
3314
|
+
pointerType?: string;
|
|
3315
|
+
}
|
|
3316
|
+
/** How the signature is given: drawn with a pointer, or typed as a name. */
|
|
3317
|
+
type SignaturePadMode = "draw" | "type";
|
|
3318
|
+
/** Detail of the `rel-change` event of `rel-signature-pad`. */
|
|
3319
|
+
interface SignaturePadChangeDetail {
|
|
3320
|
+
value: string;
|
|
3321
|
+
strokes: SignatureStroke[];
|
|
3322
|
+
signedAt: string;
|
|
3323
|
+
mode: SignaturePadMode;
|
|
3324
|
+
}
|
|
3325
|
+
/**
|
|
3326
|
+
* Signature capture field. The user signs with a mouse, pen or finger on a 160px pad that fills its container's width; the field has a label, helper text, error and disabled states like `rel-textfield`, and Undo and Clear buttons in its helper row. Undo removes the last stroke and also reverses Clear. `value` is the signature as a trimmed PNG data URL; `strokes` holds the vector record and `toSVG()` exports it. A "Type your name instead" link switches to type mode, where the user types their name and it renders as the signature in Poppins italic: the keyboard alternative to drawing (WCAG 2.2 SC 2.5.7).
|
|
3327
|
+
*
|
|
3328
|
+
* New in 1.5.0.
|
|
3329
|
+
* @csspart label - The label above the pad.
|
|
3330
|
+
* @csspart mode-toggle - The link-style `rel-button` beside the label that switches between drawing ("Type your name instead") and typing ("Draw instead"). Hidden while `readonly`.
|
|
3331
|
+
* @csspart pad - The bordered drawing area. In draw mode it is a focusable `role="img"` named by the label and the signature's state; in type mode it holds the name input.
|
|
3332
|
+
* @csspart canvas - The `<canvas>` the ink is drawn on.
|
|
3333
|
+
* @csspart typed-input - The text input of type mode, drawn on the baseline in Poppins italic.
|
|
3334
|
+
* @csspart placeholder - The "Sign here" text ("Type your full name" in type mode), shown while the pad is empty.
|
|
3335
|
+
* @csspart baseline - The line near the bottom of the pad.
|
|
3336
|
+
* @csspart helper - The helper, error or "Signed …" text below the pad.
|
|
3337
|
+
* @csspart actions - The row that holds the Undo and Clear buttons.
|
|
3338
|
+
* @csspart undo - The Undo `rel-button` (ghost, small).
|
|
3339
|
+
* @csspart clear - The Clear `rel-button` (secondary, small).
|
|
3340
|
+
* @cssprop --rel-signature-pad-height - Height of the pad, border included (default 160px).
|
|
3341
|
+
* @fires rel-begin - The user put the pointer down to start a stroke. Detail: `{}`.
|
|
3342
|
+
* @fires rel-end - The user finished a stroke. Detail: `{}`.
|
|
3343
|
+
* @fires rel-change - The signature changed through the user: a finished stroke, Undo, Clear, a committed typed name (on blur or Enter) or a switch of mode. Detail: `{ value, strokes, signedAt, mode }`. Not fired for property changes or the `undo()` / `clear()` methods.
|
|
3344
|
+
*/
|
|
3345
|
+
declare class RelSignaturePad extends RelElement {
|
|
3346
|
+
static styles: lit.CSSResult;
|
|
3347
|
+
/** Visible label above the pad. A `required` asterisk is appended. */
|
|
3348
|
+
label?: string;
|
|
3349
|
+
/** Marks the signature as required: the label gets an asterisk. */
|
|
3350
|
+
required: boolean;
|
|
3351
|
+
/** Helper line below the pad. Defaults to "Use a mouse, pen or finger to sign"; once signed, the line shows "Signed {date and time}" instead. */
|
|
3352
|
+
helperText?: string;
|
|
3353
|
+
/** Text in the helper line while disabled (default "Signing is unavailable"). */
|
|
3354
|
+
disabledText?: string;
|
|
3355
|
+
/** Puts the field in the error state: danger border, and `error-message` replacing the helper text. */
|
|
3356
|
+
error: boolean;
|
|
3357
|
+
/** Text shown below the pad, with an alert icon, instead of the helper text while `error` is set. */
|
|
3358
|
+
errorMessage?: string;
|
|
3359
|
+
/** Disables the field: no drawing, Undo and Clear disabled, the pad leaves the Tab order, and the helper line shows `disabled-text`. */
|
|
3360
|
+
disabled: boolean;
|
|
3361
|
+
/** Shows the signature and its timestamp without letting it change: a subtle border, no Undo or Clear buttons, no drawing. */
|
|
3362
|
+
readonly: boolean;
|
|
3363
|
+
/** Text in the empty pad (default "Sign here"). It hides on the first ink; the baseline stays. */
|
|
3364
|
+
placeholder: string;
|
|
3365
|
+
/** Name of the field in a form. */
|
|
3366
|
+
name?: string;
|
|
3367
|
+
/** Accessible name of the pad when there is no visible `label`. */
|
|
3368
|
+
fieldAriaLabel?: string;
|
|
3369
|
+
/**
|
|
3370
|
+
* The signature as a PNG data URL, trimmed to the ink at 2×, with black ink on a transparent background in every theme; `""` when empty. Set it to show a stored signature: it is drawn in the theme's ink colour and replaces the strokes, so Undo cannot take it apart stroke by stroke (Clear removes it, and Undo brings it back). Setting `""` empties the pad.
|
|
3371
|
+
*/
|
|
3372
|
+
value: string;
|
|
3373
|
+
/**
|
|
3374
|
+
* The vector record of the signature, one entry per stroke: `{ points: [x, y, t, pressure][], pointerType? }`. Coordinates are CSS pixels of the pad when the first stroke was drawn (a narrower pad later shows the signature scaled down to fit, and the coordinates do not change); `t` is epoch milliseconds. Set it to redraw a stored signature that can be added to; that starts a new Undo history.
|
|
3375
|
+
*/
|
|
3376
|
+
strokes: SignatureStroke[];
|
|
3377
|
+
/** `draw` (default) captures the signature with a pointer; `type` takes a typed name and renders it in Poppins italic. The user switches with the link beside the label. Each mode keeps its own content; only the active mode makes the `value`. */
|
|
3378
|
+
mode: SignaturePadMode;
|
|
3379
|
+
/** The name typed in type mode. The `value` in type mode is this name rendered as a PNG, black, in Poppins italic. */
|
|
3380
|
+
typedName: string;
|
|
3381
|
+
private signedAtIso;
|
|
3382
|
+
private typedAtIso;
|
|
3383
|
+
private typedHistory;
|
|
3384
|
+
private drawing;
|
|
3385
|
+
private history;
|
|
3386
|
+
private stored;
|
|
3387
|
+
private padEl?;
|
|
3388
|
+
private canvas?;
|
|
3389
|
+
private typedInput?;
|
|
3390
|
+
private readonly uid;
|
|
3391
|
+
/** The strokes and value this component last set itself; anything else was assigned from outside. */
|
|
3392
|
+
private ownStrokes;
|
|
3393
|
+
private ownValue;
|
|
3394
|
+
private ownTypedName;
|
|
3395
|
+
/** Size of the pad when the current signature began: the space `strokes` coordinates live in. */
|
|
3396
|
+
private ref?;
|
|
3397
|
+
/** Current CSS size of the canvas and its backing-store size in device pixels. */
|
|
3398
|
+
private size?;
|
|
3399
|
+
private pixels?;
|
|
3400
|
+
private current;
|
|
3401
|
+
private activePointer;
|
|
3402
|
+
private frame;
|
|
3403
|
+
private resizeObserver?;
|
|
3404
|
+
private themeObserver?;
|
|
3405
|
+
private mediaQueries;
|
|
3406
|
+
/** The stored signature recoloured to one ink colour, cached across frames. */
|
|
3407
|
+
private tint?;
|
|
3408
|
+
static formAssociated: boolean;
|
|
3409
|
+
private readonly internals;
|
|
3410
|
+
/** An outer `<label>` names the pad and focuses it; a `<fieldset disabled>` disables it. */
|
|
3411
|
+
private readonly outerLabel;
|
|
3412
|
+
/** `disabled`, or an ancestor `<fieldset disabled>`. */
|
|
3413
|
+
private get isDisabled();
|
|
3414
|
+
/** @internal Form-associated lifecycle: an ancestor `<fieldset disabled>` disables the pad too. */
|
|
3415
|
+
formDisabledCallback(): void;
|
|
3416
|
+
/** @internal Form-associated lifecycle: a form reset empties both modes and their Undo history, without `rel-change`. */
|
|
3417
|
+
formResetCallback(): void;
|
|
3418
|
+
/** @internal Form-associated lifecycle: the browser restores the signature (back / forward navigation, autofill) from the state `syncForm()` saved. */
|
|
3419
|
+
formStateRestoreCallback(state: string | File | FormData | null): void;
|
|
3420
|
+
/** Form value, restore state and validity. A read-only pad, like a read-only input, is not validated. */
|
|
3421
|
+
private syncForm;
|
|
3422
|
+
/** When the signature was started, as an ISO 8601 string; `""` while empty. Set by the first stroke and cleared by Clear. Read-only. */
|
|
3423
|
+
get signedAt(): string;
|
|
3424
|
+
/** True when the active mode has no signature: no strokes and no stored signature in draw mode, a blank name in type mode. */
|
|
3425
|
+
isEmpty(): boolean;
|
|
3426
|
+
/** Removes the last stroke, or restores what Clear removed (in type mode, the cleared name). Does not fire `rel-change`. */
|
|
3427
|
+
undo(): void;
|
|
3428
|
+
/** Removes the whole signature of the active mode; Undo brings it back. Does not fire `rel-change`. */
|
|
3429
|
+
clear(): void;
|
|
3430
|
+
/**
|
|
3431
|
+
* The signature as a data URL of the given type (default `"image/png"`), trimmed to the ink at 2× with black ink; `"image/svg+xml"` returns `toSVG()` as a data URL, and `"image/jpeg"` gets a white background. `""` when empty.
|
|
3432
|
+
*/
|
|
3433
|
+
toDataURL(type?: string): string;
|
|
3434
|
+
/** The signature as an SVG document string, in black and trimmed. Draw mode gives smoothed paths in the `strokes` coordinate space (a stored signature from `value` is embedded as an image); type mode gives the name as `<text>` in Poppins italic. `""` when empty. */
|
|
3435
|
+
toSVG(): string;
|
|
3436
|
+
connectedCallback(): void;
|
|
3437
|
+
disconnectedCallback(): void;
|
|
3438
|
+
protected firstUpdated(): void;
|
|
3439
|
+
protected willUpdate(changed: PropertyValues<this>): void;
|
|
3440
|
+
protected updated(): void;
|
|
3441
|
+
private get typing();
|
|
3442
|
+
/** No strokes and no stored signature (draw mode's content, whatever the active mode). */
|
|
3443
|
+
private get drawEmpty();
|
|
3444
|
+
private get canUndo();
|
|
3445
|
+
private snapshot;
|
|
3446
|
+
private restore;
|
|
3447
|
+
private setStrokes;
|
|
3448
|
+
private setTypedName;
|
|
3449
|
+
/** Recomputes `value` from the active mode. */
|
|
3450
|
+
private commit;
|
|
3451
|
+
/** Strokes assigned from outside: a new signature with a fresh history. */
|
|
3452
|
+
private adoptStrokes;
|
|
3453
|
+
/** A value assigned from outside: show it as a stored signature, or empty the pad for `""`. */
|
|
3454
|
+
private adoptValue;
|
|
3455
|
+
/** A typed name assigned from outside: a fresh type-mode history, and no typed-at time. */
|
|
3456
|
+
private adoptTypedName;
|
|
3457
|
+
private undoStep;
|
|
3458
|
+
private clearStep;
|
|
3459
|
+
private emit;
|
|
3460
|
+
private emitChange;
|
|
3461
|
+
private get canEdit();
|
|
3462
|
+
private get canDraw();
|
|
3463
|
+
/** Display scale of the signature: 1, or smaller when the pad is now smaller than when the signature began. */
|
|
3464
|
+
private get viewScale();
|
|
3465
|
+
private addPoint;
|
|
3466
|
+
private onPointerDown;
|
|
3467
|
+
private onPointerMove;
|
|
3468
|
+
private onPointerEnd;
|
|
3469
|
+
private onKeyDown;
|
|
3470
|
+
/** Focus target that stays enabled: the pad in draw mode, the name input in type mode. */
|
|
3471
|
+
private focusField;
|
|
3472
|
+
private onUndoClick;
|
|
3473
|
+
private onClearClick;
|
|
3474
|
+
private onToggleMode;
|
|
3475
|
+
private onTypedInput;
|
|
3476
|
+
/** The native change event (blur, or Enter) commits the typed name. */
|
|
3477
|
+
private onTypedChange;
|
|
3478
|
+
private observeSize;
|
|
3479
|
+
private onResize;
|
|
3480
|
+
private scheduleDraw;
|
|
3481
|
+
/** Where a stored signature sits in the `strokes` space: at half its pixel size (it was exported at 2×), shrunk to fit, centred. */
|
|
3482
|
+
private storedPlacement;
|
|
3483
|
+
/** Paints the stored signature and the strokes in one colour. The stored image is recoloured, so it follows the ink colour as strokes do. */
|
|
3484
|
+
private paintInk;
|
|
3485
|
+
private draw;
|
|
3486
|
+
/** Bounding box of the ink in the `strokes` space, line widths included. */
|
|
3487
|
+
private inkBounds;
|
|
3488
|
+
/** The ink trimmed to its bounds plus padding, at 2×, in black. */
|
|
3489
|
+
private renderExport;
|
|
3490
|
+
/** The font of a typed signature: the input's family (our body family, Poppins) in italic. */
|
|
3491
|
+
private typedFont;
|
|
3492
|
+
/** Measures the typed name in its font. Until the font has loaded, measuring (and so the export) uses a fallback; the value is recomputed once it arrives. */
|
|
3493
|
+
private typedMetrics;
|
|
3494
|
+
/** The typed name trimmed to its bounds plus padding, at 2×, in black. */
|
|
3495
|
+
private renderTyped;
|
|
3496
|
+
private typedSVG;
|
|
3497
|
+
private formatSignedAt;
|
|
3498
|
+
/** The pad's accessible name: the field's name, then its state. */
|
|
3499
|
+
private padName;
|
|
3500
|
+
render(): lit_html.TemplateResult<1>;
|
|
3501
|
+
}
|
|
3502
|
+
declare global {
|
|
3503
|
+
interface HTMLElementTagNameMap {
|
|
3504
|
+
"rel-signature-pad": RelSignaturePad;
|
|
3505
|
+
}
|
|
3506
|
+
}
|
|
3507
|
+
|
|
2784
3508
|
/**
|
|
2785
3509
|
* "continuous"/"discrete" are the legacy tick-mode values; Figma's Type axis
|
|
2786
3510
|
* adds "default" (alias of continuous) and "range" (dual-thumb interval).
|
|
@@ -2807,7 +3531,7 @@ type SliderSizeInput = SliderSize | SliderSizeAlias;
|
|
|
2807
3531
|
* @cssprop --rel-slider-tick-size - Tick-mark diameter in discrete mode; 4 / 5 / 6px for size sm / md / lg
|
|
2808
3532
|
* @cssprop --rel-slider-bubble-radius - Corner radius of the value bubble; 8px for size sm, otherwise 10px
|
|
2809
3533
|
*/
|
|
2810
|
-
declare class RelSlider extends
|
|
3534
|
+
declare class RelSlider extends RelElement {
|
|
2811
3535
|
/** Slider mode: `continuous` (or its alias `default`) accepts any integer value, `discrete` snaps to `step` and draws tick marks, `range` shows two thumbs bounding `value`…`valueEnd`. */
|
|
2812
3536
|
type: SliderType;
|
|
2813
3537
|
/**
|
|
@@ -2896,22 +3620,22 @@ type SnackbarType = "default" | "success" | "error" | "warning";
|
|
|
2896
3620
|
* Snackbar (Figma "Snackbar"): a dark, elevated message bar with an optional tone accent and leading status icon, an optional action button and a close icon, shown via `show` and auto-dismissed after `duration` milliseconds. It is not positioned — place it (fixed or in-flow) yourself. Use it for brief feedback with a single follow-up action ("Undo", "Retry"); use `rel-alert` for persistent messages.
|
|
2897
3621
|
* @csspart label - The message text container
|
|
2898
3622
|
* @csspart action - The action button; rendered only when `action` is set
|
|
2899
|
-
* @csspart close-button - The close icon button; rendered while `
|
|
3623
|
+
* @csspart close-button - The close icon button; rendered while `icon-close` is true
|
|
2900
3624
|
*/
|
|
2901
|
-
declare class RelSnackbar extends
|
|
3625
|
+
declare class RelSnackbar extends RelElement {
|
|
2902
3626
|
/** Message text. Announced to screen readers through the shared live-region announcer when the snackbar is shown and whenever it changes while shown. The default is a placeholder — always set it. */
|
|
2903
3627
|
message: string;
|
|
2904
3628
|
/** Label of the optional action button (Figma trailing button, Static / Small); omitted when unset. Clicking it fires `actionClick` and then dismisses the snackbar. */
|
|
2905
3629
|
action?: string;
|
|
2906
3630
|
/**
|
|
2907
|
-
* Layout and timing (Figma "Type"): `"default"` (message and actions on one row) | `"longer-action"` (message stacked above the actions, which align to the end, with the auto-dismiss delay doubled so there is time to use the action). Takes precedence over the deprecated `lines` and `longerAction` props.
|
|
3631
|
+
* Layout and timing (Figma "Type"): `"default"` (the default: message and actions on one row) | `"longer-action"` (message stacked above the actions, which align to the end, with the auto-dismiss delay doubled so there is time to use the action). Takes precedence over the deprecated `lines` and `longerAction` props.
|
|
2908
3632
|
*/
|
|
2909
3633
|
variant?: SnackbarVariant;
|
|
2910
|
-
/** @deprecated — use `variant="longer-action"
|
|
3634
|
+
/** @deprecated — use `variant="longer-action"`. On its own it renders the full longer-action variant (stacked layout and the doubled auto-dismiss delay, `duration * 2`). Ignored when `variant` is set. Logs a one-time console notice. */
|
|
2911
3635
|
longerAction: boolean;
|
|
2912
|
-
/** Shows the trailing close icon button. Defaults to true;
|
|
3636
|
+
/** Shows the trailing close icon button. Defaults to true; `icon-close="false"` (or the property set to `false`) hides the button. */
|
|
2913
3637
|
iconClose: boolean;
|
|
2914
|
-
/** @deprecated — use `variant`; `lines="double"` maps to `variant="longer-action"
|
|
3638
|
+
/** @deprecated — use `variant`; `lines="double"` maps to `variant="longer-action"` (stacked layout and the doubled auto-dismiss delay). Ignored when `variant` is set. Logs a one-time console notice. */
|
|
2915
3639
|
lines: SnackbarLines;
|
|
2916
3640
|
/** Auto-dismiss delay in milliseconds (doubled by `variant="longer-action"`), started when `show` becomes true and restarted when `duration` or the layout changes while shown. `0` (or a negative value) disables auto-dismiss. */
|
|
2917
3641
|
duration: number;
|
|
@@ -2942,7 +3666,100 @@ declare class RelSnackbar extends LitElement {
|
|
|
2942
3666
|
render(): lit_html.TemplateResult<1>;
|
|
2943
3667
|
}
|
|
2944
3668
|
|
|
2945
|
-
/**
|
|
3669
|
+
/** One entry of the split button's menu. */
|
|
3670
|
+
interface SplitButtonItem {
|
|
3671
|
+
/** Identifies the entry in `rel-select`. Unique within `items`. */
|
|
3672
|
+
value: string;
|
|
3673
|
+
/** Visible text of the menu row. */
|
|
3674
|
+
label: string;
|
|
3675
|
+
/** `rel-icon` name drawn before the label, sized with the menu (20 / 18 / 16px). */
|
|
3676
|
+
icon?: string;
|
|
3677
|
+
/** The row stays in the menu (and reachable with the arrow keys) but cannot be chosen; drawn at 40% opacity. */
|
|
3678
|
+
disabled?: boolean;
|
|
3679
|
+
}
|
|
3680
|
+
type SplitButtonVariant = "primary" | "secondary" | "ghost" | "static";
|
|
3681
|
+
type SplitButtonTone = "neutral" | "brand" | "destructive";
|
|
3682
|
+
type SplitButtonSize = "small" | "medium" | "large";
|
|
3683
|
+
/**
|
|
3684
|
+
* New in 1.5.0. A button with a main action and a menu of related actions (the "Combo Button"): one pill in two segments with a 1px divider between them, the main action on the left and a chevron on the right that opens a `rel-menu` of `items`, anchored below and end-aligned. Each segment is its own `<button>` with rel-button's styles for the chosen `variant`, `tone` and `size`, so the heights (32 / 40 / 48), padding, hover, pressed, focus ring and disabled look are rel-button's. The chevron follows the WAI-ARIA menu button pattern and shows its pressed look while the menu is open.
|
|
3685
|
+
* @slot - The main action's content (text, or a `rel-icon` and text). Falls back to `label`.
|
|
3686
|
+
* @csspart main - The main action's native `<button>`.
|
|
3687
|
+
* @csspart toggle - The chevron's native `<button>` (`aria-haspopup="menu"`, `aria-expanded`, named by `menu-label`).
|
|
3688
|
+
* @csspart indicator - The loading spinner on the main action, rendered only while `loading` is set.
|
|
3689
|
+
* @csspart list - The menu's `role="menu"` list (rel-menu's list part): restyle the menu's surface here.
|
|
3690
|
+
* @cssprop --rel-split-button-menu-width - Width of the menu (default `max-content`). The menu is never narrower than the split button.
|
|
3691
|
+
* @cssprop --rel-button-min-width - The main action's minimum width, as on rel-button (80 / 100 / 120px by size).
|
|
3692
|
+
* @fires click - The main action was activated (a native click: pointer, Enter or Space). Clicks on the chevron or the menu do not reach the host. Swallowed while `disabled` or `loading`.
|
|
3693
|
+
* @fires rel-select - A menu entry was chosen with a click, Enter or Space; the menu has closed and focus is back on the chevron. Detail: `{ value: string, item: SplitButtonItem }`.
|
|
3694
|
+
* @fires rel-open-change - The menu opened or closed (chevron, keyboard, Escape, an outside click, Tab away, or a choice). Detail: `{ open: boolean }`.
|
|
3695
|
+
*/
|
|
3696
|
+
declare class RelSplitButton extends RelElement {
|
|
3697
|
+
/** Text of the main action. Slotted content replaces it. */
|
|
3698
|
+
label: string;
|
|
3699
|
+
/** Style of both segments, as rel-button's `variant`: `primary` (filled), `secondary` (outlined, the default), `ghost` (no fill or border) or `static` (transparent with a white label and divider, for dark or coloured surfaces; neutral only, as on rel-button). */
|
|
3700
|
+
variant: SplitButtonVariant;
|
|
3701
|
+
/** Colour of both segments, as rel-button's `tone`: `neutral` (default), `brand` or `destructive`. As on rel-button, `brand` changes only the `primary` style. */
|
|
3702
|
+
tone: SplitButtonTone;
|
|
3703
|
+
/** Height of the pill and size of its text and icons, as rel-button's `size`: `small` = 32px, `medium` = 40px (default), `large` = 48px. The menu rows take the same size. */
|
|
3704
|
+
size: SplitButtonSize;
|
|
3705
|
+
/** Dims both segments to rel-button's disabled look (the divider keeps its colour), removes them from the Tab order and keeps the menu closed. */
|
|
3706
|
+
disabled: boolean;
|
|
3707
|
+
/** The main action shows only rel-button's spinner, at its minimum width; its text stays its accessible name (visually hidden) and it is `aria-busy`. Its clicks are blocked and the chevron is disabled, so nothing else starts mid-request; an open menu closes. */
|
|
3708
|
+
loading: boolean;
|
|
3709
|
+
/** The main action is a square of the button's height (32 / 40 / 48), as rel-button's `icon-only`: give it a single icon (`icon`, or a slotted `rel-icon`) and set `aria-label`. */
|
|
3710
|
+
iconOnly: boolean;
|
|
3711
|
+
/** Accessible name of the main action, forwarded to its native `<button>`. Required with `icon-only`, where the main action has no visible text (a console warning names split buttons without one). */
|
|
3712
|
+
ariaLabel: string | null;
|
|
3713
|
+
/** Accessible name of the chevron button (attribute `menu-label`); it has no visible text. */
|
|
3714
|
+
menuLabel: string;
|
|
3715
|
+
/** `rel-icon` name drawn before the main action's text (16 / 18 / 20px by size). */
|
|
3716
|
+
icon: string;
|
|
3717
|
+
/** The menu entries, each `{ value, label, icon?, disabled? }`. Set as a property (or a JSON array attribute). */
|
|
3718
|
+
items: SplitButtonItem[];
|
|
3719
|
+
/** Whether the menu is open. Updated by the component (and announced with `rel-open-change`); set it to open or close the menu from code. */
|
|
3720
|
+
open: boolean;
|
|
3721
|
+
private popoverEl?;
|
|
3722
|
+
private menu?;
|
|
3723
|
+
/** The menu is at least as wide as the split button; measured on open. */
|
|
3724
|
+
private menuMinWidth;
|
|
3725
|
+
/** Right-to-left: the chevron is on the left, so the menu aligns to its start. */
|
|
3726
|
+
private rtl;
|
|
3727
|
+
static styles: (lit.CSSResult | lit.CSSResult[])[];
|
|
3728
|
+
connectedCallback(): void;
|
|
3729
|
+
disconnectedCallback(): void;
|
|
3730
|
+
/** One console warning per element for an icon-only main action with no name. */
|
|
3731
|
+
private warnedNoName;
|
|
3732
|
+
willUpdate(changed: PropertyValues<this>): void;
|
|
3733
|
+
private get variantKey();
|
|
3734
|
+
private get toneKey();
|
|
3735
|
+
private get sizeKey();
|
|
3736
|
+
/** rel-button's class contract: the same names rel-button renders, so its
|
|
3737
|
+
* stylesheet styles both segments. */
|
|
3738
|
+
private segmentClasses;
|
|
3739
|
+
/** Opens or closes the menu and announces it. `focusIndex` picks the row
|
|
3740
|
+
* the menu opens on (negative counts from the end). */
|
|
3741
|
+
private setOpen;
|
|
3742
|
+
private onHostClick;
|
|
3743
|
+
/** Tab or a click elsewhere moved focus out of the split button (its menu
|
|
3744
|
+
* included): the menu closes, focus stays where the user put it. */
|
|
3745
|
+
private onFocusOut;
|
|
3746
|
+
/** rel-popover asks (chevron press, Enter, Space, Escape, outside click);
|
|
3747
|
+
* the split button owns the state and re-emits the event as its own. */
|
|
3748
|
+
private onPopoverOpenChange;
|
|
3749
|
+
private onMenuSideClick;
|
|
3750
|
+
private onToggleKeydown;
|
|
3751
|
+
private onMenuSelect;
|
|
3752
|
+
private onMenuKeydown;
|
|
3753
|
+
render(): lit_html.TemplateResult<1>;
|
|
3754
|
+
private onMainClick;
|
|
3755
|
+
}
|
|
3756
|
+
declare global {
|
|
3757
|
+
interface HTMLElementTagNameMap {
|
|
3758
|
+
"rel-split-button": RelSplitButton;
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3761
|
+
|
|
3762
|
+
/** Control scale, spelled out (Figma Switch "Size": Small / Medium / Large). */
|
|
2946
3763
|
type SwitchSize = "small" | "medium" | "large";
|
|
2947
3764
|
/** Alternative spellings, not deprecations — the short names work too. */
|
|
2948
3765
|
type SwitchSizeAlias = "sm" | "md" | "lg";
|
|
@@ -2950,14 +3767,20 @@ type SwitchSizeInput = SwitchSize | SwitchSizeAlias;
|
|
|
2950
3767
|
/** Which side of the control the label sits on. */
|
|
2951
3768
|
type SwitchLabelPlacement = "end" | "start";
|
|
2952
3769
|
/**
|
|
2953
|
-
* Toggle switch (Figma "Switch",
|
|
2954
|
-
* thin 10px track and a 20px handle that slides 20px
|
|
2955
|
-
*
|
|
3770
|
+
* Toggle switch (Figma "Switch", 9059:11244): at the default medium size a
|
|
3771
|
+
* 44×20 control with a thin 10px track and a 20px handle that slides 20px
|
|
3772
|
+
* (`type="line"`), or a 44×24 filled track (`type="pill"`), with the label in
|
|
3773
|
+
* body-md beside it. Hover and pressed cover the whole component, and the
|
|
3774
|
+
* keyboard focus ring is a square 1.5px outline around the control and its
|
|
3775
|
+
* label together. Wraps a native checkbox with `role="switch"`, so keyboard
|
|
3776
|
+
* and screen-reader behaviour are native.
|
|
3777
|
+
* Form-associated, so an outer `<label>` (wrapping it, or `for=`) toggles it
|
|
3778
|
+
* and names it; it still sets no form value and is not submitted.
|
|
2956
3779
|
* @slot - Rich label content beside the control, as an alternative to the `label` property. Clicking it toggles the switch.
|
|
2957
|
-
* @csspart root - The `<label>` holding the control and its optional text; carries the `label-placement` order
|
|
3780
|
+
* @csspart root - The `<label>` holding the control and its optional text; carries the `label-placement` order and the keyboard focus ring
|
|
2958
3781
|
* @csspart base - The control box around the hidden input and the track
|
|
2959
3782
|
* @csspart track - The thin rail; the handle is its `::before` pseudo-element
|
|
2960
|
-
* @csspart label - The text beside the control; not rendered when there is neither a `label` nor slotted content
|
|
3783
|
+
* @csspart label - The text beside the control (body-sm / body-md / body-lg by `size`; `--rel-text-disabled` while disabled); not rendered when there is neither a `label` nor slotted content
|
|
2961
3784
|
* @cssprop --rel-switch-track-width - Overall control width; defaults to the `size` ramp (36 / 44 / 52px)
|
|
2962
3785
|
* @cssprop --rel-switch-track-height - Overall control height; defaults to the `size` ramp — 16 / 20 / 24px for `type="line"`, 20 / 24 / 28px for `type="pill"`
|
|
2963
3786
|
* @cssprop --rel-switch-thumb-size - Handle diameter; defaults to the `size` ramp (16 / 20 / 24px), and the handle always travels its own width minus the 2px inset on each side
|
|
@@ -2966,23 +3789,23 @@ type SwitchLabelPlacement = "end" | "start";
|
|
|
2966
3789
|
* @cssprop --rel-switch-knob-off - Handle colour when unchecked; default `var(--rel-text-static-light)`
|
|
2967
3790
|
* @cssprop --rel-switch-disabled - Handle colour while disabled; default `var(--rel-bg-neutral-elevated-1)`
|
|
2968
3791
|
*/
|
|
2969
|
-
declare class RelSwitch extends
|
|
3792
|
+
declare class RelSwitch extends RelElement {
|
|
3793
|
+
/** Form-associated only so an outer `<label>` has a control (see utils/outer-label.ts). No form value is set. */
|
|
3794
|
+
static formAssociated: boolean;
|
|
2970
3795
|
/** Whether the switch is on. Set it to control the state programmatically; user toggles update it and fire `rel-change`. */
|
|
2971
3796
|
checked: boolean;
|
|
2972
3797
|
/**
|
|
2973
3798
|
* Shape (Figma "Type"): `"line"` (default) is the 44x20 control with a thin
|
|
2974
3799
|
* 40x10 rail and the handle riding on it; `"pill"` is the 44x24 filled track
|
|
2975
|
-
* with the handle inside it.
|
|
2976
|
-
*
|
|
2977
|
-
* flipping it would restyle every existing switch — so this is a recorded
|
|
2978
|
-
* divergence from the design default, not an oversight.
|
|
3800
|
+
* with the handle inside it. Pressing squashes the handle; only `line`
|
|
3801
|
+
* also shows a pressed disc behind it.
|
|
2979
3802
|
*/
|
|
2980
3803
|
type: "line" | "pill";
|
|
2981
|
-
/** Disables interaction and swaps in the dulled rail / handle fills; the handle shadow is removed. */
|
|
3804
|
+
/** Disables interaction and swaps in the dulled rail / handle fills (for both types, checked or not) and the disabled label colour; the handle shadow is removed. An ancestor `<fieldset disabled>` disables it the same way, without changing this property. */
|
|
2982
3805
|
disabled: boolean;
|
|
2983
3806
|
/** Arbitrary string echoed in the `rel-change` event detail — useful when one handler serves several switches. */
|
|
2984
3807
|
value: string;
|
|
2985
|
-
/** Accessible name for the native input
|
|
3808
|
+
/** Accessible name for the native input when the switch has no visible text. Prefer `label`, slotted text or an outer `<label>` (wrapping the switch, or `for=`), which are visible and clickable. */
|
|
2986
3809
|
fieldAriaLabel?: string;
|
|
2987
3810
|
/** Visible text beside the control. Clicking it toggles the switch, and it becomes the accessible name — use `fieldAriaLabel` instead when the switch has no visible text. For rich content (a bold word, an icon) slot it in the default slot rather than setting this. */
|
|
2988
3811
|
label?: string;
|
|
@@ -2998,9 +3821,9 @@ declare class RelSwitch extends LitElement {
|
|
|
2998
3821
|
* are alternative spellings and stay supported — normalised to the full
|
|
2999
3822
|
* words, not deprecated.
|
|
3000
3823
|
*
|
|
3001
|
-
* Figma's
|
|
3002
|
-
*
|
|
3003
|
-
*
|
|
3824
|
+
* Matches Figma's Size axis: controls 36 / 44 / 52px wide, labels body-sm /
|
|
3825
|
+
* body-md / body-lg (12 / 14 / 16px). The default stays `medium` (Figma's
|
|
3826
|
+
* own default is Large).
|
|
3004
3827
|
*
|
|
3005
3828
|
* It does NOT respond to viewport width. Picking a size per breakpoint is the
|
|
3006
3829
|
* consuming application's decision — a control that silently resized itself
|
|
@@ -3010,8 +3833,15 @@ declare class RelSwitch extends LitElement {
|
|
|
3010
3833
|
size: SwitchSizeInput;
|
|
3011
3834
|
private _onChange;
|
|
3012
3835
|
private _onTouched;
|
|
3013
|
-
private
|
|
3014
|
-
|
|
3836
|
+
private readonly internals;
|
|
3837
|
+
/** A click on an outer label arrives at the host; route it through the
|
|
3838
|
+
* native input so it toggles exactly as a direct click does (one
|
|
3839
|
+
* `change`, one `rel-change`). A disabled input ignores the click. */
|
|
3840
|
+
private readonly outerLabel;
|
|
3841
|
+
/** Own `disabled`, or an ancestor `<fieldset disabled>`. */
|
|
3842
|
+
private get isDisabled();
|
|
3843
|
+
/** @internal Form-associated lifecycle: an ancestor `<fieldset disabled>` disables the control too (utils/outer-label.ts, 3). */
|
|
3844
|
+
formDisabledCallback(): void;
|
|
3015
3845
|
private hasSlottedLabel;
|
|
3016
3846
|
/** Alternative spellings, NOT deprecations — no console notice. Normalising
|
|
3017
3847
|
* keeps the reflected attribute canonical so the :host([size=…]) rules only
|
|
@@ -3025,10 +3855,7 @@ declare class RelSwitch extends LitElement {
|
|
|
3025
3855
|
registerOnTouched(fn: () => void): void;
|
|
3026
3856
|
/** @internal Angular ControlValueAccessor bridge. */
|
|
3027
3857
|
writeValue(checked: boolean): void;
|
|
3028
|
-
private handleFocus;
|
|
3029
3858
|
private handleBlur;
|
|
3030
|
-
private handleMouseDown;
|
|
3031
|
-
private handleMouseUp;
|
|
3032
3859
|
render(): lit_html.TemplateResult<1>;
|
|
3033
3860
|
/** Rich label content can be slotted instead of set as text; this keeps the
|
|
3034
3861
|
* label span out of the layout entirely when neither is present, so an
|
|
@@ -3050,11 +3877,15 @@ interface TabItem {
|
|
|
3050
3877
|
* is an explicit item height — 32 / 40 / 48px (Figma Tab Item S/M/L).
|
|
3051
3878
|
*/
|
|
3052
3879
|
type TabSize = "sm" | "md" | "lg" | "small" | "medium" | "large";
|
|
3880
|
+
/** Layout of the tab list: a row above the panel (`horizontal`, default) or a column beside it (`vertical`). */
|
|
3881
|
+
type TabOrientation = "horizontal" | "vertical";
|
|
3882
|
+
/** Where each tab's icon sits relative to its label. */
|
|
3883
|
+
type TabIconPlacement = "start" | "top";
|
|
3053
3884
|
/**
|
|
3054
3885
|
* Declarative tab definition for `<rel-tab>`. Renders nothing itself — place
|
|
3055
3886
|
* it in the parent's `items` slot and the parent reads its properties.
|
|
3056
3887
|
*/
|
|
3057
|
-
declare class RelTabItem extends
|
|
3888
|
+
declare class RelTabItem extends RelElement {
|
|
3058
3889
|
/** Text shown on the tab. */
|
|
3059
3890
|
label: string;
|
|
3060
3891
|
/** Icon name from the generated icon dictionary, rendered before the label (Figma "Show Icon" / "Icon"). Sized 20 / 18 / 16px with the tab's own size step. */
|
|
@@ -3079,14 +3910,15 @@ declare class RelTabItem extends LitElement {
|
|
|
3079
3910
|
* @csspart list - The `role="tablist"` row
|
|
3080
3911
|
* @csspart item - Each `role="tab"` element
|
|
3081
3912
|
* @csspart label - The text span inside each tab
|
|
3913
|
+
* @cssprop --rel-tab-list-width - Width of the tab list when `orientation="vertical"`; default `max-content`
|
|
3082
3914
|
* @cssprop --rel-tab-active-color - Underline colour of the active tab; default `var(--rel-bg-brand)`
|
|
3083
3915
|
* @cssprop --rel-tab-underline-height - Thickness of the active underline; default 1px (`--rel-stroke-sm`, the weight Figma draws). Set it to restore the heavier 3px bar shipped previously.
|
|
3084
3916
|
* @cssprop --rel-tab-text-default - Label colour of the active tab; default `var(--rel-text-default)`
|
|
3085
|
-
* @cssprop --rel-tab-text-hover - Label colour while hovering an enabled tab; default `var(--rel-text-
|
|
3917
|
+
* @cssprop --rel-tab-text-hover - Label colour while hovering an enabled tab; default `var(--rel-text-default)`
|
|
3086
3918
|
* @cssprop --rel-tab-text-disabled - Label colour of a disabled tab; default `var(--rel-text-disabled)`
|
|
3087
|
-
* @cssprop --rel-tab-hover-color - Background of an inactive tab on hover; default `
|
|
3919
|
+
* @cssprop --rel-tab-hover-color - Background of an inactive tab on hover; default `transparent` (the design darkens the label instead). Set it to bring a hover fill back.
|
|
3088
3920
|
*/
|
|
3089
|
-
declare class RelTab extends
|
|
3921
|
+
declare class RelTab extends RelElement {
|
|
3090
3922
|
/** Tab definitions as `{ label, badge?, badgeDot?, disabled? }` objects — normally set as a property (as an attribute it must be a JSON string). Assign a new array to update; mutating in place does not re-render. Ignored when `<rel-tab-item>` children are slotted into `items`. */
|
|
3091
3923
|
tabs: TabItem[];
|
|
3092
3924
|
/** Zero-based index of the selected tab. Set it to switch tabs programmatically (no event is fired for programmatic changes). */
|
|
@@ -3094,6 +3926,10 @@ declare class RelTab extends LitElement {
|
|
|
3094
3926
|
/** Tab size — styled via :host([size]) rules. Explicit item heights
|
|
3095
3927
|
* 32 / 40 / 48px (audit 34); `small|medium|large` alias `sm|md|lg`. */
|
|
3096
3928
|
size: TabSize;
|
|
3929
|
+
/** New in 1.5.0. Tab list layout: `horizontal` (default, a row above the panel) or `vertical` (a column beside the panel as wide as its longest label, tabs 24px apart along a rule on the list's inline-start edge, the active bar on that edge, labels that wrap rather than truncate; Up / Down move between tabs). There is no built-in breakpoint: switch to horizontal on small screens in your app. */
|
|
3930
|
+
orientation: TabOrientation;
|
|
3931
|
+
/** New in 1.5.0. Icon position in every tab: `start` (default, before the label) or `top` (stacked above the label, with the badge beside the label). Stacked tabs are 76 / 64 / 52px tall at large / medium / small. Works in both orientations. */
|
|
3932
|
+
iconPlacement: TabIconPlacement;
|
|
3097
3933
|
private _tabItems;
|
|
3098
3934
|
/** Stable id prefix linking tabs to the shared tabpanel. */
|
|
3099
3935
|
private tabsId;
|
|
@@ -3133,16 +3969,17 @@ declare class RelTab extends LitElement {
|
|
|
3133
3969
|
* @csspart option - Each hour / minute / second / AM-PM entry button
|
|
3134
3970
|
* @csspart footer - The Now / Cancel / OK row
|
|
3135
3971
|
* @csspart helper - The helper / error text live region under the field
|
|
3972
|
+
* @cssprop --rel-overlay-fallback-z - z-index of the panel on the **no-Popover-API fallback path only**. Wherever the browser top layer is available the panel is promoted into it and this value is inert, because top-layer elements are not in the page stacking order at all. Shared with the other overlays (select, autocomplete, the three pickers) so the whole family can be moved from one place.
|
|
3136
3973
|
* @fires rel-focus - Fired when the text input receives focus. No detail.
|
|
3137
3974
|
*/
|
|
3138
|
-
declare class RelTimePicker extends
|
|
3975
|
+
declare class RelTimePicker extends RelElement {
|
|
3139
3976
|
/** Committed time, 24-hour "HH:mm" or "HH:mm:ss" (e.g. "09:30", "17:05:30"). */
|
|
3140
3977
|
value: string | null;
|
|
3141
3978
|
/** Placeholder shown in the field while no value is committed and nothing is typed. */
|
|
3142
3979
|
placeholder: string;
|
|
3143
3980
|
/** Field label rendered above the trigger; also the input's accessible name (unset → "Select time"). */
|
|
3144
3981
|
label: string | null;
|
|
3145
|
-
/** Disables the field (
|
|
3982
|
+
/** Disables the field (no pointer events) and the panel cannot open. The field looks exactly like a disabled `rel-textfield`: the whole field at 0.65 opacity, an elevated-2 box with the accent border, the label in `--rel-text-label` and the value and placeholder in `--rel-text-caption` (changed in 1.5.0: they were `--rel-text-disabled` under the 0.65, which left them barely readable). */
|
|
3146
3983
|
disabled: boolean;
|
|
3147
3984
|
/** Renders the `*` mark after the label and sets `aria-required`; not enforced by the component. */
|
|
3148
3985
|
required: boolean;
|
|
@@ -3176,7 +4013,7 @@ declare class RelTimePicker extends LitElement {
|
|
|
3176
4013
|
size: "small" | "medium" | "large";
|
|
3177
4014
|
/** Visual style; only `"outlined"` exists today. */
|
|
3178
4015
|
variant: "outlined";
|
|
3179
|
-
/** Fills the parent width (the host is inline-block with intrinsic width otherwise). The attribute is
|
|
4016
|
+
/** Fills the parent width (the host is inline-block with intrinsic width otherwise). The attribute is `full-width`. */
|
|
3180
4017
|
fullWidth: boolean;
|
|
3181
4018
|
private draftHour;
|
|
3182
4019
|
private draftMinute;
|
|
@@ -3204,6 +4041,7 @@ declare class RelTimePicker extends LitElement {
|
|
|
3204
4041
|
private showTopLayer;
|
|
3205
4042
|
private hideTopLayer;
|
|
3206
4043
|
private onReposition;
|
|
4044
|
+
private scrollWatch;
|
|
3207
4045
|
private updatePopoverPosition;
|
|
3208
4046
|
/** Focus the selected (or first enabled) option in the columns. */
|
|
3209
4047
|
private focusPanelSelection;
|
|
@@ -3280,8 +4118,11 @@ declare global {
|
|
|
3280
4118
|
}
|
|
3281
4119
|
}
|
|
3282
4120
|
|
|
3283
|
-
/**
|
|
3284
|
-
|
|
4121
|
+
/**
|
|
4122
|
+
* Canonical semantic tones: neutral | info | success | destructive, as on
|
|
4123
|
+
* Figma's Toast "Tone" axis; the filled tones reuse rel-alert's solid tone tokens.
|
|
4124
|
+
*/
|
|
4125
|
+
type ToastTone = "neutral" | "info" | "success" | "destructive";
|
|
3285
4126
|
/** Deprecated spellings: "default" → neutral; "error" | "danger" | "critical" → destructive. */
|
|
3286
4127
|
type ToastToneAlias = "default" | "error" | "danger" | "critical";
|
|
3287
4128
|
type ToastToneInput = ToastTone | ToastToneAlias;
|
|
@@ -3309,22 +4150,23 @@ type ToastSizeInput = ToastSize | ToastSizeAlias;
|
|
|
3309
4150
|
* independently. Behaviour change: five toasts at one position used to render on
|
|
3310
4151
|
* top of each other; now three show and two wait.
|
|
3311
4152
|
* @csspart base - The `role="status"` toast container that carries the tone class
|
|
4153
|
+
* @csspart icon - The 20px leading icon of a filled tone (`error` on destructive, `check-circle` on success, `info` on info); a neutral toast has none. New in 1.5.0
|
|
3312
4154
|
* @csspart label - The message text span
|
|
3313
|
-
* @csspart action - The action button; rendered only when `
|
|
4155
|
+
* @csspart action - The action button; rendered only when `action-label` is set
|
|
3314
4156
|
* @csspart close-button - The dismiss button; rendered while `dismissible` is true
|
|
3315
4157
|
* @cssprop --rel-toast-z - `z-index` of the fixed host (default `9000`); raise it when a modal or drawer layer covers the toast
|
|
3316
4158
|
* @cssprop --rel-z-toast - Deprecated alias of `--rel-toast-z`, still read as its fallback
|
|
3317
4159
|
*/
|
|
3318
|
-
declare class RelToast extends
|
|
4160
|
+
declare class RelToast extends RelElement {
|
|
3319
4161
|
/** Text of the toast. It is also announced to screen readers through the shared live-region announcer each time `show` becomes true. */
|
|
3320
4162
|
message: string;
|
|
3321
4163
|
/**
|
|
3322
|
-
* Semantic tone (Figma "Tone"): `"neutral"` (default: neutral surface) | `"destructive"` (danger fill, announced assertively). `"default"` is a deprecated alias of `"neutral"`; `"error"`, `"danger"` and `"critical"` are deprecated aliases of `"destructive"`; each logs a one-time console notice. Takes precedence over the deprecated `type` prop.
|
|
4164
|
+
* Semantic tone (Figma "Tone"): `"neutral"` (default: neutral surface) | `"info"` (info fill) | `"success"` (success fill) | `"destructive"` (danger fill, announced assertively). The three filled tones use the same fill and text tokens as rel-alert's solid style, so a toast matches an alert of the same tone; info and success are announced politely. The three filled tones show a 20px leading icon (`error`, `check-circle`, `info`; part `icon`, hidden from assistive technology); the neutral tone has none (new in 1.5.0). Figma's Toast has all four tones. An unknown value renders as `"neutral"`. `"default"` is a deprecated alias of `"neutral"`; `"error"`, `"danger"` and `"critical"` are deprecated aliases of `"destructive"`; each logs a one-time console notice. Takes precedence over the deprecated `type` prop.
|
|
3323
4165
|
*/
|
|
3324
4166
|
tone?: ToastToneInput;
|
|
3325
4167
|
/** @deprecated Deprecated since 1.4.7 — alias of `tone`; use `tone`. Same values as `tone`; `type="error"` maps to `tone="destructive"` and `type="default"` to `tone="neutral"`. Ignored when `tone` is set. Logs a one-time console notice. */
|
|
3326
4168
|
type?: ToastToneInput;
|
|
3327
|
-
/** Read-only canonical tone actually rendered: explicit `tone` wins, else `type`, else `"neutral"`; deprecated aliases are resolved to `"neutral"` / `"destructive"`. */
|
|
4169
|
+
/** Read-only canonical tone actually rendered: explicit `tone` wins, else `type`, else `"neutral"`; deprecated aliases are resolved to `"neutral"` / `"destructive"`, and an unknown value to `"neutral"`. */
|
|
3328
4170
|
get resolvedTone(): ToastTone;
|
|
3329
4171
|
/** Label of the optional action button rendered between the message and the dismiss button; the button is omitted when unset. Clicking it fires `action` and then closes the toast. */
|
|
3330
4172
|
actionLabel?: string;
|
|
@@ -3332,7 +4174,7 @@ declare class RelToast extends LitElement {
|
|
|
3332
4174
|
duration: number;
|
|
3333
4175
|
/** Whether the toast is visible. Set it to true (or call `open()`) to show the toast and start the auto-dismiss timer; it is set back to false by `close()`, the dismiss button, the action button and the timer. */
|
|
3334
4176
|
show: boolean;
|
|
3335
|
-
/** Shows the trailing dismiss button (Figma "Show Close Button"). Defaults to true;
|
|
4177
|
+
/** Shows the trailing dismiss button (Figma "Show Close Button"). Defaults to true; `dismissible="false"` (or the property set to `false`) hides the button. */
|
|
3336
4178
|
dismissible: boolean;
|
|
3337
4179
|
/**
|
|
3338
4180
|
* Where the toast is anchored: `bottom-center` (default, unchanged from
|
|
@@ -3400,12 +4242,12 @@ type TooltipType = "single-line" | "multi-line";
|
|
|
3400
4242
|
type TooltipTone = "inverse" | "neutral";
|
|
3401
4243
|
/**
|
|
3402
4244
|
* Hover/focus tooltip (Figma "Tooltip"): wraps a trigger element and shows a short inverse-coloured text bubble above, below, left or right of it. Use it for supplementary hints on icons and truncated labels only — the text is not reachable on touch and must never be the only place critical information lives.
|
|
3403
|
-
* @slot - The trigger element (one focusable element such as a button or icon button).
|
|
4245
|
+
* @slot - The trigger element (one focusable element such as a button or icon button). The control that takes focus — the slotted element itself, or the focusable control inside a rel-* trigger such as rel-button — receives `text` as its `aria-description`, so screen readers announce it.
|
|
3404
4246
|
* @csspart panel - The tooltip bubble (`role="tooltip"`): background, padding, radius, shadow and max-width.
|
|
3405
4247
|
* @csspart indicator - The triangular tail pointing at the trigger, rendered only when `show-tail` is set.
|
|
3406
4248
|
* @cssprop --rel-tooltip-offset - Gap between the trigger and the bubble; defaults to `6px`, or `13px` when `show-tail` is set so the tail clears the trigger.
|
|
3407
4249
|
*/
|
|
3408
|
-
declare class RelTooltip extends
|
|
4250
|
+
declare class RelTooltip extends RelElement {
|
|
3409
4251
|
/** Plain-text content of the bubble. Empty text still renders an (empty) bubble on hover, so always set it. */
|
|
3410
4252
|
text: string;
|
|
3411
4253
|
/** Side of the trigger the bubble appears on, centred and 6px away (13px when `show-tail` is set, so the tail clears the trigger; override with `--rel-tooltip-offset`): `above`, `below`, `left` or `right`. No collision detection — pick a side with room in the viewport. */
|
|
@@ -3417,6 +4259,10 @@ declare class RelTooltip extends LitElement {
|
|
|
3417
4259
|
/** Bubble appearance: `inverse` (default) is the original inverse-surface bubble, unchanged; `neutral` is a light surface — `--rel-bg-neutral` with `--rel-text-default` and a 1px `--rel-border-default`, tail included. Figma has no such variant; this is a deliberate addition. */
|
|
3418
4260
|
tone: TooltipTone;
|
|
3419
4261
|
private uniqueId;
|
|
4262
|
+
/** The element whose description is the tooltip text. */
|
|
4263
|
+
private describedEl;
|
|
4264
|
+
/** The value this component wrote, so it only ever removes its own. */
|
|
4265
|
+
private appliedDescription;
|
|
3420
4266
|
static styles: lit.CSSResult;
|
|
3421
4267
|
connectedCallback(): void;
|
|
3422
4268
|
disconnectedCallback(): void;
|
|
@@ -3425,10 +4271,143 @@ declare class RelTooltip extends LitElement {
|
|
|
3425
4271
|
private onKeydown;
|
|
3426
4272
|
private clearDismissed;
|
|
3427
4273
|
firstUpdated(): void;
|
|
4274
|
+
updated(changed: Map<string, unknown>): void;
|
|
4275
|
+
/**
|
|
4276
|
+
* Screen readers announce `text` as the trigger's DESCRIPTION. It used to
|
|
4277
|
+
* be wired with aria-describedby pointing at the bubble's id, but the
|
|
4278
|
+
* trigger is light DOM and the bubble lives in this shadow root: an IDREF
|
|
4279
|
+
* cannot cross that boundary, so nothing was ever announced. aria-description
|
|
4280
|
+
* carries the text itself, and it goes on the element that actually takes
|
|
4281
|
+
* focus — the slotted element, or, for a rel-* trigger such as rel-button,
|
|
4282
|
+
* the first focusable control inside its shadow root (the host itself is
|
|
4283
|
+
* not in the focus order and its description would never be read).
|
|
4284
|
+
*/
|
|
3428
4285
|
private linkTrigger;
|
|
4286
|
+
private syncDescription;
|
|
4287
|
+
private clearDescription;
|
|
3429
4288
|
render(): lit_html.TemplateResult<1>;
|
|
3430
4289
|
}
|
|
3431
4290
|
|
|
4291
|
+
/** One node of a `rel-tree`. */
|
|
4292
|
+
interface TreeItem {
|
|
4293
|
+
/** Identifies the item in `selected`, `selected-values`, `expanded-values` and every event. Unique within the tree. */
|
|
4294
|
+
value: string;
|
|
4295
|
+
/** Visible label: one line, truncated with an ellipsis (the full text is the row's tooltip). */
|
|
4296
|
+
label: string;
|
|
4297
|
+
/** `rel-icon` name drawn before the label (Figma "Show Icon"), 16px. */
|
|
4298
|
+
icon?: string;
|
|
4299
|
+
/** Child items. A non-empty array makes the item a parent with an expand / collapse caret. */
|
|
4300
|
+
children?: TreeItem[];
|
|
4301
|
+
/** Seeds `expanded-values` when the tree first gets its items. */
|
|
4302
|
+
expanded?: boolean;
|
|
4303
|
+
/**
|
|
4304
|
+
* Children are loaded on demand. While `children` is undefined the item shows a caret; expanding it fires `rel-load-children` and marks the row `aria-busy` until you set its `children` (an empty array when it has none, which makes it a leaf) and assign `items` again.
|
|
4305
|
+
*/
|
|
4306
|
+
lazy?: boolean;
|
|
4307
|
+
/** The row stays focusable but cannot be selected, checked or expanded (Figma State=Disabled, 40% opacity). A parent's check cascade skips it. */
|
|
4308
|
+
disabled?: boolean;
|
|
4309
|
+
}
|
|
4310
|
+
type TreeSelection = "single" | "multiple" | "none";
|
|
4311
|
+
/**
|
|
4312
|
+
* Hierarchical list whose parents expand and collapse (Figma "Nested Tree"), rendered from the `items` array: 24px rows with hierarchy guides, an expand / collapse caret on parents, an optional icon and a one-line label. The tree is one Tab stop; the arrow keys move, expand and collapse as in the WAI-ARIA Tree View pattern. It has no background, padding or radius of its own: place it inside the surface that hosts it.
|
|
4313
|
+
* @csspart tree - The `role="tree"` list.
|
|
4314
|
+
* @csspart item - Each `role="treeitem"` element; it contains the item's row and, when expanded, the group of its children.
|
|
4315
|
+
* @csspart row - The visible row of an item (guides, caret, checkbox, icon, label). Carries the hover, pressed, selected and focus styles.
|
|
4316
|
+
* @csspart guide - One hierarchy-guide column, one per level of indentation.
|
|
4317
|
+
* @csspart caret - The expand / collapse caret of a parent row.
|
|
4318
|
+
* @csspart checkbox - The check glyph of a row in `multiple` mode (Figma .Check Control: unchecked, checked, indeterminate).
|
|
4319
|
+
* @csspart icon - The optional leading icon.
|
|
4320
|
+
* @csspart label - The label text.
|
|
4321
|
+
* @csspart group - The `role="group"` list that holds an expanded item's children.
|
|
4322
|
+
* @cssprop --rel-tree-row-height - Row height (default 24px, Figma .Tree Item).
|
|
4323
|
+
* @cssprop --rel-tree-indent - Width of one level of indentation, one guide column (default 24px).
|
|
4324
|
+
* @cssprop --rel-tree-guide-color - Colour of the hierarchy guides (default `var(--rel-border-subtle)`).
|
|
4325
|
+
* @fires rel-change - The user changed the selection with Enter, Space or a click: picked a row in `single` mode (detail `{ value: string }`) or checked / unchecked one in `multiple` mode (detail `{ value: string[] }`, the new `selected-values`).
|
|
4326
|
+
* @fires rel-expanded-change - The user expanded or collapsed a parent. Detail: `{ value: string; expanded: boolean }`.
|
|
4327
|
+
* @fires rel-load-children - A `lazy` item without `children` was expanded (by the user, `expanded` or `expanded-values`). Load its children, set them on the item and assign `items` again. Fired once per item until its children arrive. Detail: `{ value: string }`.
|
|
4328
|
+
*/
|
|
4329
|
+
declare class RelTree extends RelElement {
|
|
4330
|
+
/** The tree's items, each `{ value, label, icon?, children?, expanded?, disabled?, lazy? }`. Set as a property or as a JSON array attribute. */
|
|
4331
|
+
items: TreeItem[];
|
|
4332
|
+
/** Selection mode: `single` (default; the selected row has the Figma Active style and `aria-selected="true"`), `multiple` (a checkbox on every row, see `selected-values`) or `none` (navigation only: Enter, Space and clicks on a parent row expand or collapse it). */
|
|
4333
|
+
selection: TreeSelection;
|
|
4334
|
+
/** `value` of the selected item in `single` mode; `""` when nothing is selected. Updated on every user selection. */
|
|
4335
|
+
selected: string;
|
|
4336
|
+
/**
|
|
4337
|
+
* Values of the checked items in `multiple` mode. Checking a parent checks every enabled descendant and unchecking it clears them; a parent is checked when all its children are, and shows the indeterminate glyph (`aria-checked="mixed"`) when only some are. The array lists every checked value, parents included, and is rewritten in that form when you set it: a parent's value checks its whole subtree.
|
|
4338
|
+
*/
|
|
4339
|
+
selectedValues: string[];
|
|
4340
|
+
/** Values of the expanded parents. Seeded from the items' `expanded` flags, updated whenever the user expands or collapses a row; set it to control expansion. */
|
|
4341
|
+
expandedValues: string[];
|
|
4342
|
+
/** Draws the hierarchy guides (│ ├ └) in the indentation. On by default; `show-guides="false"` hides them and keeps the indentation. */
|
|
4343
|
+
showGuides: boolean;
|
|
4344
|
+
/** Accessible name of the tree. The tree renders no visible label of its own, so set this (a console warning names trees without one). */
|
|
4345
|
+
fieldAriaLabel?: string;
|
|
4346
|
+
/** The item that holds the Tab stop (roving tabindex). */
|
|
4347
|
+
private focusedValue;
|
|
4348
|
+
private typeahead;
|
|
4349
|
+
private typeaheadTimer?;
|
|
4350
|
+
private seededExpansion;
|
|
4351
|
+
private warnedNoName;
|
|
4352
|
+
private rtl;
|
|
4353
|
+
private labelIds;
|
|
4354
|
+
/** Derived check state of every item in `multiple` mode. */
|
|
4355
|
+
private checks;
|
|
4356
|
+
/** Lazy items whose children were requested and have not arrived (`aria-busy`). */
|
|
4357
|
+
private loading;
|
|
4358
|
+
private pendingLoads;
|
|
4359
|
+
static styles: lit.CSSResult;
|
|
4360
|
+
private isParent;
|
|
4361
|
+
/** A lazy item whose children have not been set yet. */
|
|
4362
|
+
private isUnloaded;
|
|
4363
|
+
/** Shows a caret: has children, or may have them once loaded. */
|
|
4364
|
+
private canExpand;
|
|
4365
|
+
private isExpanded;
|
|
4366
|
+
/** Every item with its parent, depth first. */
|
|
4367
|
+
private allRows;
|
|
4368
|
+
/** The rows the user can see, in reading order. */
|
|
4369
|
+
private visibleRows;
|
|
4370
|
+
/** Check state of every item, from the checked leaves (a parent's value counts as all of its leaves). */
|
|
4371
|
+
private deriveChecks;
|
|
4372
|
+
private checkedValues;
|
|
4373
|
+
/** Normalises `selectedValues` to the derived form: every fully checked value, parents included. */
|
|
4374
|
+
private syncChecks;
|
|
4375
|
+
/** Checks or clears every enabled leaf under `item` (disabled subtrees keep their state). */
|
|
4376
|
+
private toggleCheck;
|
|
4377
|
+
protected willUpdate(changed: PropertyValues<this>): void;
|
|
4378
|
+
protected updated(changed: PropertyValues<this>): void;
|
|
4379
|
+
disconnectedCallback(): void;
|
|
4380
|
+
/** Expands every parent that has children (lazy items whose children have not been loaded stay closed). */
|
|
4381
|
+
expandAll(): void;
|
|
4382
|
+
/** Collapses every parent. */
|
|
4383
|
+
collapseAll(): void;
|
|
4384
|
+
private emit;
|
|
4385
|
+
private setExpanded;
|
|
4386
|
+
/** Enter, Space or a click on the row. */
|
|
4387
|
+
private activate;
|
|
4388
|
+
private focusRow;
|
|
4389
|
+
private onRowClick;
|
|
4390
|
+
/** A row can get focus without the keyboard or a click (`focus()`, a screen reader's cursor): it takes the Tab stop, so keys act on it. */
|
|
4391
|
+
private onFocusIn;
|
|
4392
|
+
private onKeyDown;
|
|
4393
|
+
/** Moves to the next visible row whose label starts with the typed text; repeating one character cycles through the matches. */
|
|
4394
|
+
private typeAhead;
|
|
4395
|
+
/**
|
|
4396
|
+
* `more[i]` says whether the ancestor at depth i has a sibling below it.
|
|
4397
|
+
* Level 1 has no guide column; below that there is one column per ancestor
|
|
4398
|
+
* level (a line where that ancestor continues, blank where it ended) and
|
|
4399
|
+
* a last column for the row's own connector (branch, or end on a last child).
|
|
4400
|
+
*/
|
|
4401
|
+
private renderItems;
|
|
4402
|
+
private renderItem;
|
|
4403
|
+
render(): TemplateResult<1>;
|
|
4404
|
+
}
|
|
4405
|
+
declare global {
|
|
4406
|
+
interface HTMLElementTagNameMap {
|
|
4407
|
+
"rel-tree": RelTree;
|
|
4408
|
+
}
|
|
4409
|
+
}
|
|
4410
|
+
|
|
3432
4411
|
/** Per-file lifecycle state. Mirrors the Figma "Upload File Row" variants 1:1. */
|
|
3433
4412
|
type UploadStatus = "ready" | "uploading" | "success" | "error";
|
|
3434
4413
|
/**
|
|
@@ -3455,7 +4434,8 @@ interface UploadFile {
|
|
|
3455
4434
|
}
|
|
3456
4435
|
interface UploadRejection {
|
|
3457
4436
|
name: string;
|
|
3458
|
-
|
|
4437
|
+
/** `count`: beyond `max-files` (new in 1.5.0). */
|
|
4438
|
+
reason: "format" | "size" | "count";
|
|
3459
4439
|
message: string;
|
|
3460
4440
|
}
|
|
3461
4441
|
interface UploaderContext {
|
|
@@ -3495,7 +4475,8 @@ interface UploadState {
|
|
|
3495
4475
|
*
|
|
3496
4476
|
* @element rel-upload
|
|
3497
4477
|
* @fires rel-files-added - Fired after files are picked or dropped and validated. Detail: `{ added: UploadFile[], rejected: UploadRejection[] }`.
|
|
3498
|
-
* @fires rel-invalid - Fired just before `rel-files-added` when at least one picked file fails `accept` / `max-size`. Detail: `{ rejected: UploadRejection[] }`.
|
|
4478
|
+
* @fires rel-invalid - Fired just before `rel-files-added` when at least one picked file fails `accept` / `max-size` / `max-files`. Detail: `{ rejected: UploadRejection[] }`.
|
|
4479
|
+
* @fires rel-file-replaced - New in 1.5.0. Fired once per list entry that a newly picked file with the same name replaced (the replace itself is unchanged: names stay unique). The component also announces it and shows an info notice in its alert slot. Detail: `{ name: string, previous: UploadFile, next: UploadFile }`.
|
|
3499
4480
|
* @fires rel-change - Fired whenever the file list changes (files added, a row removed, `reset()`). Detail: `{ files: UploadFile[] }`.
|
|
3500
4481
|
* @fires rel-remove - Fired when a row is removed via its delete button or `removeFile()`. Detail: `{ id: string, file?: File }`.
|
|
3501
4482
|
* @fires rel-upload - Fired when Upload is pressed (or `upload()` is called) with the rows still `ready`; in controlled mode the app performs the transfer. Detail: `{ files: UploadFile[] }`.
|
|
@@ -3504,18 +4485,31 @@ interface UploadState {
|
|
|
3504
4485
|
* @fires rel-progress - Fired on every progress tick in self-driving mode. Detail: `{ id: string, progress: number (0–100), loaded: number, total: number }` (bytes).
|
|
3505
4486
|
* @fires rel-file-complete - Fired when one file finishes uploading in self-driving mode. Detail: `{ id: string, file: File }`.
|
|
3506
4487
|
* @fires rel-file-error - Fired when one file's `uploader` rejects in self-driving mode. Detail: `{ id: string, file: File, error: string }`.
|
|
3507
|
-
* @fires rel-complete - Fired when the whole self-driving batch settles without being cancelled. Detail: `{ succeeded: UploadFile[], failed: UploadFile[] }
|
|
4488
|
+
* @fires rel-complete - Deprecated: use `rel-upload-complete`, which fires once per batch in both modes; removed in 3.0. It still fires as before, and listening for it logs a one-time console warning. Fired when the whole self-driving batch settles without being cancelled. Detail: `{ succeeded: UploadFile[], failed: UploadFile[] }` (every success and error row in the list). Self-driving mode only; `rel-upload-complete` covers both modes.
|
|
4489
|
+
* @fires rel-upload-complete - New in 1.5.0. Fired once per batch when nothing is uploading any more, in BOTH modes: in self-driving mode when the `uploader` calls settle, in controlled mode when the app moves the last `uploading` row it set to `success` or `error`. Not fired after `cancel()`. The component announces the result politely ("3 files uploaded", "2 uploaded, 1 failed"), and when nothing failed it shows a success alert in its alert slot ("3 files uploaded"; the delay warning and the failure alert come first). It shows no toast: listen for this event to show your own (for example a success `rel-toast`). Detail: `{ succeeded: UploadFile[], failed: UploadFile[] }`, the rows of this batch only.
|
|
3508
4490
|
* @fires rel-state - Fired when the derived `state` snapshot changes (and once after connecting). Detail: `UploadState`.
|
|
3509
4491
|
* @cssprop --rel-upload-browse-hover-bg - Background of the Browse button on hover. Defaults to `transparent`, which is what the underlying `rel-button` secondary style draws (Figma's outline button reacts on its border, not its fill), so this only takes effect when you set it.
|
|
3510
4492
|
* @csspart browse - The `rel-button` that opens the file picker (Figma "Browse Button": Size=Medium, Style=Secondary).
|
|
3511
4493
|
*/
|
|
3512
|
-
declare class RelUpload extends
|
|
4494
|
+
declare class RelUpload extends RelElement {
|
|
4495
|
+
/**
|
|
4496
|
+
* `rel-complete` is deprecated (removal in 3.0): adding a listener for it on
|
|
4497
|
+
* the element logs a one-time notice (once per page). Lit `@rel-complete`,
|
|
4498
|
+
* Angular's EventMapper and React 19 all register here. The event itself is
|
|
4499
|
+
* unchanged; listeners on an ancestor that rely on bubbling are not seen.
|
|
4500
|
+
* @internal DOM plumbing, not component API (kept out of the README and the manifest).
|
|
4501
|
+
*/
|
|
4502
|
+
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
4503
|
+
/** @internal */
|
|
4504
|
+
addEventListener(type: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions): void;
|
|
3513
4505
|
/** Comma-separated accept list, e.g. ".pdf,.png,.jpg" or "image/*". */
|
|
3514
4506
|
accept: string;
|
|
3515
4507
|
/** Max size per file as a human string ("10MB", "500kb"). Empty → no limit. */
|
|
3516
4508
|
maxSize: string;
|
|
3517
4509
|
/** Allow more than one file. */
|
|
3518
4510
|
multiple: boolean;
|
|
4511
|
+
/** New in 1.5.0. With `multiple`, the most files the list may hold; `0` (the default) means no limit. Files beyond it become error rows ("only 5 files allowed") and `rel-invalid` rejections with `reason: "count"`. Rows already in the list count first, then new files in selection order; rows rejected by `accept`, `max-size` or the limit hold no place. `retry()` checks the limit again, so removing rows lets a rejected one through. Ignored without `multiple` (one file at a time). */
|
|
4512
|
+
maxFiles: number;
|
|
3519
4513
|
/** Disables the whole control. */
|
|
3520
4514
|
disabled: boolean;
|
|
3521
4515
|
/** Overrides the derived "PDF, PNG or JPG - up to 10 MB per file" hint. */
|
|
@@ -3527,6 +4521,9 @@ declare class RelUpload extends LitElement {
|
|
|
3527
4521
|
/**
|
|
3528
4522
|
* The file list. Set it to drive the component in controlled mode; the
|
|
3529
4523
|
* component also maintains it itself as files are added and removed.
|
|
4524
|
+
* A row whose `file` is an image (`image/*`) shows a 40px preview in place
|
|
4525
|
+
* of the file icon (new in 1.5.0); its object URL is revoked when the row
|
|
4526
|
+
* leaves the list and when the element disconnects.
|
|
3530
4527
|
*/
|
|
3531
4528
|
files: UploadFile[];
|
|
3532
4529
|
/** Supply an `Uploader` `(file, { file, signal, onProgress }) => Promise<void>` to switch to self-driving mode: the component runs the batch itself with `concurrency`, progress, the delay alert, abort and retry. Unset (default) the component only emits intents. */
|
|
@@ -3537,12 +4534,26 @@ declare class RelUpload extends LitElement {
|
|
|
3537
4534
|
delayThreshold: number;
|
|
3538
4535
|
private dragOver;
|
|
3539
4536
|
private delayed;
|
|
4537
|
+
/** Names replaced by the latest pick; drives the info notice. */
|
|
4538
|
+
private replacedNames;
|
|
4539
|
+
/** Files in the last batch when it finished with no failures; drives the success alert. */
|
|
4540
|
+
private uploadedCount;
|
|
4541
|
+
/** Rows whose image preview failed to decode; they show the file icon. */
|
|
4542
|
+
private thumbFailed;
|
|
4543
|
+
/** Object URLs of image previews, by row id. Revoked as soon as the row leaves the list, and on disconnect. */
|
|
4544
|
+
private thumbUrls;
|
|
3540
4545
|
private inputEl;
|
|
3541
4546
|
private aborter?;
|
|
3542
4547
|
private delayTimer?;
|
|
3543
4548
|
private lastSignature;
|
|
3544
4549
|
private lastHeading;
|
|
3545
4550
|
private lastAlertText;
|
|
4551
|
+
/** Rows rejected by `max-files`: they hold no place until `retry()` re-checks them. */
|
|
4552
|
+
private overLimit;
|
|
4553
|
+
private batchIds;
|
|
4554
|
+
private wasUploading;
|
|
4555
|
+
private batchCancelled;
|
|
4556
|
+
private settledBatch?;
|
|
3546
4557
|
static styles: lit.CSSResult;
|
|
3547
4558
|
/**
|
|
3548
4559
|
* Aggregate state. Read-only; corresponds to the Figma modal variants.
|
|
@@ -3560,6 +4571,12 @@ declare class RelUpload extends LitElement {
|
|
|
3560
4571
|
* rather than re-queueing it blindly.
|
|
3561
4572
|
*/
|
|
3562
4573
|
private get retryable();
|
|
4574
|
+
/** The `max-files` limit in force: none without `multiple` or at `0`. */
|
|
4575
|
+
private get fileLimit();
|
|
4576
|
+
/** Whether a row already in the list holds one of the `max-files` places:
|
|
4577
|
+
* any row that is not an error, and failed rows that a retry would send
|
|
4578
|
+
* again (not rejected by `accept`, `max-size` or the limit itself). */
|
|
4579
|
+
private holdsPlace;
|
|
3563
4580
|
/** Whether the primary action is enabled: not disabled, nothing in flight, and either `ready` rows exist or (in the failed phase) at least one failed row can be retried. */
|
|
3564
4581
|
get canUpload(): boolean;
|
|
3565
4582
|
/** Footer button label — "Upload", "Upload 3 files" or "Retry upload". */
|
|
@@ -3606,6 +4623,16 @@ declare class RelUpload extends LitElement {
|
|
|
3606
4623
|
private onDrop;
|
|
3607
4624
|
connectedCallback(): void;
|
|
3608
4625
|
disconnectedCallback(): void;
|
|
4626
|
+
/** Revoke the previews of rows no longer in `files`. */
|
|
4627
|
+
private pruneThumbs;
|
|
4628
|
+
/** An object URL for an image row's preview, created once per row. */
|
|
4629
|
+
private thumbUrl;
|
|
4630
|
+
/** A preview that cannot be decoded falls back to the file icon. */
|
|
4631
|
+
private onThumbError;
|
|
4632
|
+
/** Batch tracking for `rel-upload-complete`, from the `files` the update
|
|
4633
|
+
* renders. Self-driving (`patch()`) and controlled (the app writes
|
|
4634
|
+
* `files`) both end here, so one rule serves both modes. */
|
|
4635
|
+
willUpdate(changed: Map<PropertyKey, unknown>): void;
|
|
3609
4636
|
updated(): void;
|
|
3610
4637
|
private rowMeta;
|
|
3611
4638
|
private renderRow;
|
|
@@ -3640,7 +4667,7 @@ declare global {
|
|
|
3640
4667
|
* @csspart cancel - The secondary Cancel `rel-button` (absent when `no-cancel` is set)
|
|
3641
4668
|
* @csspart primary - The primary Upload / Retry `rel-button`
|
|
3642
4669
|
*/
|
|
3643
|
-
declare class RelUploadActions extends
|
|
4670
|
+
declare class RelUploadActions extends RelElement {
|
|
3644
4671
|
/** Id of the `<rel-upload>` to control. Omit to auto-discover a sibling. */
|
|
3645
4672
|
for: string;
|
|
3646
4673
|
/** Cancel button label. */
|
|
@@ -3712,6 +4739,7 @@ declare class FocusTrap {
|
|
|
3712
4739
|
private getContainer;
|
|
3713
4740
|
private previousFocus;
|
|
3714
4741
|
private active;
|
|
4742
|
+
private generation;
|
|
3715
4743
|
constructor(getContainer: () => Element | ShadowRoot | null);
|
|
3716
4744
|
activate(options?: {
|
|
3717
4745
|
initialFocus?: HTMLElement | null;
|
|
@@ -3770,6 +4798,69 @@ declare function bindShortcut(shortcut: string, handler: ShortcutHandler, option
|
|
|
3770
4798
|
*/
|
|
3771
4799
|
declare function formatShortcutParts(shortcut: string): string[];
|
|
3772
4800
|
|
|
4801
|
+
/**
|
|
4802
|
+
* New in 1.5.0. Keyboard navigation for a two-dimensional grid of cells
|
|
4803
|
+
* (WAI-ARIA Grid pattern, data grid flavour), framework-free so that plain-JS
|
|
4804
|
+
* recipes can use it as well as components.
|
|
4805
|
+
*
|
|
4806
|
+
* - Roving tabindex: exactly one cell has `tabindex="0"`; a click or any other
|
|
4807
|
+
* focus on a cell moves the Tab stop there.
|
|
4808
|
+
* - Arrows move one cell (Left / Right swap in a right-to-left grid); Home / End
|
|
4809
|
+
* go to the row's first / last cell; Ctrl+Home / Ctrl+End (Cmd on a Mac) to the
|
|
4810
|
+
* grid's first / last cell; PageUp / PageDown move `pageSize` rows when set.
|
|
4811
|
+
* - Enter, Space and a click activate a cell (`onActivate`), except a disabled
|
|
4812
|
+
* one (`aria-disabled="true"`).
|
|
4813
|
+
*
|
|
4814
|
+
* Only the keys it handles are prevented. The grid's rows and cells are re-read
|
|
4815
|
+
* by `refresh()`: call it after re-rendering them.
|
|
4816
|
+
*
|
|
4817
|
+
* ```js
|
|
4818
|
+
* import { createGridNavigation } from "@reliability-design/web";
|
|
4819
|
+
* const nav = createGridNavigation(document.querySelector('[role="grid"]'), {
|
|
4820
|
+
* onActivate(cell, pos) { select(pos.row, pos.col) },
|
|
4821
|
+
* });
|
|
4822
|
+
* ```
|
|
4823
|
+
*/
|
|
4824
|
+
/** A cell's place in the grid: zero-based row and column. */
|
|
4825
|
+
interface GridPosition {
|
|
4826
|
+
row: number;
|
|
4827
|
+
col: number;
|
|
4828
|
+
}
|
|
4829
|
+
interface GridNavigationOptions {
|
|
4830
|
+
/** Selector for the rows, inside the grid. Rows give the grid its shape. Default `'[role="row"]'`. */
|
|
4831
|
+
rowSelector?: string;
|
|
4832
|
+
/** Selector for the cells, inside a row, in DOM order. Default `'[role="gridcell"]'`. Rows with no cells (a header row of `columnheader`s) are not part of the grid. */
|
|
4833
|
+
cellSelector?: string;
|
|
4834
|
+
/** A disabled cell (`aria-disabled="true"`): `"focus"` (default) keeps it reachable, as the WAI-ARIA grid pattern does, but it does not activate; `"skip"` jumps over it. */
|
|
4835
|
+
disabledCells?: "focus" | "skip";
|
|
4836
|
+
/** Arrows past an edge continue at the opposite edge of the same row or column. Default `false`: they stop at the edge. */
|
|
4837
|
+
wrap?: boolean;
|
|
4838
|
+
/** PageUp / PageDown move this many rows (clamped to the grid). Unset: the Page keys are not handled. */
|
|
4839
|
+
pageSize?: number;
|
|
4840
|
+
/** `"auto"` (default) reads the grid's computed `direction` on every key, so Left / Right follow a right-to-left layout. */
|
|
4841
|
+
direction?: "auto" | "ltr" | "rtl";
|
|
4842
|
+
/** Enter, Space or a click on a cell that is not disabled. */
|
|
4843
|
+
onActivate?(cell: HTMLElement, pos: GridPosition, event: KeyboardEvent | MouseEvent): void;
|
|
4844
|
+
/** After a key moved the focus to `cell`. */
|
|
4845
|
+
onMove?(cell: HTMLElement, pos: GridPosition, event: KeyboardEvent): void;
|
|
4846
|
+
/** A custom key map, consulted first: return the target position, `null` to leave the key unhandled, or `undefined` to use the default map. */
|
|
4847
|
+
resolve?(key: string, pos: GridPosition, event: KeyboardEvent): GridPosition | null | undefined;
|
|
4848
|
+
}
|
|
4849
|
+
interface GridNavigation {
|
|
4850
|
+
/** The cell that holds the Tab stop, or `null` while the grid has no cells. */
|
|
4851
|
+
readonly active: GridPosition | null;
|
|
4852
|
+
/** Moves the Tab stop to `pos` (clamped to the grid) and focuses it, unless `focus: false`. */
|
|
4853
|
+
focusCell(pos: GridPosition, opts?: {
|
|
4854
|
+
focus?: boolean;
|
|
4855
|
+
}): void;
|
|
4856
|
+
/** Re-reads the rows and cells after a re-render; the Tab stop keeps its position, clamped. */
|
|
4857
|
+
refresh(): void;
|
|
4858
|
+
/** Removes the listeners. The cells keep their tabindex. */
|
|
4859
|
+
destroy(): void;
|
|
4860
|
+
}
|
|
4861
|
+
/** New in 1.5.0. Adds grid keyboard navigation and a roving Tab stop to `grid`. See the module comment. */
|
|
4862
|
+
declare function createGridNavigation(grid: HTMLElement, options?: GridNavigationOptions): GridNavigation;
|
|
4863
|
+
|
|
3773
4864
|
/**
|
|
3774
4865
|
* Shared screen-reader announcer.
|
|
3775
4866
|
*
|
|
@@ -3791,4 +4882,4 @@ type Politeness = "polite" | "assertive";
|
|
|
3791
4882
|
*/
|
|
3792
4883
|
declare function announce(message: string, politeness?: Politeness): void;
|
|
3793
4884
|
|
|
3794
|
-
export { type AlertTone, type AlertToneAlias, type AlertToneInput, type AutocompleteFilter, type AutocompleteItem, type AutocompleteSearchFn, type AvatarSize, type AvatarSizeAlias, type AvatarSizeInput, type BadgeSize, type BadgeSizeAlias, type BadgeSizeInput, type BindShortcutOptions, type BreadcrumbItem, type ButtonTone, type ButtonVariant, type ChipBorder, type ChipSize, type ChipSizeAlias, type ChipSizeInput, type ChipTone, type ChipToneAlias, type ChipToneInput, type ChipVariant, type ChipVariantAlias, type ChipVariantInput, type ContainerBackground, type ContainerPadding, type ContainerPaddingAlias, type ContainerPaddingInput, type ContainerSurface, type DrawerCloseReason, type DrawerSide, type FieldLabelStyle, FocusTrap, type KbdSize, type LabelPlacement, type MenuItem, type MenuSize, type MenuType, type MenuWidth, type MenubarType, type ModalSide, type ModalSize, type ModalSizeAlias, type ModalSizeInput, type ModalVariant, type Orientation, type OtpInputMode, type OtpSize, type OtpType, type PopoverContentSize, type PopoverContentSizeAlias, type PopoverContentSizeInput, type ProgressMode, type RadioOption, type RadioSize, type RadioSizeAlias, type RadioSizeInput, type RangePickerSize, type RangePickerSizeAlias, type RangePickerSizeInput, RelAccordion, RelAlert, RelAutocomplete, RelAvatar, RelBadge, RelBreadcrumbs, RelButton, RelCalendar, RelCard, RelCardMedia, RelCarousel, RelCheckbox, RelChip, RelContainer, RelDatePicker, RelDivider, RelDrawer, RelDrawerFooter, RelKbd, RelKbdGroup, RelLayout, RelMenu, RelMenuItem, RelMenubar, RelMenubarMenu, RelModal, RelOtp, RelPagination, RelPopover, RelPopoverContent, RelProgress, RelRadio, RelRangePicker, RelResizableGroup, RelResizableHandle, RelResizablePanel, RelSegmentedButton, RelSelect, RelSkeleton, RelSlider, RelSnackbar, RelStepper, RelSwitch, RelTab, RelTabItem, RelTextfield, RelTimePicker, RelToast, RelTooltip, RelUpload, RelUploadActions, type SegmentAlign, type SegmentOption, type SegmentSize, type SelectBorder, type SelectLabelStyle, type SelectOption, type SelectOptionObject, type SelectSize, type SelectState, type ShortcutHandler, type SkeletonAnimation, type SkeletonShape, type SliderSize, type SliderSizeAlias, type SliderSizeInput, type SliderType, type SnackbarLines, type SnackbarTone, type SnackbarToneAlias, type SnackbarToneInput, type SnackbarType, type SnackbarVariant, type Step, type StepStatus, type StepperSize, type StepperType, type SwitchLabelPlacement, type SwitchSize, type SwitchSizeAlias, type SwitchSizeInput, type TabItem, type TabSize, type TextAlign, type TextFieldPrefixStyle, type TextFieldSize, type TextFieldState, type TextFieldVariant, type ToastPosition, type ToastSize, type ToastSizeAlias, type ToastSizeInput, type ToastTone, type ToastToneAlias, type ToastToneInput, type ToastType, type TooltipPosition, type TooltipTone, type TooltipType, type TrackStyle, type UploadFile, type UploadPhase, type UploadRejection, type UploadState, type UploadStatus, type Uploader, type UploaderContext, announce, bindShortcut, formatShortcutParts, getDeepActiveElement, getFocusableElements, isApplePlatform, isEditableTarget, matchesShortcut, parseShortcut, trapTabKey };
|
|
4885
|
+
export { type AlertTone, type AlertToneAlias, type AlertToneInput, type AutocompleteFilter, type AutocompleteItem, type AutocompleteSearchFn, type AvatarBadge, type AvatarSize, type AvatarSizeAlias, type AvatarSizeInput, type BadgeSize, type BadgeSizeAlias, type BadgeSizeInput, type BindShortcutOptions, type BreadcrumbItem, type ButtonTone, type ButtonVariant, type ChipBorder, type ChipSize, type ChipSizeAlias, type ChipSizeInput, type ChipTone, type ChipToneAlias, type ChipToneInput, type ChipVariant, type ChipVariantAlias, type ChipVariantInput, type ContainerBackground, type ContainerPadding, type ContainerPaddingAlias, type ContainerPaddingInput, type ContainerSurface, type DrawerCloseReason, type DrawerSide, type FieldLabelStyle, FocusTrap, type GridNavigation, type GridNavigationOptions, type GridPosition, type KbdPlatform, type KbdSize, type LabelPlacement, type MenuItem, type MenuSize, type MenuType, type MenuWidth, type MenubarType, type ModalSide, type ModalSize, type ModalSizeAlias, type ModalSizeInput, type ModalVariant, type Orientation, type OtpInputMode, type OtpSize, type OtpType, type PaginationType, type PopoverContentSize, type PopoverContentSizeAlias, type PopoverContentSizeInput, type ProgressMode, type RadioOption, type RadioSize, type RadioSizeAlias, type RadioSizeInput, type RangePickerSize, type RangePickerSizeAlias, type RangePickerSizeInput, RelAccordion, RelAlert, RelAutocomplete, RelAvatar, RelAvatarGroup, RelBadge, RelBreadcrumbs, RelButton, RelCalendar, RelCard, RelCardMedia, RelCarousel, RelCheckbox, RelChip, RelContainer, RelDatePicker, RelDivider, RelDrawer, RelDrawerFooter, RelKbd, RelKbdGroup, RelLayout, RelMenu, RelMenuItem, RelMenubar, RelMenubarMenu, RelModal, RelOtp, RelPagination, RelPopover, RelPopoverContent, RelProgress, RelRadio, RelRangePicker, RelResizableGroup, RelResizableHandle, RelResizablePanel, RelSegmentedButton, RelSelect, RelSignaturePad, RelSkeleton, RelSlider, RelSnackbar, RelSplitButton, RelStepper, RelSwitch, RelTab, RelTabItem, RelTextfield, RelTimePicker, RelToast, RelTooltip, RelTree, RelUpload, RelUploadActions, type SegmentAlign, type SegmentOption, type SegmentSize, type SelectBorder, type SelectLabelStyle, type SelectOption, type SelectOptionObject, type SelectSize, type SelectState, type ShortcutHandler, type SignaturePadChangeDetail, type SignaturePadMode, type SignaturePoint, type SignatureStroke, type SkeletonAnimation, type SkeletonShape, type SliderSize, type SliderSizeAlias, type SliderSizeInput, type SliderType, type SnackbarLines, type SnackbarTone, type SnackbarToneAlias, type SnackbarToneInput, type SnackbarType, type SnackbarVariant, type SplitButtonItem, type SplitButtonSize, type SplitButtonTone, type SplitButtonVariant, type Step, type StepStatus, type StepperConnector, type StepperSize, type StepperType, type SwitchLabelPlacement, type SwitchSize, type SwitchSizeAlias, type SwitchSizeInput, type TabIconPlacement, type TabItem, type TabOrientation, type TabSize, type TextAlign, type TextFieldPrefixStyle, type TextFieldSize, type TextFieldState, type TextFieldVariant, type ToastPosition, type ToastSize, type ToastSizeAlias, type ToastSizeInput, type ToastTone, type ToastToneAlias, type ToastToneInput, type ToastType, type TooltipPosition, type TooltipTone, type TooltipType, type TrackStyle, type TreeItem, type TreeSelection, type UploadFile, type UploadPhase, type UploadRejection, type UploadState, type UploadStatus, type Uploader, type UploaderContext, announce, bindShortcut, createGridNavigation, detectKbdPlatform, formatShortcutParts, getDeepActiveElement, getFocusableElements, isApplePlatform, isEditableTarget, matchesShortcut, parseShortcut, resolveKbdKey, trapTabKey };
|