@raylang/elements 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/llms-full.txt ADDED
@@ -0,0 +1,3808 @@
1
+ # ray-elements
2
+
3
+ > Web components (custom elements, Shadow DOM, no dependencies) for any web app: plain HTML, React, Vue or a raylang app. npm: `@raylang/elements`, `@raylang/react`, `@raylang/vue`; raylang: the `elements` package. This file describes version 0.5.2.
4
+
5
+ ray-elements is a design system of standard web components (custom elements
6
+ with Shadow DOM, no dependencies): `<ray-button>`, `<ray-input>`,
7
+ `<ray-dialog>`… They work in plain HTML, React, Vue, a browser or any webview,
8
+ and get extras in a raylang app (a native bridge to the program). The rules
9
+ below are what this library does differently from what you may assume; the
10
+ reference of every component follows them.
11
+
12
+ ## Load it
13
+
14
+ ```html
15
+ <link rel="stylesheet" href="node_modules/@raylang/elements/tokens.css"> <!-- required: the components read the tokens -->
16
+ <link rel="stylesheet" href="node_modules/@raylang/elements/base.css"> <!-- optional: font, colors and margins of the document -->
17
+ <script type="module">
18
+ import "@raylang/elements"; // registers EVERY <ray-*> element and exports the whole API
19
+ </script>
20
+ ```
21
+
22
+ - The bare name (`"@raylang/elements"`) resolves with a bundler (Vite,
23
+ esbuild…) and in a raylang app (raylang serves the package with an import
24
+ map). A plain page without either imports the files:
25
+ `import { notify } from "./node_modules/@raylang/elements/index.js";`
26
+ (everything), `./node_modules/@raylang/elements/components/<name>/<name>.js`
27
+ (one component), `./node_modules/@raylang/elements/core.js` (the API), or
28
+ declares an import map:
29
+ `<script type="importmap">{ "imports": { "@raylang/elements": "./node_modules/@raylang/elements/index.js" } }</script>`.
30
+
31
+ - `npm install @raylang/elements` (React: also `@raylang/react`; Vue: also
32
+ `@raylang/vue`). With a bundler: `import "@raylang/elements/tokens.css";`.
33
+ - Only some components: `import "@raylang/elements/button";` — one entry per
34
+ component directory (the "Import" line of each component below). Each brings
35
+ what it uses. `import { notify } from "@raylang/elements/notification";` gets
36
+ a component's exports with it.
37
+ - The API without registering any element: `import { setTheme } from
38
+ "@raylang/elements/core";`. Note that `import { RayButton } from
39
+ "@raylang/elements"` loads everything (that entry registers every element).
40
+ - Avoid a flash of unstyled tags: `<style>:not(:defined) { visibility: hidden; }</style>`.
41
+
42
+ ## Rules
43
+
44
+ - **Attributes are kebab-case, properties camelCase**: `full-width` /
45
+ `fullWidth`. Boolean attributes are present or absent (`disabled`, never
46
+ `disabled="false"`). Properties marked "property only" have no attribute:
47
+ set them from JS (arrays, objects, functions). The exception is `checked`
48
+ and `value` on form controls: their attribute is the initial state (see
49
+ Forms).
50
+ - **Shared vocabulary**: `size` = `xs` | `sm` | `md` | `lg` | `xl` (default
51
+ `sm`); `radius` = `xs`…`xl` | `full`; `color` = a palette color (`blue`,
52
+ `red`, `teal`, `gray`…) or any CSS color, default the primary; `variant` per
53
+ component (button: `filled`, `light`, `outline`, `subtle`, `default`,
54
+ `transparent`, `gradient`, `raised`). Use only the values the reference lists.
55
+ - **Slots have exact names**: an icon in a button goes in `slot="left"` or
56
+ `slot="right"` (not `start`/`end`, not `prefix`): `<ray-button><ray-icon
57
+ slot="left" name="plus"></ray-icon>Add</ray-button>`. Content without a
58
+ `slot` goes to the default slot. Check the slot list of the component.
59
+ - **Never hard-code colors, spacing, radii or shadows** in your own CSS: use
60
+ the tokens (`var(--ray-background)`, `var(--ray-foreground)`,
61
+ `var(--ray-border)`, `var(--ray-space-md)`, `var(--ray-radius-default)`,
62
+ `var(--ray-shadow-sm)`). They follow light and dark themes; literal colors do
63
+ not. Prefer the semantic tokens over the palette (`--ray-blue-6`).
64
+ - **Style components from outside** with `color`/`variant`/`size`/`radius`,
65
+ the tokens (custom properties pierce the shadow root) and `::part()` (the
66
+ parts each lists). Do not reach into their
67
+ `shadowRoot` or depend on its markup.
68
+ - **Layout components exist**: `ray-stack` (vertical), `ray-group`
69
+ (horizontal), `ray-grid`, `ray-container`, `ray-center`, `ray-card`
70
+ (a heading of your own in its `header` slot), `ray-app-shell`. Their
71
+ `gap`/`padding` take `xs`…`xl`.
72
+ - **Icons**: `<ray-icon name="settings"></ray-icon>`, from the registry (a
73
+ small set, listed in the reference: there is no `save` or `trash`); decorative unless it has `label`. An icon-only button is
74
+ `<ray-icon-button label="Settings"><ray-icon name="settings"></ray-icon></ray-icon-button>`
75
+ (`label` is required: it is the accessible name). Add or replace icons with
76
+ `setIcons({ inbox: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">…</svg>' })`
77
+ (the style of the built-in set: 24×24, a 2px `currentColor` stroke) from
78
+ your own code, never from user input.
79
+ - **Overlays are in the top layer**: `ray-dialog` is a native modal
80
+ `<dialog>`; popovers, menus, tooltips and notifications are `[popover]`
81
+ elements. Never fight them with `z-index` or `overflow`.
82
+
83
+ ## An app's frame
84
+
85
+ ```html
86
+ <ray-app-shell>
87
+ <ray-app-bar slot="header" label="Files" description="No folder chosen">
88
+ <ray-button slot="end" variant="default" size="xs">Commands</ray-button>
89
+ <ray-theme-toggle slot="end"></ray-theme-toggle>
90
+ </ray-app-bar>
91
+ <ray-sidebar slot="navbar" label="Workspace">
92
+ <ray-nav-link label="Files" href="#files" active><ray-icon slot="left" name="folder"></ray-icon></ray-nav-link>
93
+ <ray-nav-link label="Settings" href="#settings"><ray-icon slot="left" name="settings"></ray-icon></ray-nav-link>
94
+ </ray-sidebar>
95
+ <main>…</main>
96
+ </ray-app-shell>
97
+ ```
98
+
99
+ `ray-app-bar` is the header on the desktop too (its `label` is the title;
100
+ several elements may share the `end` slot). On narrow screens the sidebar
101
+ becomes a drawer and the shell switches to a phone layout by itself.
102
+
103
+ ## Forms
104
+
105
+ - Inputs are **form-associated**: inside a `<form>` they submit under `name`,
106
+ validate (`required`, `pattern`, `min`…), reset with it and follow a
107
+ disabled `<fieldset>`. Read values with `new FormData(form)` or the
108
+ element's `.value` / `.checked`.
109
+ - The `value` / `checked` **attributes are the initial value**; the
110
+ properties hold the current one. Set `el.value = …` to change it.
111
+ - Fields take `label`, `description` and `error` (the error text also marks it
112
+ invalid): do not wrap them in your own `<label>`.
113
+ - Enter in a `ray-input` submits its form, as in a native field; a submit
114
+ button is `<ray-button type="submit">`.
115
+ - As with native controls: an invalid field (`required` and empty, a wrong
116
+ `type="email"`…) blocks the submit and the browser shows its message; an
117
+ unchecked `ray-checkbox`/`ray-switch` and a `ray-select` with nothing chosen
118
+ are left out of `FormData` (a select's `placeholder` shows meanwhile).
119
+
120
+ ## Events
121
+
122
+ - A value change is a plain `input` (while typing) and `change` event: read
123
+ `event.target.value`.
124
+ - Everything else is a `ray-*` custom event (bubbles, composed) with its data
125
+ in `event.detail`: `ray-select` on a menu (`detail.value`), `ray-close` on a
126
+ dialog (`detail.returnValue`), `ray-request-close` (cancelable). The
127
+ reference lists each component's events and their `detail`.
128
+
129
+ ## Dialogs and notifications
130
+
131
+ ```html
132
+ <ray-dialog id="d" label="Rename">
133
+ <ray-input label="Name" name="name"></ray-input>
134
+ <ray-button slot="footer" variant="default" data-dialog-close>Cancel</ray-button>
135
+ <ray-button slot="footer" data-dialog-close="ok">Save</ray-button>
136
+ </ray-dialog>
137
+ ```
138
+
139
+ `d.show()` or the `open` attribute opens it; any slotted element with
140
+ `data-dialog-close` closes it (its value becomes `returnValue`); the close
141
+ button, Escape and the backdrop close it with `returnValue` `""` (after a
142
+ cancelable `ray-request-close`).
143
+ `await confirmDialog({ label, message, confirmLabel, cancelLabel, color: "red" })`
144
+ asks a yes/no question (every option is optional: "Are you sure?",
145
+ "Confirm", "Cancel"); `notify({ title, message, color })` shows a
146
+ notification (`message` is plain text; a `color` adds a status icon:
147
+ green a check, red an error, yellow a warning, others info).
148
+
149
+ ## Theme
150
+
151
+ - The theme follows the system. Force it on the page or any subtree with
152
+ `data-theme="light"` | `"dark"`; change the primary color with
153
+ `data-primary="violet"` (a palette color).
154
+ - From JS: `setTheme("light" | "dark" | "system")`, `setPrimary("violet")`,
155
+ `definePrimary("#7c3aed")` (any brand color: builds the ten shades and
156
+ checks contrast), `onThemeChange(cb)`. `<ray-theme-toggle>` is the switch.
157
+ - App-wide defaults for a component: `configure({ defaults: { "ray-button":
158
+ { variant: "light" } } })`.
159
+
160
+ ## React and Vue
161
+
162
+ ```tsx
163
+ import "@raylang/elements/tokens.css";
164
+ import { RayInput, RayMenu, RayMenuItem, RayButton } from "@raylang/react";
165
+
166
+ <RayInput label="Name" value={name} onInput={(e) => setName(e.currentTarget.value)} />
167
+ <RayMenu onRaySelect={(e) => run(e.detail.value)}>
168
+ <RayButton slot="trigger">Actions</RayButton>
169
+ <RayMenuItem value="rename">Rename</RayMenuItem>
170
+ </RayMenu>
171
+ ```
172
+
173
+ ```vue
174
+ <!-- main.ts: import RayElements from "@raylang/vue"; app.use(RayElements) -->
175
+ <RayInput v-model="name" label="Name" required />
176
+ <RayDialog v-model="open" label="Confirm" @ray-close="onClose">…</RayDialog>
177
+ ```
178
+
179
+ - The wrapper of `<ray-tag-name>` is `RayTagName`. React events are `on` +
180
+ PascalCase of the event (`onRaySelect`, `onChange`); props are set as DOM
181
+ properties. Vue has `v-model` where the reference lists a model (`value`,
182
+ `checked` or `open`).
183
+ - A wrapper registers only its own element: a plain `<ray-*>` tag in JSX
184
+ needs its import (`import "@raylang/elements/badge"`).
185
+
186
+ ## In a raylang app
187
+
188
+ `ray add elements` brings the raylang package `elements`: it serves
189
+ `@raylang/elements` to the app's pages by its npm name, with no npm and no
190
+ build step. The page:
191
+
192
+ ```html
193
+ <link rel="stylesheet" href="/node_modules/@raylang/elements/tokens.css">
194
+ <script type="module">
195
+ import { enableRaylang } from "@raylang/elements";
196
+ const host = await enableRaylang(); // the native host, or null in a browser
197
+ </script>
198
+ ```
199
+
200
+ The program serves the page and answers the bridge before its own events:
201
+
202
+ ```ray
203
+ import std/ui;
204
+ import elements/bridge;
205
+
206
+ fn main() -> int {
207
+ match (run()) {
208
+ Result.Ok(code) => code,
209
+ Result.Err(e) => {
210
+ eprint(e);
211
+ 1
212
+ },
213
+ }
214
+ }
215
+
216
+ fn run() -> Result<int, string> {
217
+ ui.mount_embed_at("", "assets")?; // the page: assets/index.html, ray.toml [native] embed = ["assets"]
218
+ ui.open_with("App", "ray://app/index.html", ui.options(800, 600))?;
219
+ while (true) {
220
+ let e = ui.next_event()?;
221
+ if (bridge.handle(e)) {
222
+ continue; // a ray-elements request, already answered
223
+ }
224
+ if (e.kind == "closed") {
225
+ return Result.Ok(0);
226
+ }
227
+ // the app's own events: e.kind == "message" (window.ray.send), e.tag…
228
+ }
229
+ }
230
+ ```
231
+
232
+ With the bridge: `<ray-file-upload native>` and `<ray-path-input>` use the
233
+ system file dialogs and give real paths, `confirmDialog()` asks with the
234
+ system dialog, `<ray-menu native>` opens a native context menu,
235
+ `<ray-command-palette native-menus>` runs the app's menu bar
236
+ (`bridge.menu`, `bridge.route`), `ray-app-shell` becomes the title bar of a
237
+ `full_content` window, and `trackEdits(form)` shows the unsaved mark. The
238
+ components that use it have an "In a raylang app" section. Without the
239
+ bridge every component keeps its web behavior.
240
+
241
+ ## Check your markup
242
+
243
+ The package checks markup against this version:
244
+ `npx ray-elements check src/` (with npm), or
245
+ `node node_modules/@raylang/elements/check/cli.js check assets/` (a raylang
246
+ app). It reports unknown elements, attributes, slots and `ray-*` events,
247
+ invalid values, unregistered icons and literal colors, with the line and a
248
+ suggestion, and exits with 1 on an error. Run it after writing a page and fix
249
+ what it reports; `--format json` gives the diagnostics as JSON.
250
+
251
+ ## Your own components
252
+
253
+ Extend `RayElement`, `FormControl`, `FieldControl` or `Floating` (or any
254
+ component class) from `@raylang/elements/core`; see the Extending guide.
255
+ Members whose name starts with `_` are internal.
256
+
257
+ ## Components
258
+
259
+ ### Base classes
260
+
261
+ Properties the components inherit from the base classes (each component lists which it extends):
262
+
263
+ FieldControl (extends FormControl):
264
+
265
+ - `name`: string. Form field name.
266
+ - `label`: string. Visible label (also the accessible name).
267
+ - `description`: string. Help text.
268
+ - `error`: string. Error text; marks the field invalid.
269
+ - `required`: boolean, reflects. Required for form submission.
270
+ - `disabled`: boolean, reflects. Not interactive nor submitted.
271
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Size.
272
+ - `radius`: `xs` | `sm` | `md` | `lg` | `xl` | `full`, reflects. Corner radius.
273
+ - `variant`: `default` | `filled` | `unstyled`, default `default`, reflects. Box style.
274
+ - `descriptionPosition` (attribute `description-position`): `above` | `below`, default `above`, reflects. Description before or after the control.
275
+
276
+ Floating (extends RayElement):
277
+
278
+ - `open`: boolean, reflects. Shown.
279
+ - `placement`: string, default `bottom`, reflects. Preferred side and alignment.
280
+ - `offset`: number, default `8`. Gap to the anchor in px.
281
+
282
+ ### Button
283
+
284
+ A button, or a link styled as one with href. Submits or resets its form with type.
285
+
286
+ Import: `import "@raylang/elements/button";` · Category: Buttons
287
+
288
+ #### `<ray-button>` (RayButton, extends RayElement)
289
+
290
+ Properties:
291
+
292
+ - `variant`: `filled` | `light` | `outline` | `subtle` | `default` | `transparent` | `gradient` | `raised`, default `filled`, reflects. Visual style. raised: a physical key on a darker edge that sinks when pressed (mouse, touch or keyboard).
293
+ - `gradient`: string, reflects. With variant=gradient: "from to [deg]", palette colors or CSS colors ("teal blue 90"). Default: the --ray-gradient-* tokens.
294
+ - `color`: string. A palette color (blue, red…) or any CSS color. Default: the primary color.
295
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Height, padding and font size.
296
+ - `radius`: `xs` | `sm` | `md` | `lg` | `xl` | `full`. Corner radius. Default: --ray-radius-default.
297
+ - `type`: `button` | `submit` | `reset`, default `button`. submit/reset act on the enclosing form.
298
+ - `disabled`: boolean. Not interactive (also when inside a disabled fieldset).
299
+ - `loading`: boolean. Shows a spinner over the content and blocks clicks.
300
+ - `fullWidth` (attribute `full-width`): boolean. Takes the whole width of its container.
301
+ - `href`: string. Renders a link instead of a button.
302
+ - `target`: string. Link target, with href.
303
+ - `name`: string. With type=submit: submitted as name=value.
304
+ - `value`: string. With type=submit: the submitted value.
305
+
306
+ Slots:
307
+
308
+ - (default): The label.
309
+ - `left`: Icon or content before the label.
310
+ - `right`: Icon or content after the label.
311
+
312
+ Parts (`::part()`):
313
+
314
+ - `button`: The inner <button> or <a>.
315
+ - `label`: The label wrapper.
316
+
317
+ Methods and properties:
318
+
319
+ - `readonly form: HTMLFormElement | null`: The form a submit/reset button acts on.
320
+
321
+ ### Button group
322
+
323
+ Buttons joined into one control: inner corners squared, borders overlapped. Works with ray-button, ray-icon-button, menus with a button trigger and fields (ray-input, ray-select, ray-search).
324
+
325
+ Import: `import "@raylang/elements/button-group";` · Category: Buttons
326
+
327
+ #### `<ray-button-group>` (RayButtonGroup, extends RayElement)
328
+
329
+ role=group; give it a label. The corners come from the --ray-group-radius-* custom properties, which your own components can read too.
330
+
331
+ Properties:
332
+
333
+ - `orientation`: `horizontal` | `vertical`, default `horizontal`, reflects. Direction of the group.
334
+ - `fullWidth` (attribute `full-width`): boolean, reflects. Fills its container; the children share the width.
335
+ - `label`: string. Accessible name (aria-label).
336
+
337
+ Slots:
338
+
339
+ - (default): The buttons, fields or menus to join.
340
+
341
+ ### Icon button
342
+
343
+ A square button for an icon (Mantine's ActionIcon). Always give it a label.
344
+
345
+ Import: `import "@raylang/elements/icon-button";` · Category: Buttons
346
+
347
+ #### `<ray-icon-button>` (RayIconButton, extends RayButton)
348
+
349
+ Same properties as ray-button; variant defaults to subtle.
350
+
351
+ Properties:
352
+
353
+ - `label`: string, reflects. Accessible name and tooltip (required: the button has no text).
354
+ - `variant`: `filled` | `light` | `outline` | `subtle` | `default` | `transparent` | `gradient` | `raised`, default `subtle`, reflects. Visual style.
355
+ - `gradient`: string, reflects. With variant=gradient: "from to [deg]", palette colors or CSS colors ("teal blue 90"). Default: the --ray-gradient-* tokens.
356
+ - `color`: string. A palette color or any CSS color.
357
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Width and height.
358
+ - `disabled`: boolean. Not interactive.
359
+ - `loading`: boolean. Shows a spinner instead of the icon.
360
+
361
+ Also the properties of RayButton (`<ray-button>`): `radius`, `type`, `fullWidth`, `href`, `target`, `name`, `value`.
362
+
363
+ Slots:
364
+
365
+ - (default): The icon (an inline <svg> is sized to the button).
366
+
367
+ Parts (`::part()`):
368
+
369
+ - `button`: The inner button.
370
+
371
+ ### Toggle
372
+
373
+ A two-state button (aria-pressed): bold in a toolbar, mute, favorite. The variant is how "on" looks; "off" is always neutral, so the states differ by more than color. Has everything ray-button has and joins a ray-button-group.
374
+
375
+ Import: `import "@raylang/elements/toggle";` · Category: Buttons
376
+
377
+ #### `<ray-toggle>` (RayToggle, extends RayButton)
378
+
379
+ Click, Enter or Space flips pressed and fires change. In a form it is submitted like a checkbox: value (default "on") under name while pressed; reset restores the initial pressed attribute.
380
+
381
+ Properties:
382
+
383
+ - `pressed`: boolean, reflects. On.
384
+ - `variant`: `subtle` | `outline` | `light` | `filled` | `raised`, default `subtle`, reflects. Look of "on": subtle (tint), outline (colored border + tint), light (muted → tint), filled (surface → solid color), raised (a key that latches down, lit). ray-button's default, transparent and gradient are left out: no distinct on state, or only a color change.
385
+ - `square`: boolean, reflects. Square, for an icon alone (give it a label).
386
+ - `label`: string, reflects. Accessible name and tooltip, for icon-only toggles.
387
+
388
+ Also the properties of RayButton (`<ray-button>`): `gradient`, `color`, `size`, `radius`, `type`, `disabled`, `loading`, `fullWidth`, `href`, `target`, `name`, `value`.
389
+
390
+ Events:
391
+
392
+ - `change`: The user flipped it (read `pressed`).
393
+
394
+ Slots:
395
+
396
+ - (default): Text or an icon.
397
+
398
+ ### Toggle group
399
+
400
+ ray-toggle elements with one shared value: type="single" (at most one on: alignment, view mode) or "multiple" (bold / italic / underline). Joined like a button group, or spaced; arrow keys move between toggles; submitted with its form.
401
+
402
+ Import: `import "@raylang/elements/toggle-group";` · Category: Buttons
403
+
404
+ #### `<ray-toggle-group>` (RayToggleGroup, extends RayButtonGroup)
405
+
406
+ Each toggle's value (else its text) is its key. variant, color, size, radius and square reach the toggles that do not set their own. One tab stop (the selected toggle); arrows, Home and End move; Space/Enter flips.
407
+
408
+ Properties:
409
+
410
+ - `type`: `single` | `multiple`, default `single`, reflects. single: choosing one turns the others off; multiple: each toggle is independent.
411
+ - `value`: `string | string[] | undefined`. The selected key (single) or keys (multiple: an array, or a comma-separated attribute).
412
+ - `name`: string, reflects. Form field name: the value (multiple: one entry per key).
413
+ - `required`: boolean, reflects. Needs a value; with single the selected toggle cannot be turned off.
414
+ - `disabled`: boolean, reflects. Disables every toggle.
415
+ - `spaced`: boolean, reflects. Toggles apart, each with its own corners (default: joined).
416
+ - `variant`: `subtle` | `outline` | `light` | `filled` | `raised`, reflects. Variant of the toggles.
417
+ - `color`: string, reflects. Color of the toggles' on state.
418
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, reflects. Size of the toggles.
419
+ - `radius`: string, reflects. Corner radius of the toggles.
420
+ - `square`: boolean, reflects. Square toggles, for icons.
421
+
422
+ Also the properties of RayButtonGroup (`<ray-button-group>`): `orientation`, `fullWidth`, `label`.
423
+
424
+ Events:
425
+
426
+ - `change`: The user changed the selection (read `value` or `values`; the toggles' own change events stop at the group).
427
+
428
+ Slots:
429
+
430
+ - (default): ray-toggle elements.
431
+
432
+ Methods and properties:
433
+
434
+ - `values: string[]`: The selected keys as a list, in any mode.
435
+ - `readonly toggles: RayToggle[]`: The toggles of this group.
436
+
437
+ ### Checkbox
438
+
439
+ A checkbox with label, description and error. Submits value when checked.
440
+
441
+ Import: `import "@raylang/elements/checkbox";` · Category: Inputs
442
+
443
+ #### `<ray-checkbox>` (RayCheckbox, extends FieldControl)
444
+
445
+ Properties:
446
+
447
+ - `checked` (attribute `checked`: the initial value only): boolean. Current state. The checked attribute is the initial state (restored on reset).
448
+ - `indeterminate`: boolean, reflects. Mixed state; cleared on the next user change.
449
+ - `value`: string, default `on`, reflects. Submitted value when checked.
450
+ - `name`: string. Form field name.
451
+ - `label`: string. Label text (or put the label in the content).
452
+ - `description`: string. Help text.
453
+ - `error`: string. Error text.
454
+ - `required`: boolean. Must be checked to submit.
455
+ - `disabled`: boolean. Not interactive nor submitted.
456
+ - `variant`: `filled` | `outline`, default `filled`, reflects. Checked look: filled box, or colored border and mark.
457
+ - `color`: string. A palette color or any CSS color for the checked state.
458
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Box and font size.
459
+ - `labelPosition` (attribute `label-position`): `right` | `left`, default `right`, reflects. Side of the label.
460
+
461
+ Also the properties of FieldControl: `radius`, `descriptionPosition`.
462
+
463
+ Events:
464
+
465
+ - `change`: When the user toggles it.
466
+
467
+ Slots:
468
+
469
+ - (default): Label content.
470
+
471
+ Parts (`::part()`):
472
+
473
+ - `input`: The native checkbox (transparent, on top of the indicator).
474
+ - `indicator`: The drawn box.
475
+ - `label`: The label.
476
+
477
+ Vue `v-model`: `checked` (updated on change).
478
+
479
+ ### Checkbox group
480
+
481
+ Several choices among options (Mantine's Checkbox.Group): a label, description and error around ray-checkbox elements; the value is the array of the checked ones. max caps how many; required asks for one.
482
+
483
+ Import: `import "@raylang/elements/checkbox-group";` · Category: Inputs
484
+
485
+ #### `<ray-checkbox-group>` (RayCheckboxGroup, extends FormControl)
486
+
487
+ The group is the form control: one entry per checked value under name (like checkboxes sharing a name); the checkboxes inside lose their own name. It stops their change events and fires its own. role="group" named by its label.
488
+
489
+ Properties:
490
+
491
+ - `value` (attribute `value`: the initial value only): `string[]`. The checked values. The value attribute: "a,b".
492
+ - `name`: string, reflects. Form field name.
493
+ - `label`: string. Group label (also its accessible name).
494
+ - `description`: string. Help text.
495
+ - `error`: string. Error text.
496
+ - `required`: boolean, reflects. At least one must be checked.
497
+ - `disabled`: boolean, reflects. Disables every checkbox.
498
+ - `max`: number. At most this many: the others are disabled once reached; the label shows the count.
499
+ - `orientation`: `vertical` | `horizontal`, default `vertical`, reflects. Layout of the checkboxes.
500
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, reflects. Size of the checkboxes that set none.
501
+ - `color`: string, reflects. Color of the checkboxes that set none.
502
+ - `descriptionPosition` (attribute `description-position`): `above` | `below`, default `above`, reflects. The description before the checkboxes or after them.
503
+
504
+ Events:
505
+
506
+ - `change`: The user checked or unchecked one (read value).
507
+ - `input`: Same moment as change.
508
+
509
+ Slots:
510
+
511
+ - (default): ray-checkbox elements (also nested in other markup).
512
+
513
+ Methods and properties:
514
+
515
+ - `readonly checkboxes: HTMLElement[]`: The checkboxes of this group.
516
+
517
+ Vue `v-model`: `value` (updated on change).
518
+
519
+ ### Color picker
520
+
521
+ Pick a color: an inline picker (saturation area, hue, opacity, swatches) and a text field with the picker in a dropdown and an eyedropper. Pointer and keyboard; form-associated; hex, rgb or hsl, with or without alpha.
522
+
523
+ Import: `import "@raylang/elements/color-picker";` · Category: Inputs
524
+
525
+ #### `<ray-color-picker>` (RayColorPicker, extends FormControl)
526
+
527
+ Keyboard: arrows move the area's thumb (saturation, brightness) or a slider's; Shift for 10× steps; Home/End on the sliders. The alpha slider shows when format has alpha.
528
+
529
+ Properties:
530
+
531
+ - `value`: string. The color, written in format. Any color is accepted and rewritten in format. The value attribute is the initial value (restored on form reset).
532
+ - `format`: `ColorFormat`, default `hex`, reflects. How value is written: hex, hexa, rgb, rgba, hsl or hsla. Formats ending in a show the opacity slider.
533
+ - `swatches`: `string | string[]`. Preset colors below the picker: an array, or a comma-separated list in the attribute (commas inside rgb()/hsl() are kept).
534
+ - `swatchesPerRow` (attribute `swatches-per-row`): number, default `7`. Swatches in each row.
535
+ - `swatchesOnly` (attribute `swatches-only`): boolean, reflects. Only the swatches: no area nor sliders.
536
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `md`, reflects. Width of the picker and size of its thumbs.
537
+ - `fullWidth` (attribute `full-width`): boolean, reflects. Takes the width of its container.
538
+ - `name`: string, reflects. Form field name.
539
+ - `disabled`: boolean, reflects. Not interactive.
540
+ - `label`: string. Accessible name of the whole picker.
541
+
542
+ Events:
543
+
544
+ - `input`: The color moved (every step of a drag).
545
+ - `change`: The color settled: pointer released, a key pressed or a swatch chosen (read value).
546
+
547
+ Parts (`::part()`):
548
+
549
+ - `saturation`: The saturation/brightness area.
550
+ - `hue`: The hue slider.
551
+ - `alpha`: The opacity slider.
552
+ - `preview`: The current color.
553
+ - `swatches`: The swatches' grid.
554
+
555
+ Methods and properties:
556
+
557
+ - `readonly rgba: Rgba`: The current color as channels and alpha (0…1).
558
+
559
+ Vue `v-model`: `value` (updated on input).
560
+
561
+ #### `<ray-color-input>` (RayColorInput, extends FieldControl)
562
+
563
+ Type any CSS color (it becomes the value as soon as it is valid; invalid text goes back to the value on blur), or open the picker with a click or ArrowDown. The eyedropper shows only where the browser has the EyeDropper API.
564
+
565
+ Properties:
566
+
567
+ - `value`: string. The color, written in format. The value attribute is the initial value (restored on form reset).
568
+ - `format`: `ColorFormat`, default `hex`, reflects. How value is written: hex, hexa, rgb, rgba, hsl or hsla.
569
+ - `swatches`: `string | string[]`. Preset colors in the dropdown (an array, or a comma-separated list).
570
+ - `swatchesPerRow` (attribute `swatches-per-row`): number, default `7`. Swatches in each row.
571
+ - `placeholder`: string. Shown while empty.
572
+ - `hideEyedropper` (attribute `hide-eyedropper`): boolean, reflects. Hides the eyedropper button.
573
+ - `open`: boolean, reflects. The dropdown is shown.
574
+ - `name`: string, reflects. Form field name.
575
+ - `label`: string. Label above the field.
576
+ - `description`: string. Help text.
577
+ - `error`: string. Error message; marks the field invalid.
578
+ - `required`: boolean, reflects. Must have a color.
579
+ - `disabled`: boolean, reflects. Not interactive.
580
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Field height and font size.
581
+ - `radius`: string, reflects. Corner radius: xs…xl or a CSS length.
582
+ - `variant`: `default` | `filled` | `unstyled`, default `default`, reflects. Visual style of the field.
583
+ - `descriptionPosition` (attribute `description-position`): `above` | `below`, default `above`, reflects. Where the description goes.
584
+
585
+ Events:
586
+
587
+ - `input`: The color changed (typing a valid color, or moving the picker).
588
+ - `change`: The color settled (picker released, a swatch, the eyedropper, or the field left with a new color).
589
+ - `ray-open`: The dropdown opened.
590
+ - `ray-close`: The dropdown closed.
591
+
592
+ Parts (`::part()`):
593
+
594
+ - `input`: The text field.
595
+ - `preview`: The swatch of the current color.
596
+ - `eyedropper`: The eyedropper button.
597
+ - `dropdown`: The dropdown with the picker.
598
+
599
+ Methods and properties:
600
+
601
+ - `readonly picker: RayColorPicker`: The ray-color-picker in the dropdown.
602
+ - `toggle(force?: boolean): void`: Opens or closes the dropdown.
603
+
604
+ Vue `v-model`: `value` (updated on input).
605
+
606
+ Exports (from `@raylang/elements/color-picker` and `@raylang/elements`):
607
+
608
+ - `function parseColorValue(input: string | null | undefined): Rgba | null`: A color string (hex with 3/4/6/8 digits, rgb(a), hsl(a), or any CSS color) as channels and alpha, or null.
609
+ - `function formatColor(color: Rgba, format?: ColorFormat): string`: Channels and alpha as a string in a format (default hex).
610
+
611
+ Types:
612
+
613
+ - `"hex" | "hexa" | "rgb" | "rgba" | "hsl" | "hsla"`: How a color value is written.
614
+ - `{ r: number; g: number; b: number; a: number }`: sRGB channels and alpha, all 0…1.
615
+
616
+ ### Combobox (also Multi select)
617
+
618
+ A select you can type in, an autocomplete (Mantine's searchable Select, MultiSelect and TagsInput): typing filters the options; multiple keeps chips; creatable adds new values; clearable, max-values, groups, a result limit.
619
+
620
+ Import: `import "@raylang/elements/combobox";` · Category: Inputs
621
+
622
+ #### `<ray-combobox>` (RayCombobox, extends FieldControl)
623
+
624
+ The WAI-ARIA combobox pattern (a text field with a listbox popup; the active option is aria-activedescendant). Arrows move, Enter picks, Escape closes (then clears with clearable), Backspace in an empty field removes the last chip. The form gets one entry per value.
625
+
626
+ Properties:
627
+
628
+ - `value` (attribute `value`: the initial value only): `string | string[]`. The chosen value; an array with multiple. The value attribute: "a,b" with multiple.
629
+ - `data` (property only): `Array<string | { value: string; label?: string; disabled?: boolean; group?: string }>`. Options instead of child <option>/<optgroup> elements.
630
+ - `multiple`: boolean, reflects. Several values, shown as chips.
631
+ - `placeholder`: string. Shown while empty.
632
+ - `creatable`: boolean. What was typed can be added when no option matches it ("+ Create …"); fires ray-create.
633
+ - `clearable`: boolean. A button that clears the value.
634
+ - `maxValues` (attribute `max-values`): number. With multiple: at most this many.
635
+ - `limit`: number. At most this many options shown (large lists: keep typing).
636
+ - `nothingFound` (attribute `nothing-found`): string, default `No matches`. Shown when nothing matches.
637
+ - `open`: boolean, reflects. The dropdown is shown.
638
+
639
+ Also the properties of FieldControl: `name`, `label`, `description`, `error`, `required`, `disabled`, `size`, `radius`, `variant`, `descriptionPosition`.
640
+
641
+ Events:
642
+
643
+ - `change`: The value changed (read value).
644
+ - `input`: Same moment as change.
645
+ - `ray-create` (detail `{ value: string }`): A new value was created from the typed text.
646
+ - `ray-open`: The dropdown opened.
647
+ - `ray-close`: The dropdown closed.
648
+
649
+ Slots:
650
+
651
+ - (default): <option> and <optgroup> elements.
652
+
653
+ Parts (`::part()`):
654
+
655
+ - `input`: The text field.
656
+ - `chips`: The chips container.
657
+ - `chip`: A chip.
658
+ - `clear`: The clear button.
659
+ - `dropdown`: The listbox.
660
+ - `option`: An option.
661
+
662
+ Methods and properties:
663
+
664
+ - `readonly values: string[]`: The value as an array (with or without multiple).
665
+ - `toggle(force?: boolean): void`: Opens or closes the dropdown.
666
+
667
+ Vue `v-model`: `value` (updated on change).
668
+
669
+ ### Date picker
670
+
671
+ A date field with a calendar dropdown, and the calendar on its own. Keyboard grid navigation, min/max, locale-aware. Form-associated.
672
+
673
+ Import: `import "@raylang/elements/date-picker";` · Category: Inputs
674
+
675
+ #### `<ray-date-picker>` (RayDatePicker, extends FieldControl)
676
+
677
+ Values are ISO dates ("2026-10-06"), submitted as such. ArrowDown on the field opens the calendar; Escape closes it.
678
+
679
+ Properties:
680
+
681
+ - `value`: string. The chosen date, ISO "YYYY-MM-DD" ("" for none). The value attribute is the initial value (restored on form reset).
682
+ - `min`: string. Earliest selectable date (ISO). Earlier days are disabled; an earlier value is invalid (rangeUnderflow).
683
+ - `max`: string. Latest selectable date (ISO).
684
+ - `placeholder`: string, default `Pick a date`. Shown while no date is chosen.
685
+ - `format`: `short` | `medium` | `long` | `full`, default `medium`. How the date is displayed (Intl dateStyle).
686
+ - `locale`: string. Locale for names and formats. Default: the nearest lang attribute, else the browser's.
687
+ - `firstDay` (attribute `first-day`): number. First day of the week, 0 (Sunday) to 6. Default: the locale's.
688
+ - `clearable`: boolean, reflects. Shows a button that clears the date.
689
+ - `open`: boolean, reflects. The calendar dropdown is shown.
690
+ - `name`: string, reflects. Form field name.
691
+ - `label`: string. Visible label (also the accessible name).
692
+ - `description`: string. Help text.
693
+ - `descriptionPosition` (attribute `description-position`): `above` | `below`, default `above`, reflects. The description before the control (help first) or after it, with the error (fields in a row stay aligned).
694
+ - `error`: string. Error text.
695
+ - `required`: boolean. Required for form submission.
696
+ - `disabled`: boolean. Not interactive nor submitted.
697
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Height and font size.
698
+ - `radius`: `xs` | `sm` | `md` | `lg` | `xl` | `full`. Corner radius.
699
+ - `variant`: `default` | `filled` | `unstyled`, default `default`, reflects. Box style.
700
+
701
+ Events:
702
+
703
+ - `input`: When the date changes (picked or cleared).
704
+ - `change`: When the date changes (picked or cleared).
705
+ - `ray-open`: The calendar opened.
706
+ - `ray-close`: The calendar closed.
707
+
708
+ Parts (`::part()`):
709
+
710
+ - `trigger`: The button showing the date.
711
+ - `clear`: The clear button.
712
+ - `dropdown`: The calendar panel (a popover in the top layer).
713
+ - `calendar`: The <ray-calendar> in the dropdown (its day, caption, nav and grid parts are exported).
714
+ - `input`: The hidden native <input type=date> that holds the value (the model).
715
+ - `wrapper`: The box.
716
+
717
+ Methods and properties:
718
+
719
+ - `toggle(force?: boolean): void`: Opens or closes the calendar.
720
+ - `readonly displayValue: string`: The chosen date as displayed ("" when none).
721
+
722
+ Vue `v-model`: `value` (updated on change).
723
+
724
+ #### `<ray-calendar>` (RayCalendar, extends RayElement)
725
+
726
+ WAI-ARIA grid: arrows move by day and week, Home/End to the week's ends, PageUp/PageDown by month (with Shift, by year), Enter/Space select.
727
+
728
+ Properties:
729
+
730
+ - `value`: string. The selected date, ISO "YYYY-MM-DD".
731
+ - `min`: string. Earliest selectable date (ISO).
732
+ - `max`: string. Latest selectable date (ISO).
733
+ - `locale`: string. Locale for month and weekday names. Default: the nearest lang attribute, else the browser's.
734
+ - `firstDay` (attribute `first-day`): number. First day of the week, 0 (Sunday) to 6. Default: the locale's.
735
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Day cell size and font size.
736
+
737
+ Events:
738
+
739
+ - `change`: A day was selected (read `value`).
740
+
741
+ Parts (`::part()`):
742
+
743
+ - `header`: The row with the month and the navigation buttons.
744
+ - `caption`: The month and year.
745
+ - `nav`: The previous/next month buttons.
746
+ - `grid`: The day grid (role=grid).
747
+ - `day`: Each day button ([aria-selected], [aria-current=date], [aria-disabled], [data-outside]).
748
+
749
+ Methods and properties:
750
+
751
+ - `focusDay(): void`: Focuses the day the keyboard is on (the selected day, else today).
752
+ - `readonly focusedDate: string`: The day the keyboard is on (ISO).
753
+
754
+ Vue `v-model`: `value` (updated on change).
755
+
756
+ ### File upload
757
+
758
+ A drop zone to pick files: drag, click, keyboard or paste. Checks type, size and count as files arrive, lists them as ray-attachment rows (thumbnails, remove) and submits them with its form.
759
+
760
+ Import: `import "@raylang/elements/file-upload";` · Category: Inputs
761
+
762
+ #### `<ray-file-upload>` (RayFileUpload, extends FormControl)
763
+
764
+ A drag that can only be refused turns the zone red before the drop; refused files fire ray-reject and are explained under the zone. Without multiple a new file replaces the current one. Uploading is the app's: attachmentFor(file) gives the row whose progress/status/error to set.
765
+
766
+ Properties:
767
+
768
+ - `name`: string, reflects. Form field name: every file is submitted under it.
769
+ - `label`: string. Label above the zone.
770
+ - `description`: string. Help text under the label.
771
+ - `error`: string. Error text (replaces the explanation of refused files).
772
+ - `required`: boolean, reflects. The form needs at least one file.
773
+ - `disabled`: boolean, reflects. No picking, dropping or removing.
774
+ - `accept`: string, reflects. Accepted types, as in <input type=file>: ".pdf,.png", "image/*", "application/json".
775
+ - `multiple`: boolean, reflects. Several files (else one, replaced by the next).
776
+ - `maxSize` (attribute `max-size`): `string | number`. Largest file: bytes or a size like "10 MB", "512 KB".
777
+ - `maxFiles` (attribute `max-files`): number. With multiple: the most files kept.
778
+ - `hint`: string. Small text in the zone. Default: from accept, max-size and max-files ("PNG or PDF · up to 10 MB each · max. 5 files").
779
+ - `dropLabel` (attribute `drop-label`): string, default `Drag files here`. Title of the zone, before "or browse".
780
+ - `browseLabel` (attribute `browse-label`): string, default `browse`. The link-styled word (the button text in compact).
781
+ - `activeLabel` (attribute `active-label`): string, default `Drop to add files`. Title while files are dragged over it.
782
+ - `tapLabel` (attribute `tap-label`): string, default `Choose files`. Title on touch screens (no hover), where dragging files is rare.
783
+ - `variant`: `default` | `compact`, default `default`, reflects. default: a tall centered zone; compact: one row with a Browse button.
784
+ - `list`: `rows` | `cards` | `none`, default `rows`, reflects. How chosen files show: full-width rows, thumbnail cards, or not at all (render your own on change).
785
+ - `native`: boolean, reflects. With a native host (ray-elements/core/raylang.js in a std/ui window), browsing opens the system dialog and gives paths (see `paths`); drop and paste still give Files.
786
+ - `color`: string, reflects. Accent of hover, drag and the browse link (default: primary).
787
+
788
+ Events:
789
+
790
+ - `change`: Files were added or removed (read `files`, and `lastChange` for which).
791
+ - `ray-reject` (detail `{ rejected: FileRejection[] }`): Some files were refused (type, size or count).
792
+ - `ray-error` (detail `{ error: Error }`): The native dialog failed (with `native`).
793
+
794
+ Slots:
795
+
796
+ - `icon`: Replaces the upload icon.
797
+
798
+ Parts (`::part()`):
799
+
800
+ - `dropzone`: The zone (a button).
801
+ - `icon`: The icon tile.
802
+ - `hint`: The small text in the zone.
803
+ - `files`: The list of chosen files.
804
+ - `label`: The label.
805
+ - `error`: The error text.
806
+
807
+ Methods and properties:
808
+
809
+ - `files: (File | HostFile)[]`: The chosen files (assign to replace them, without events).
810
+ - `readonly paths: string[]`: The paths of the files chosen with the native dialog (`native`), in order; they are also what the form submits for them.
811
+ - `readonly lastChange: FileUploadChange | null`: What the last change event changed: the files added and removed. null before the first one, and after assigning files.
812
+ - `open(): void`: Opens the system file picker.
813
+ - `addFiles(files: Iterable<File>): { accepted: File[]; rejected: FileRejection[] }`: Adds files as if dropped (checks them, fires the events).
814
+ - `removeFile(file: File): boolean`: Removes a file (fires change).
815
+ - `clear(): void`: Removes every file (fires change).
816
+ - `attachmentFor(file: File): RayAttachment | null`: The row of a file, to show its upload progress, status or error.
817
+
818
+ Exports (from `@raylang/elements/file-upload` and `@raylang/elements`):
819
+
820
+ - `function parseSize(value: string | number | null | undefined): number`: Bytes from a number or a size like "10 MB" (NaN if neither).
821
+ - `function matchesAccept(file: { name: string; type: string }, accept: string | null | undefined): boolean`: Whether a file passes an accept list.
822
+ - `function describeAccept(accept: string | null | undefined): string`: A short human list of an accept value ("PNG, JPG or PDF").
823
+
824
+ Types:
825
+
826
+ - `{ added: (File | HostFile)[]; removed: (File | HostFile)[] }`: The files a change added and removed.
827
+ - `{ file: File; reason: "type" | "size" | "count"; message: string }`: A refused file and why.
828
+
829
+ #### In a raylang app
830
+
831
+ In a `std/ui` window with [the native bridge](https://elements.raylang.dev/raylang.html#using-the-bridge), `native` makes browsing open the system's file dialog, with the `accept` types as its filter. The files it gives are paths on the user's disk, not bytes: they list like any other file (name, size, type) and the program reads them.
832
+
833
+ ```html
834
+ <form id="import">
835
+ <ray-file-upload name="photos" native multiple accept="image/*" label="Photos"></ray-file-upload>
836
+ </form>
837
+ ```
838
+
839
+ ```js
840
+ upload.addEventListener("change", () => {
841
+ window.ray.send("import:" + JSON.stringify(upload.paths)); // ["/Users/ada/Pictures/a.jpg", …]
842
+ });
843
+ ```
844
+
845
+ The form submits those paths under `name`. Dropped and pasted files are still `File` objects (`upload.files` holds both; a chosen one is a `HostFile` with a `path`). Without the bridge, or in a browser, `native` changes nothing.
846
+
847
+ ### Input
848
+
849
+ A text field with label, description and error (Mantine's TextInput). Form-associated.
850
+
851
+ Import: `import "@raylang/elements/input";` · Category: Inputs
852
+
853
+ #### `<ray-input>` (RayInput, extends FieldControl)
854
+
855
+ Also forwards placeholder, autocomplete, inputmode, pattern, min, max, step, minlength, maxlength, spellcheck, autocapitalize, enterkeyhint and list to the inner input. Enter submits its form as a native field does: through the first submit button (ray-button type="submit" included; nothing when it is disabled), or, without one, only when the form has a single text field.
856
+
857
+ Properties:
858
+
859
+ - `value`: string. Current value. The value attribute is the initial value (restored on form reset).
860
+ - `type`: `text` | `email` | `password` | `search` | `number` | `url` | `tel`, default `text`, reflects. Input type.
861
+ - `name`: string, reflects. Form field name.
862
+ - `label`: string. Visible label (also the accessible name).
863
+ - `description`: string. Help text under the label.
864
+ - `descriptionPosition` (attribute `description-position`): `above` | `below`, default `above`, reflects. The description before the control (help first) or after it, with the error (fields in a row stay aligned).
865
+ - `error`: string. Error text; marks the field invalid (display only — does not block submit).
866
+ - `placeholder`: string. Placeholder text.
867
+ - `required`: boolean. Required for form submission; shows an asterisk.
868
+ - `disabled`: boolean. Not editable nor submitted.
869
+ - `readonly`: boolean. Not editable, still submitted.
870
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Height and font size.
871
+ - `radius`: `xs` | `sm` | `md` | `lg` | `xl` | `full`. Corner radius.
872
+ - `variant`: `default` | `filled` | `unstyled`, default `default`, reflects. Box style.
873
+
874
+ Attributes (forwarded to the inner element):
875
+
876
+ - `autocomplete`: Forwarded to the inner input.
877
+ - `inputmode`: Virtual keyboard hint.
878
+ - `pattern`: Validation pattern (regular expression).
879
+ - `min`: Minimum (number/date types).
880
+ - `max`: Maximum (number/date types).
881
+ - `step`: Step (number types).
882
+ - `minlength`: Minimum length.
883
+ - `maxlength`: Maximum length.
884
+ - `autocapitalize`: Mobile auto-capitalization.
885
+ - `enterkeyhint`: Label of the Enter key on virtual keyboards.
886
+ - `list`: Id of a <datalist> with suggestions.
887
+
888
+ Events:
889
+
890
+ - `input`: On every edit (value already updated).
891
+ - `change`: When an edit is committed (blur, Enter).
892
+
893
+ Slots:
894
+
895
+ - `left`: Section before the text (icon).
896
+ - `right`: Section after the text (icon, button).
897
+
898
+ Parts (`::part()`):
899
+
900
+ - `input`: The inner <input>.
901
+ - `wrapper`: The box around the input and sections.
902
+ - `label`: The label.
903
+ - `description`: The description.
904
+ - `error`: The error message.
905
+
906
+ Methods and properties:
907
+
908
+ - `select(): void`: Selects the text.
909
+
910
+ Vue `v-model`: `value` (updated on input).
911
+
912
+ ### Number input
913
+
914
+ A number field (Mantine's NumberInput): + and − buttons (hold to repeat), arrow keys, min, max and step, fixed decimals, a prefix and a suffix, a thousands separator. An ARIA spinbutton.
915
+
916
+ Import: `import "@raylang/elements/number-input";` · Category: Inputs
917
+
918
+ #### `<ray-number-input>` (RayNumberInput, extends FieldControl)
919
+
920
+ Arrow Up/Down step (Shift: ×10), Page Up/Down ×10, Home/End go to min/max. The value is a number (undefined when empty); the form gets its plain digits; min and max are checked (rangeUnderflow, rangeOverflow). Enter submits its form, as in ray-input.
921
+
922
+ Properties:
923
+
924
+ - `value`: number. The number (undefined when empty).
925
+ - `min`: number. Minimum.
926
+ - `max`: number. Maximum.
927
+ - `step`: number, default `1`. What + and − add.
928
+ - `decimals`: number. Fixed decimals (2: 3 shows as 3.00).
929
+ - `prefix`: `string | null`. Shown before the number ("$").
930
+ - `suffix`: string. Shown after the number (" kg", "%").
931
+ - `thousandsSeparator` (attribute `thousands-separator`): string. Groups thousands in the shown text (",", ".", " ").
932
+ - `decimalSeparator` (attribute `decimal-separator`): string, default `.`. The decimal mark shown and typed ("," in many locales).
933
+ - `clamp`: `blur` | `strict` | `none`, default `blur`. When out-of-range input is clamped: on blur, while typing, or never (then it is invalid).
934
+ - `hideControls` (attribute `hide-controls`): boolean, reflects. No + and − buttons (the keys still step).
935
+ - `placeholder`: string. Shown while empty.
936
+ - `readonly`: boolean, reflects. Not editable, still submitted.
937
+
938
+ Also the properties of FieldControl: `name`, `label`, `description`, `error`, `required`, `disabled`, `size`, `radius`, `variant`, `descriptionPosition`.
939
+
940
+ Events:
941
+
942
+ - `input`: On every change of the value (typing, keys, buttons).
943
+ - `change`: When the value is committed (blur, a step).
944
+
945
+ Slots:
946
+
947
+ - `left`: Left section (an icon).
948
+ - `right`: Right section.
949
+
950
+ Parts (`::part()`):
951
+
952
+ - `input`: The text field.
953
+ - `controls`: The + and − column.
954
+ - `increment`: The + button.
955
+ - `decrement`: The − button.
956
+
957
+ Methods and properties:
958
+
959
+ - `stepBy(steps: number): void`: Adds steps (negative: subtracts), clamped; fires input and change.
960
+
961
+ Vue `v-model`: `value` (updated on input).
962
+
963
+ Exports (from `@raylang/elements/number-input` and `@raylang/elements`):
964
+
965
+ - `function parseNumber(text: string, options?: { decimal?: string; thousands?: string }): number`: The number in a text with separators, prefix or suffix (NaN if none).
966
+ - `function formatNumber(n: number, options?: { decimals?: number; thousands?: string; decimal?: string }): string`: A number as text with fixed decimals and separators.
967
+
968
+ ### Password input
969
+
970
+ A password field with a button that shows or hides what was typed (Mantine's PasswordInput). Everything else is ray-input: label, description, error, sizes, validation, forms.
971
+
972
+ Import: `import "@raylang/elements/password-input";` · Category: Inputs
973
+
974
+ #### `<ray-password-input>` (RayPasswordInput, extends RayInput)
975
+
976
+ autocomplete defaults to current-password: use new-password on sign-up and change forms. The toggle keeps the focus and the caret in the field.
977
+
978
+ Properties:
979
+
980
+ - `visible`: boolean, reflects. The password is shown as text.
981
+ - `showLabel` (attribute `show-label`): string, default `Show password`. Accessible name of the toggle while hidden.
982
+ - `hideLabel` (attribute `hide-label`): string, default `Hide password`. Accessible name of the toggle while shown.
983
+
984
+ Also the properties of RayInput (`<ray-input>`): `value`, `type`, `name`, `label`, `description`, `descriptionPosition`, `error`, `placeholder`, `required`, `disabled`, `readonly`, `size`, `radius`, `variant`.
985
+
986
+ Events:
987
+
988
+ - `ray-visibility-change` (detail `{ visible: boolean }`): The user showed or hid the password.
989
+
990
+ Parts (`::part()`):
991
+
992
+ - `toggle`: The show/hide button.
993
+
994
+ ### Path input (also File path, Folder picker)
995
+
996
+ A field for a path on disk: a file to open, a folder, or where to save. In a std/ui window (with ray-elements/core/raylang.js) a Browse… button opens the system dialog; in a browser it is a plain text field. Everything else is ray-input.
997
+
998
+ Import: `import "@raylang/elements/path-input";` · Category: Inputs
999
+
1000
+ #### `<ray-path-input>` (RayPathInput, extends RayInput)
1001
+
1002
+ Browse… shows only with a native host that offers pick_path (see core/host.js); the dialog starts in the folder of the current path. The path can always be typed or pasted.
1003
+
1004
+ Properties:
1005
+
1006
+ - `mode`: `open` | `folder` | `save`, default `open`, reflects. What the dialog chooses: an existing file, a folder, or a file to save (the current name is suggested).
1007
+ - `accept`: string, reflects. File types the dialog offers, as in <input type=file>: ".json,.toml", "image/*" (ignored for folders).
1008
+ - `browseLabel` (attribute `browse-label`): string, default `Browse…`. Text of the button.
1009
+ - `dialogTitle` (attribute `dialog-title`): string. Title of the system dialog (default: the label).
1010
+
1011
+ Also the properties of RayInput (`<ray-input>`): `value`, `type`, `name`, `label`, `description`, `descriptionPosition`, `error`, `placeholder`, `required`, `disabled`, `readonly`, `size`, `radius`, `variant`.
1012
+
1013
+ Events:
1014
+
1015
+ - `change`: The path changed: typed and committed, or chosen in the dialog.
1016
+ - `ray-error` (detail `{ error: Error }`): The system dialog failed.
1017
+
1018
+ Parts (`::part()`):
1019
+
1020
+ - `browse`: The Browse… button.
1021
+
1022
+ Methods and properties:
1023
+
1024
+ - `readonly canBrowse: boolean`: Whether Browse… is available (a native host offers pick_path).
1025
+ - `browse(): Promise<string | null>`: Opens the system dialog; resolves to the chosen path (also set as value, with input and change), or null.
1026
+
1027
+ Exports (from `@raylang/elements/path-input` and `@raylang/elements`):
1028
+
1029
+ - `function dirName(path: string): string`: The folder part of a path ("" when it has none), with / or \ separators.
1030
+ - `function baseName(path: string): string`: The last part of a path.
1031
+
1032
+ #### In a raylang app
1033
+
1034
+ Browse… shows only in a `std/ui` window with [the native bridge](https://elements.raylang.dev/raylang.html#using-the-bridge). It opens the system's dialog for the `mode`, starting in the folder of the current path (`save` also suggests the current file name). The chosen path fills the field and fires `input` and `change`; the program gets it with the form like any other field.
1035
+
1036
+ ```html
1037
+ <ray-path-input name="workspace" label="Workspace" mode="folder"></ray-path-input>
1038
+ <ray-path-input name="export" label="Export to" mode="save" accept=".csv"></ray-path-input>
1039
+ ```
1040
+
1041
+ ```ray
1042
+ // The program's side: ui.events() through bridge.handle, then the form arrives as usual.
1043
+ for e in ui.events() {
1044
+ if (bridge.handle(e)) {
1045
+ continue;
1046
+ }
1047
+ if (e.kind == "message" && e.tag.starts_with("settings:")) {
1048
+ save_settings(e.tag.substring(9, e.tag.len()))?;
1049
+ }
1050
+ }
1051
+ ```
1052
+
1053
+ ### Radio group
1054
+
1055
+ One choice among options: ray-radio elements inside a ray-radio-group, which is the form control.
1056
+
1057
+ Import: `import "@raylang/elements/radio";` · Category: Inputs
1058
+
1059
+ #### `<ray-radio-group>` (RayRadioGroup, extends FormControl)
1060
+
1061
+ Arrow keys move the selection, Tab enters and leaves the group.
1062
+
1063
+ Properties:
1064
+
1065
+ - `value`: string. Value of the checked radio. Initial: the value attribute, or a radio with the checked attribute.
1066
+ - `name`: string. Form field name.
1067
+ - `label`: string. Group label (also its accessible name).
1068
+ - `description`: string. Help text.
1069
+ - `descriptionPosition` (attribute `description-position`): `above` | `below`, default `above`, reflects. The description before the control (help first) or after it, with the error (fields in a row stay aligned).
1070
+ - `error`: string. Error text.
1071
+ - `required`: boolean. A choice is needed to submit.
1072
+ - `disabled`: boolean. Disables every radio.
1073
+ - `orientation`: `vertical` | `horizontal`, default `vertical`, reflects. Layout of the radios.
1074
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Size of every radio.
1075
+ - `color`: string. Checked color of every radio.
1076
+ - `variant`: `filled` | `outline`, default `filled`, reflects. Checked look of every radio: filled circle, or colored ring and dot.
1077
+
1078
+ Events:
1079
+
1080
+ - `input`: When the user picks a radio.
1081
+ - `change`: When the user picks a radio.
1082
+
1083
+ Slots:
1084
+
1085
+ - (default): ray-radio elements (may be wrapped in layout elements).
1086
+
1087
+ Methods and properties:
1088
+
1089
+ - `readonly radios: RayRadio[]`: The radios of the group.
1090
+
1091
+ Vue `v-model`: `value` (updated on change).
1092
+
1093
+ #### `<ray-radio>` (RayRadio, extends RayElement)
1094
+
1095
+ Properties:
1096
+
1097
+ - `value`: string, reflects. Value given to the group when chosen.
1098
+ - `checked` (attribute `checked`: the initial value only): boolean. Whether this radio is the group's value; setting it sets the group's value. The checked attribute marks the group's initial value (when the group has no value attribute).
1099
+ - `label`: string. Label text (or the content).
1100
+ - `description`: string. Help text under the label.
1101
+ - `disabled`: boolean. Cannot be chosen.
1102
+ - `color`: string. Overrides the group color.
1103
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`. Overrides the group size.
1104
+ - `variant`: `filled` | `outline`, reflects. Overrides the group variant.
1105
+
1106
+ Slots:
1107
+
1108
+ - (default): Label content.
1109
+
1110
+ Parts (`::part()`):
1111
+
1112
+ - `indicator`: The circle.
1113
+ - `label`: The label.
1114
+
1115
+ ### Search
1116
+
1117
+ A search box: icon, clear button, an optional shortcut that focuses it, and a debounced ray-search event. A RayInput, so it has a label and takes part in forms.
1118
+
1119
+ Import: `import "@raylang/elements/search";` · Category: Inputs
1120
+
1121
+ #### `<ray-search>` (RaySearch, extends FieldControl)
1122
+
1123
+ Escape clears it (when it has text); Enter fires ray-search at once. JS: clear(), focus().
1124
+
1125
+ Properties:
1126
+
1127
+ - `value`: string. Current text.
1128
+ - `placeholder`: string, default `Search…`. Placeholder text.
1129
+ - `shortcut`: string. Keyboard shortcut that focuses it ("mod+k", "/"; mod = ⌘ on macOS, Ctrl elsewhere). Shown as a hint while empty.
1130
+ - `debounce`: number, default `200`. Milliseconds of quiet typing before ray-search fires (0: on every keystroke).
1131
+ - `name`: string, reflects. Form field name.
1132
+ - `label`: string. Visible label (also the accessible name). Without it, use aria-label.
1133
+ - `disabled`: boolean. Not editable nor submitted.
1134
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Height and font size.
1135
+ - `radius`: `xs` | `sm` | `md` | `lg` | `xl` | `full`. Corner radius.
1136
+ - `variant`: `default` | `filled` | `unstyled`, default `filled`, reflects. Box style.
1137
+
1138
+ Also the properties of FieldControl: `description`, `error`, `required`, `descriptionPosition`.
1139
+
1140
+ Events:
1141
+
1142
+ - `input`: On every edit (value already updated).
1143
+ - `ray-search` (detail `{ value: string }`): After `debounce` ms without typing, on Enter, and when cleared.
1144
+
1145
+ Parts (`::part()`):
1146
+
1147
+ - `input`: The inner <input type=search>.
1148
+ - `icon`: The search icon.
1149
+ - `clear`: The clear button.
1150
+ - `shortcut`: The shortcut hint.
1151
+ - `wrapper`: The box.
1152
+
1153
+ Methods and properties:
1154
+
1155
+ - `clear(): void`: Empties the box (fires input and ray-search).
1156
+
1157
+ Vue `v-model`: `value` (updated on input).
1158
+
1159
+ ### Segmented control
1160
+
1161
+ One choice among a few, as a segmented row with a sliding indicator. Options from child <option> elements or data. Form-associated.
1162
+
1163
+ Import: `import "@raylang/elements/segmented-control";` · Category: Inputs
1164
+
1165
+ #### `<ray-segmented-control>` (RaySegmentedControl, extends FormControl)
1166
+
1167
+ Properties:
1168
+
1169
+ - `value`: string. Selected value (default: the first enabled option).
1170
+ - `data` (property only): `Array<string | { value: string; label?: string; disabled?: boolean }>`. Options as strings or { value, label, disabled }.
1171
+ - `name`: string. Form field name.
1172
+ - `color`: string, reflects. Indicator color (default: a raised neutral segment).
1173
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Height and font size.
1174
+ - `radius`: `xs` | `sm` | `md` | `lg` | `xl` | `full`. Corner radius.
1175
+ - `fullWidth` (attribute `full-width`): boolean. Takes the whole width.
1176
+ - `orientation`: `horizontal` | `vertical`, default `horizontal`, reflects. Direction.
1177
+ - `disabled`: boolean. Not interactive nor submitted.
1178
+
1179
+ Events:
1180
+
1181
+ - `input`: The user picked another option.
1182
+ - `change`: The user picked another option.
1183
+
1184
+ Slots:
1185
+
1186
+ - (default): <option> elements.
1187
+
1188
+ Parts (`::part()`):
1189
+
1190
+ - `root`: The row.
1191
+ - `indicator`: The sliding highlight.
1192
+ - `control`: Each option button.
1193
+
1194
+ Methods and properties:
1195
+
1196
+ - `readonly items: Array<{ value: string; label: string; disabled: boolean }>`: The options, from data or the child options.
1197
+
1198
+ Vue `v-model`: `value` (updated on change).
1199
+
1200
+ ### Select
1201
+
1202
+ A select with its own dropdown (keyboard, typeahead, groups); options from child <option> elements or the data property. Form-associated.
1203
+
1204
+ Import: `import "@raylang/elements/select";` · Category: Inputs
1205
+
1206
+ #### `<ray-select>` (RaySelect, extends FieldControl)
1207
+
1208
+ Properties:
1209
+
1210
+ - `value`: string. Selected value.
1211
+ - `data` (property only): `Array<string | { value: string; label?: string; disabled?: boolean }>`. Options as strings or { value, label, disabled } (instead of child options).
1212
+ - `placeholder`: string. Shown while nothing is selected (with required, blocks submit).
1213
+ - `open`: boolean, reflects. The dropdown is shown.
1214
+ - `name`: string. Form field name.
1215
+ - `label`: string. Visible label.
1216
+ - `description`: string. Help text.
1217
+ - `descriptionPosition` (attribute `description-position`): `above` | `below`, default `above`, reflects. The description before the control (help first) or after it, with the error (fields in a row stay aligned).
1218
+ - `error`: string. Error text.
1219
+ - `required`: boolean. Required for form submission.
1220
+ - `disabled`: boolean. Not interactive nor submitted.
1221
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Height and font size.
1222
+ - `variant`: `default` | `filled` | `unstyled`, default `default`, reflects. Box style.
1223
+
1224
+ Also the properties of FieldControl: `radius`.
1225
+
1226
+ Events:
1227
+
1228
+ - `input`: When the selection changes.
1229
+ - `change`: When the selection changes.
1230
+ - `ray-open`: The dropdown opened.
1231
+ - `ray-close`: The dropdown closed.
1232
+
1233
+ Slots:
1234
+
1235
+ - (default): <option> and <optgroup> elements.
1236
+
1237
+ Parts (`::part()`):
1238
+
1239
+ - `trigger`: The combobox button showing the selected option.
1240
+ - `dropdown`: The listbox panel (a popover in the top layer).
1241
+ - `option`: Each option in the dropdown ([aria-selected], [data-active], [aria-disabled]).
1242
+ - `select`: The hidden native <select> that holds the value (the model).
1243
+ - `wrapper`: The box.
1244
+
1245
+ Methods and properties:
1246
+
1247
+ - `readonly options: HTMLOptionsCollection`: The options of the model select.
1248
+ - `toggle(force?: boolean): void`: Opens or closes the dropdown.
1249
+
1250
+ Vue `v-model`: `value` (updated on change).
1251
+
1252
+ ### Slider
1253
+
1254
+ A native range input (keyboard, touch and screen readers as usual) with label, value display and marks. Form-associated.
1255
+
1256
+ Import: `import "@raylang/elements/slider";` · Category: Inputs
1257
+
1258
+ #### `<ray-slider>` (RaySlider, extends FieldControl)
1259
+
1260
+ Properties:
1261
+
1262
+ - `value`: number. Current value. The value attribute is the initial one (restored on reset).
1263
+ - `min`: number, default `0`. Minimum.
1264
+ - `max`: number, default `100`. Maximum.
1265
+ - `step`: number, default `1`. Step.
1266
+ - `name`: string. Form field name.
1267
+ - `label`: string. Visible label.
1268
+ - `description`: string. Help text.
1269
+ - `descriptionPosition` (attribute `description-position`): `above` | `below`, default `above`, reflects. The description before the control (help first) or after it, with the error (fields in a row stay aligned).
1270
+ - `error`: string. Error text.
1271
+ - `disabled`: boolean. Not interactive nor submitted.
1272
+ - `color`: string, reflects. Track and thumb color.
1273
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Track and thumb size.
1274
+ - `showValue` (attribute `show-value`): boolean, reflects. Shows the value next to the label.
1275
+ - `unit`: string. Appended to the shown value and its spoken text (%, px, ms…).
1276
+ - `marks` (property only): `Array<number | { value: number; label?: string }>`. Labeled ticks under the track.
1277
+
1278
+ Also the properties of FieldControl: `required`, `radius`, `variant`.
1279
+
1280
+ Events:
1281
+
1282
+ - `input`: While dragging.
1283
+ - `change`: When released.
1284
+
1285
+ Parts (`::part()`):
1286
+
1287
+ - `input`: The native range input.
1288
+
1289
+ Vue `v-model`: `value` (updated on input).
1290
+
1291
+ ### Switch
1292
+
1293
+ An on/off toggle with the same API as Checkbox, announced as a switch.
1294
+
1295
+ Import: `import "@raylang/elements/switch";` · Category: Inputs
1296
+
1297
+ #### `<ray-switch>` (RaySwitch, extends RayCheckbox)
1298
+
1299
+ Same properties and events as ray-checkbox (indeterminate does not apply).
1300
+
1301
+ Properties:
1302
+
1303
+ - `checked` (attribute `checked`: the initial value only): boolean. Current state. The checked attribute is the initial state.
1304
+ - `value`: string, default `on`. Submitted value when on.
1305
+ - `name`: string. Form field name.
1306
+ - `label`: string. Label text (or the content).
1307
+ - `description`: string. Help text.
1308
+ - `error`: string. Error text.
1309
+ - `labelPosition` (attribute `label-position`): `right` | `left`, default `right`, reflects. Side of the label.
1310
+ - `color`: string. Track color when on.
1311
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Track size.
1312
+ - `disabled`: boolean. Not interactive nor submitted.
1313
+
1314
+ Also the properties of RayCheckbox (`<ray-checkbox>`): `indeterminate`, `required`, `variant`.
1315
+ Also the properties of FieldControl: `radius`, `descriptionPosition`.
1316
+
1317
+ Events:
1318
+
1319
+ - `change`: When the user toggles it.
1320
+
1321
+ Slots:
1322
+
1323
+ - (default): Label content.
1324
+
1325
+ Parts (`::part()`):
1326
+
1327
+ - `track`: The track.
1328
+ - `thumb`: The thumb.
1329
+
1330
+ Vue `v-model`: `checked` (updated on change).
1331
+
1332
+ ### Textarea
1333
+
1334
+ A multi-line text field that can grow with its content. Form-associated.
1335
+
1336
+ Import: `import "@raylang/elements/textarea";` · Category: Inputs
1337
+
1338
+ #### `<ray-textarea>` (RayTextarea, extends FieldControl)
1339
+
1340
+ Also forwards placeholder, autocomplete, minlength, maxlength, spellcheck and wrap. Initial value: the value attribute or the element's text.
1341
+
1342
+ Properties:
1343
+
1344
+ - `value`: string. Current value.
1345
+ - `rows`: number, default `3`. Visible rows (minimum when autosize).
1346
+ - `autosize`: boolean. Grows with the content.
1347
+ - `maxRows` (attribute `max-rows`): number. With autosize: stop growing and scroll after this many rows.
1348
+ - `name`: string. Form field name.
1349
+ - `label`: string. Visible label.
1350
+ - `description`: string. Help text.
1351
+ - `descriptionPosition` (attribute `description-position`): `above` | `below`, default `above`, reflects. The description before the control (help first) or after it, with the error (fields in a row stay aligned).
1352
+ - `error`: string. Error text.
1353
+ - `required`: boolean. Required for form submission.
1354
+ - `disabled`: boolean. Not editable nor submitted.
1355
+ - `readonly`: boolean. Not editable, still submitted.
1356
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Font size.
1357
+ - `variant`: `default` | `filled` | `unstyled`, default `default`, reflects. Box style.
1358
+
1359
+ Also the properties of FieldControl: `radius`.
1360
+
1361
+ Attributes (forwarded to the inner element):
1362
+
1363
+ - `placeholder`: Placeholder text.
1364
+ - `autocomplete`: Forwarded to the inner textarea.
1365
+ - `minlength`: Minimum length.
1366
+ - `maxlength`: Maximum length.
1367
+ - `wrap`: soft or hard.
1368
+
1369
+ Events:
1370
+
1371
+ - `input`: On every edit.
1372
+ - `change`: When an edit is committed.
1373
+
1374
+ Parts (`::part()`):
1375
+
1376
+ - `textarea`: The inner <textarea>.
1377
+ - `wrapper`: The box.
1378
+
1379
+ Vue `v-model`: `value` (updated on input).
1380
+
1381
+ ### Bottom nav
1382
+
1383
+ The bottom navigation of a phone app (Material's navigation bar, the iOS tab bar): three to five destinations with an icon, a label and a badge, the current one marked by a pill. Links or a value; an action button in the middle; hides on scroll.
1384
+
1385
+ Import: `import "@raylang/elements/bottom-nav";` · Category: Navigation
1386
+
1387
+ #### `<ray-bottom-nav>` (RayBottomNav, extends RayElement)
1388
+
1389
+ With href items it marks the link to this page (aria-current="page"); without, it is a control (value, change). Clear of the home indicator (safe-area inset). In a ray-app-shell, put it in the bottom slot.
1390
+
1391
+ Properties:
1392
+
1393
+ - `value`: string, reflects. The current destination (an item's value, else its href, else its label).
1394
+ - `label`: string, default `Main`. Accessible name of the navigation.
1395
+ - `labels`: `always` | `active` | `never`, default `always`, reflects. Which labels show (the others stay for assistive technology).
1396
+ - `indicator`: `pill` | `line` | `none`, default `pill`, reflects. How the current destination is marked besides its color.
1397
+ - `color`: string, reflects. A palette color or any CSS color for the current item and the action (default: primary).
1398
+ - `variant`: `default` | `floating`, default `default`, reflects. default: a bar across the bottom; floating: a rounded bar off the edges.
1399
+ - `hideOnScroll` (attribute `hide-on-scroll`): boolean, reflects. Slides away while the content scrolls down, back on the way up.
1400
+ - `fixed`: boolean, reflects. Pinned to the bottom of the window (outside a shell).
1401
+ - `scrollTarget` (attribute `scroll-target`): string. A selector of the element whose scrolling it follows (default: its shell's, else the window).
1402
+
1403
+ Events:
1404
+
1405
+ - `change`: The user picked another destination (read value).
1406
+ - `ray-select` (detail `{ value: string }`): An action item was pressed.
1407
+
1408
+ Slots:
1409
+
1410
+ - (default): ray-bottom-nav-item elements (3 to 5).
1411
+
1412
+ Parts (`::part()`):
1413
+
1414
+ - `nav`: The <nav>.
1415
+
1416
+ Methods and properties:
1417
+
1418
+ - `readonly items: RayBottomNavItem[]`: The items, in order.
1419
+
1420
+ Vue `v-model`: `value` (updated on change).
1421
+
1422
+ #### `<ray-bottom-nav-item>` (RayBottomNavItem, extends RayElement)
1423
+
1424
+ A link with href, else a button. The badge is read with the label ("Messages, 3").
1425
+
1426
+ Properties:
1427
+
1428
+ - `value`: string, reflects. Its value (default: its href, else its label).
1429
+ - `label`: string. The label.
1430
+ - `icon`: string. An icon of the registry (or put one in the icon slot).
1431
+ - `href`: string, reflects. Makes it a link.
1432
+ - `badge`: string. A count or a short text on the icon.
1433
+ - `dot`: boolean, reflects. A dot on the icon (something new).
1434
+ - `active`: boolean, reflects. Set by the bar: the current destination.
1435
+ - `disabled`: boolean, reflects. Not interactive.
1436
+ - `action`: boolean, reflects. A raised round button ("New"): it fires ray-select on the bar, it is not a destination.
1437
+
1438
+ Slots:
1439
+
1440
+ - `icon`: A custom icon (a ray-icon, an svg, an avatar).
1441
+
1442
+ Parts (`::part()`):
1443
+
1444
+ - `item`: The link or button.
1445
+ - `indicator`: The pill behind the icon.
1446
+ - `badge`: The badge.
1447
+ - `label`: The label.
1448
+
1449
+ ### Breadcrumbs
1450
+
1451
+ Where a page sits (Mantine's Breadcrumbs, the WAI-ARIA breadcrumb pattern): links in a labelled nav, the last one the current page. Any separator or a chevron; a long path collapses into an expandable "…".
1452
+
1453
+ Import: `import "@raylang/elements/breadcrumbs";` · Category: Navigation
1454
+
1455
+ #### `<ray-breadcrumbs>` (RayBreadcrumbs, extends RayElement)
1456
+
1457
+ A <nav aria-label="Breadcrumb"> around a list. The last crumb is the current page (aria-current="page") unless one says current.
1458
+
1459
+ Properties:
1460
+
1461
+ - `separator`: string, default `/`. Text between crumbs ("/", "›", "·") or "chevron" (an icon).
1462
+ - `maxItems` (attribute `max-items`): number. Longer paths show the first crumb, "…" (a button that expands them) and the last max-items − 1.
1463
+ - `label`: string, default `Breadcrumb`. Accessible name of the nav.
1464
+ - `size`: `xs` | `sm` | `md` | `lg`, default `sm`, reflects. Font size.
1465
+
1466
+ Slots:
1467
+
1468
+ - (default): ray-breadcrumb elements.
1469
+
1470
+ Parts (`::part()`):
1471
+
1472
+ - `nav`: The <nav>.
1473
+ - `list`: The <ol>.
1474
+
1475
+ Methods and properties:
1476
+
1477
+ - `readonly items: RayBreadcrumb[]`: The crumbs, in order.
1478
+ - `expand(): void`: Shows every crumb of a collapsed path.
1479
+
1480
+ #### `<ray-breadcrumb>` (RayBreadcrumb, extends RayElement)
1481
+
1482
+ A link with href (text without, or when current).
1483
+
1484
+ Properties:
1485
+
1486
+ - `href`: string, reflects. Where it leads.
1487
+ - `current`: boolean, reflects. This crumb is the current page (default: the last).
1488
+
1489
+ Slots:
1490
+
1491
+ - (default): The text.
1492
+ - `icon`: An icon before the text.
1493
+
1494
+ Parts (`::part()`):
1495
+
1496
+ - `link`: The link (or the text of the current page).
1497
+ - `separator`: The separator before it.
1498
+ - `more`: The "…" button of a collapsed path.
1499
+
1500
+ ### Nav link
1501
+
1502
+ A sidebar/navigation item: icon, label, description, badge, active state, and nested nav links that collapse under it.
1503
+
1504
+ Import: `import "@raylang/elements/nav-link";` · Category: Navigation
1505
+
1506
+ #### `<ray-nav-link>` (RayNavLink, extends RayElement)
1507
+
1508
+ A link with href (aria-current=page when active), or a button that toggles its nested links.
1509
+
1510
+ Properties:
1511
+
1512
+ - `label`: string. Text.
1513
+ - `description`: string. Second line.
1514
+ - `href`: string, reflects. Makes it a link (ignored when it has nested links).
1515
+ - `active`: boolean, reflects. The current page or section.
1516
+ - `opened`: boolean, reflects. Nested links are shown.
1517
+ - `disabled`: boolean, reflects. Not interactive.
1518
+ - `variant`: `light` | `filled` | `subtle`, default `light`, reflects. Style of the active state.
1519
+ - `color`: string, reflects. Active color.
1520
+ - `iconOnly` (attribute `icon-only`): boolean, reflects. Only the icon (left section), centered; the label becomes its accessible name and tooltip. A collapsed ray-sidebar sets it.
1521
+
1522
+ Events:
1523
+
1524
+ - `ray-toggle` (detail `{ opened: boolean }`): Nested links were shown or hidden.
1525
+
1526
+ Slots:
1527
+
1528
+ - (default): Nested ray-nav-link elements.
1529
+ - `left`: Icon.
1530
+ - `right`: Badge or count.
1531
+
1532
+ Parts (`::part()`):
1533
+
1534
+ - `link`: The inner <a> or <button>.
1535
+ - `children`: The nested links.
1536
+
1537
+ Methods and properties:
1538
+
1539
+ - `readonly links: RayNavLink[]`: The nested nav links.
1540
+
1541
+ Vue `v-model`: `opened` (updated on ray-toggle).
1542
+
1543
+ ### Pagination
1544
+
1545
+ Page navigation: previous/next, optional first/last, page numbers with ellipses; the number of items stays constant so it does not jump.
1546
+
1547
+ Import: `import "@raylang/elements/pagination";` · Category: Navigation
1548
+
1549
+ #### `<ray-pagination>` (RayPagination, extends RayElement)
1550
+
1551
+ JS: setPage(n), next(), previous(), first(), last(); page (clamped value).
1552
+
1553
+ Properties:
1554
+
1555
+ - `total`: number, default `1`. Number of pages.
1556
+ - `value`: number, default `1`. Current page (1-based).
1557
+ - `siblings`: number, default `1`. Pages shown on each side of the current one.
1558
+ - `boundaries`: number, default `1`. Pages always shown at the start and the end.
1559
+ - `withEdges` (attribute `with-edges`): boolean, reflects. Adds first/last page buttons.
1560
+ - `hideControls` (attribute `hide-controls`): boolean, reflects. Hides the previous/next (and first/last) buttons.
1561
+ - `color`: string, reflects. Color of the current page: a palette color or any CSS color. Default: the primary color.
1562
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Item size.
1563
+ - `radius`: `xs` | `sm` | `md` | `lg` | `xl` | `full`. Corner radius of the items.
1564
+ - `disabled`: boolean, reflects. Not interactive.
1565
+ - `label`: string, default `Pagination`. Accessible name of the navigation landmark.
1566
+
1567
+ Events:
1568
+
1569
+ - `change`: The user went to another page (read `value`).
1570
+
1571
+ Parts (`::part()`):
1572
+
1573
+ - `root`: The <nav> landmark.
1574
+ - `list`: The list of items.
1575
+ - `item`: Every button (pages and controls).
1576
+ - `active`: The current page button.
1577
+ - `control`: Previous/next/first/last buttons.
1578
+ - `dots`: An ellipsis.
1579
+
1580
+ Methods and properties:
1581
+
1582
+ - `readonly page: number`: The current page clamped to 1…total.
1583
+ - `setPage(page: number): void`: Goes to a page (fires change).
1584
+ - `next(): void`: Next page.
1585
+ - `previous(): void`: Previous page.
1586
+ - `first(): void`: First page.
1587
+ - `last(): void`: Last page.
1588
+
1589
+ Vue `v-model`: `value` (updated on change).
1590
+
1591
+ Exports (from `@raylang/elements/pagination` and `@raylang/elements`):
1592
+
1593
+ - `function paginationRange(total: number, value: number, siblings?: number, boundaries?: number): Array<number | "dots">`: The items a pagination shows for a page (numbers and "dots").
1594
+
1595
+ ### Sidebar
1596
+
1597
+ The side navigation of an app shell: header, content and footer; on wide screens it collapses to an icon rail, below a breakpoint it becomes an off-canvas drawer. toggle() does the right thing for the screen.
1598
+
1599
+ Import: `import "@raylang/elements/sidebar";` · Category: Navigation
1600
+
1601
+ #### `<ray-sidebar>` (RaySidebar, extends RayElement)
1602
+
1603
+ Put ray-sidebar-group + ray-nav-link (with an icon in slot=left) inside. Collapsed, nav links show only their icon (the label becomes the tooltip) and the host has the collapsed attribute, so your own header/footer content can hide with CSS (ray-sidebar[collapsed] .brand-name { display: none }).
1604
+
1605
+ Properties:
1606
+
1607
+ - `collapsed`: boolean, reflects. Wide screens: an icon rail instead of the full panel.
1608
+ - `open`: boolean, reflects. Narrow screens: the drawer is shown (modal, focus trapped; Escape, backdrop click or a followed link close it).
1609
+ - `side`: `left` | `right`, default `left`, reflects. The edge it sits on.
1610
+ - `variant`: `sidebar` | `floating`, default `sidebar`, reflects. A panel against the edge, or a floating card with a margin.
1611
+ - `width`: string. Width when expanded (CSS length). Default 16rem.
1612
+ - `collapsedWidth` (attribute `collapsed-width`): string. Width of the icon rail. Default 3.5rem.
1613
+ - `breakpoint`: string, default `48em`. At this viewport width and below, it becomes a drawer.
1614
+ - `label`: string, default `Sidebar`. Accessible name of its navigation.
1615
+
1616
+ Events:
1617
+
1618
+ - `ray-toggle` (detail `{ collapsed: boolean; open: boolean; mobile: boolean }`): After toggle().
1619
+ - `ray-open`: The drawer opened (narrow screens).
1620
+ - `ray-close`: The drawer closed (narrow screens).
1621
+
1622
+ Slots:
1623
+
1624
+ - (default): The navigation: ray-sidebar-group and ray-nav-link elements.
1625
+ - `header`: Top area (brand, workspace switcher).
1626
+ - `footer`: Bottom area (user, settings).
1627
+
1628
+ Parts (`::part()`):
1629
+
1630
+ - `panel`: The panel (in the drawer on narrow screens).
1631
+ - `header`: The header area.
1632
+ - `content`: The scrolling <nav>.
1633
+ - `footer`: The footer area.
1634
+ - `drawer`: The <dialog> used on narrow screens.
1635
+
1636
+ Methods and properties:
1637
+
1638
+ - `toggle(): void`: Collapses/expands on wide screens; opens/closes the drawer on narrow ones.
1639
+ - `readonly mobile: boolean`: Whether it is in drawer mode (at or below the breakpoint).
1640
+
1641
+ #### `<ray-sidebar-group>` (RaySidebarGroup, extends RayElement)
1642
+
1643
+ A titled section of nav links; the title fades out (keeping its height) when the sidebar collapses.
1644
+
1645
+ Properties:
1646
+
1647
+ - `label`: string. Section title.
1648
+
1649
+ Slots:
1650
+
1651
+ - (default): ray-nav-link elements.
1652
+
1653
+ Parts (`::part()`):
1654
+
1655
+ - `label`: The title.
1656
+ - `items`: The links container.
1657
+
1658
+ ### Stepper
1659
+
1660
+ A task in steps (Mantine's Stepper): a wizard, a checkout, an onboarding. Numbers or icons, labels, connectors, the content of the active step; loading and error states; completed steps can be revisited.
1661
+
1662
+ Import: `import "@raylang/elements/stepper";` · Category: Navigation
1663
+
1664
+ #### `<ray-stepper>` (RayStepper, extends RayElement)
1665
+
1666
+ The steps are a labelled list; the active one has aria-current="step" and each reads "Step 2 of 4: Shipping, completed". Only the active step's content shows; past the last step, the completed slot.
1667
+
1668
+ Properties:
1669
+
1670
+ - `active`: number, default `0`, reflects. Index of the active step (steps.length: completed).
1671
+ - `orientation`: `horizontal` | `vertical`, default `horizontal`, reflects. Steps in a row above the content, or in a column beside it.
1672
+ - `iconPosition` (attribute `icon-position`): `left` | `top`, default `left`, reflects. Label beside the number, or under it (narrow screens, many steps).
1673
+ - `allowStepSelect` (attribute `allow-step-select`): boolean, reflects. Completed steps are buttons that go back to them.
1674
+ - `linear`: boolean, default `true`. With allow-step-select off, false lets the user jump to any step.
1675
+ - `size`: `sm` | `md` | `lg`, default `md`, reflects. Size of the numbers.
1676
+ - `color`: string, reflects. A palette color or any CSS color for active and completed steps (default: primary).
1677
+ - `label`: string, default `Progress`. Accessible name of the list of steps.
1678
+
1679
+ Events:
1680
+
1681
+ - `change`: active changed by the user (a step clicked, next(), prev()).
1682
+
1683
+ Slots:
1684
+
1685
+ - (default): ray-step elements.
1686
+ - `completed`: Shown once every step is done.
1687
+
1688
+ Parts (`::part()`):
1689
+
1690
+ - `steps`: The list of steps.
1691
+ - `step`: A step (also step-done, step-active, step-todo).
1692
+ - `indicator`: A step's number or icon.
1693
+ - `label`: A step's label.
1694
+ - `description`: A step's description.
1695
+ - `connector`: The line between steps.
1696
+ - `content`: The content area.
1697
+
1698
+ Methods and properties:
1699
+
1700
+ - `readonly steps: RayStep[]`: The steps, in order.
1701
+ - `next(): void`: To the next step (past the last: completed).
1702
+ - `prev(): void`: To the previous step.
1703
+
1704
+ Vue `v-model`: `active` (updated on change).
1705
+
1706
+ #### `<ray-step>` (RayStep, extends RayElement)
1707
+
1708
+ A step: its header is drawn by the stepper, its content shows while it is active.
1709
+
1710
+ Properties:
1711
+
1712
+ - `label`: string. The label.
1713
+ - `description`: string. A line under the label.
1714
+ - `icon`: string. An icon instead of the number.
1715
+ - `completedIcon` (attribute `completed-icon`): string. The icon once done (default: check).
1716
+ - `loading`: boolean, reflects. A spinner instead of the number.
1717
+ - `error`: string. An error message: red step, the message as its description.
1718
+ - `disabled`: boolean, reflects. Cannot be selected.
1719
+
1720
+ Slots:
1721
+
1722
+ - (default): The content shown while it is active.
1723
+
1724
+ ### Tabs
1725
+
1726
+ Tabs and panels (WAI-ARIA tabs pattern): arrows, Home/End, automatic or manual activation.
1727
+
1728
+ Import: `import "@raylang/elements/tabs";` · Category: Navigation
1729
+
1730
+ #### `<ray-tabs>` (RayTabs, extends RayElement)
1731
+
1732
+ Properties:
1733
+
1734
+ - `value`: string. Value of the active tab (default: the first enabled one).
1735
+ - `variant`: `default` | `outline` | `pills`, default `default`, reflects. Tab style.
1736
+ - `orientation`: `horizontal` | `vertical`, default `horizontal`, reflects. Tab list direction (and arrow keys).
1737
+ - `color`: string, reflects. Active indicator color.
1738
+ - `activation`: `auto` | `manual`, default `auto`. manual: arrows move focus, Enter/Space activates.
1739
+ - `grow`: boolean, reflects. Tabs share the full width.
1740
+
1741
+ Events:
1742
+
1743
+ - `change`: The user activated another tab.
1744
+
1745
+ Slots:
1746
+
1747
+ - (default): ray-tab and ray-tab-panel elements (tabs move to the tab list on their own).
1748
+
1749
+ Parts (`::part()`):
1750
+
1751
+ - `list`: The tab list.
1752
+ - `panels`: The panel area.
1753
+
1754
+ Methods and properties:
1755
+
1756
+ - `readonly tabs: RayTab[]`: The tabs.
1757
+ - `readonly panels: RayTabPanel[]`: The panels.
1758
+
1759
+ Vue `v-model`: `value` (updated on change).
1760
+
1761
+ #### `<ray-tab>` (RayTab, extends RayElement)
1762
+
1763
+ Properties:
1764
+
1765
+ - `value`: string, reflects. Matches a ray-tab-panel's value.
1766
+ - `disabled`: boolean, reflects. Cannot be activated.
1767
+
1768
+ Slots:
1769
+
1770
+ - `left`: Icon.
1771
+ - `right`: Badge or count.
1772
+
1773
+ #### `<ray-tab-panel>` (RayTabPanel, extends RayElement)
1774
+
1775
+ Properties:
1776
+
1777
+ - `value`: string, reflects. Matches a ray-tab's value.
1778
+
1779
+ ### Command palette
1780
+
1781
+ Search and run actions from the keyboard (Mantine's Spotlight): fuzzy search, groups, shortcuts, ⌘K / Ctrl+K; combobox + listbox pattern in a modal dialog.
1782
+
1783
+ Import: `import "@raylang/elements/command-palette";` · Category: Overlays
1784
+
1785
+ #### `<ray-command-palette>` (RayCommandPalette, extends RayElement)
1786
+
1787
+ Running an action fires ray-select and calls its onSelect. The best matches come first, grouped.
1788
+
1789
+ Properties:
1790
+
1791
+ - `open`: boolean, reflects. Shown.
1792
+ - `actions` (property only): `CommandAction[]`. The actions.
1793
+ - `query`: string. The search text.
1794
+ - `placeholder`: string, default `Search commands…`. Placeholder of the search field.
1795
+ - `hotkey`: string, default `mod+k`. Toggle shortcut (mod = ⌘ on macOS, Ctrl elsewhere); empty to disable.
1796
+ - `limit`: number, default `50`. Maximum results.
1797
+ - `emptyLabel` (attribute `empty-label`): string, default `Nothing found`. Text without results.
1798
+ - `label`: string, default `Command palette`. Accessible name.
1799
+ - `hideHint` (attribute `hide-hint`): boolean, reflects. No keyboard hint at the bottom.
1800
+ - `nativeMenus` (attribute `native-menus`): boolean, reflects. With a native host (ray-elements/core/raylang.js in a std/ui window, menus declared with elements/bridge), also lists the app's menu bar, grouped by menu with its shortcuts; running one gives the program the menu's own event.
1801
+ - `overlayBlur` (attribute `overlay-blur`): string. Blur of the page behind: px ("8"), a CSS length or "none". Default: --ray-overlay-blur ([overlay] blur in tokens.toml).
1802
+
1803
+ Events:
1804
+
1805
+ - `ray-select` (detail `{ action: CommandAction }`): An action was run.
1806
+ - `ray-open`: After it opened.
1807
+ - `ray-close`: After it closed.
1808
+
1809
+ Parts (`::part()`):
1810
+
1811
+ - `dialog`: The dialog.
1812
+ - `input`: The search field.
1813
+ - `option`: Each result.
1814
+
1815
+ Methods and properties:
1816
+
1817
+ - `show(): void`: Opens it.
1818
+ - `hide(): void`: Closes it.
1819
+ - `toggle(): void`: Opens or closes it.
1820
+ - `readonly results: CommandAction[]`: The actions matching the query, in display order.
1821
+
1822
+ Vue `v-model`: `open` (updated on ray-open, ray-close).
1823
+
1824
+ Exports (from `@raylang/elements/command-palette` and `@raylang/elements`):
1825
+
1826
+ - `function score(action: CommandAction, query: string): number`: How well an action matches a query (0 = not at all).
1827
+
1828
+ Types:
1829
+
1830
+ - `{ id?: string; label: string; description?: string; group?: string; keywords?: string | string[]; shortcut?: string; icon?: string | Node; disabled?: boolean; native?: boolean; tag?: string; onSelect?: (action: CommandAction) => void }`: An action of ray-command-palette.
1831
+
1832
+ #### In a raylang app
1833
+
1834
+ With `native-menus` and [the native bridge](https://elements.raylang.dev/raylang.html#using-the-bridge), the palette also lists the app's menu bar: every item, grouped by its menu, with its shortcut, the disabled ones greyed out. Running one gives the program the same `"menu"` event as choosing it in the menu bar, so the program handles it in one place.
1835
+
1836
+ ```ray
1837
+ let n = bridge.system();
1838
+ bridge.menu(n, "File", [ui.item("new", "New window", "cmd+n"), ui.item("open", "Open…", "cmd+o")])?;
1839
+ for raw in ui.events() {
1840
+ let e = match (bridge.route(n, raw)) {
1841
+ Option.Some(e) => e,
1842
+ Option.None => continue,
1843
+ };
1844
+ if (e.kind == "menu" && e.tag == "new") {
1845
+ new_window()?;
1846
+ }
1847
+ }
1848
+ ```
1849
+
1850
+ ```html
1851
+ <ray-command-palette native-menus></ray-command-palette>
1852
+ ```
1853
+
1854
+ Declare the menus with `bridge.menu` (and change them with `bridge.replace_menu` and `bridge.set_menu_item`) so the palette knows them.
1855
+
1856
+ ### Dialog (also Modal)
1857
+
1858
+ ray-elements's modal, on the native <dialog>: top layer, the rest of the page inert, focus trapped and restored, stackable. Title, description, header, body and footer; preset or free sizes. Also exports confirmDialog().
1859
+
1860
+ Import: `import "@raylang/elements/dialog";` · Category: Overlays
1861
+
1862
+ #### `<ray-dialog>` (RayDialog, extends RayElement)
1863
+
1864
+ Any slotted element with data-dialog-close closes it (its value becomes returnValue). JS: show(), close(returnValue), confirmDialog({ label, message, confirmLabel, cancelLabel, color, native }) -> Promise<boolean>; with a native host (ray-elements/core/raylang.js in a std/ui window) it asks with the system dialog unless native is false.
1865
+
1866
+ Properties:
1867
+
1868
+ - `open`: boolean, reflects. Shown as a modal.
1869
+ - `label`: string. Heading (also the dialog's accessible name).
1870
+ - `description`: string. A line under the title (the dialog's accessible description).
1871
+ - `size`: `"xs" | "sm" | "md" | "lg" | "xl" | "full" | (string & {})`, default `md`, reflects. Width: xs…xl, full (the whole window), or any CSS length; a percentage is of the window (70% = 70vw, at least 40rem). Never wider than the window.
1872
+ - `height`: string, reflects. Fixed height (the body scrolls): any CSS length; a percentage is of the window (70% = 70dvh, at least 30rem). Never taller than the window. Default: as tall as the content, up to the window.
1873
+ - `radius`: string, reflects. Corner radius: xs…xl, none, or a CSS length. Default: lg.
1874
+ - `position`: `center` | `top`, default `center`, reflects. Vertical placement.
1875
+ - `persistent`: boolean, reflects. Escape and backdrop clicks do not close it (the × still does; hide it with hide-close). To allow only one of them, cancel ray-request-close by its source.
1876
+ - `hideClose` (attribute `hide-close`): boolean, reflects. No close button in the header.
1877
+ - `overlayBlur` (attribute `overlay-blur`): string. Blur of the page behind: px ("8"), a CSS length or "none". Default: --ray-overlay-blur ([overlay] blur in tokens.toml).
1878
+
1879
+ Events:
1880
+
1881
+ - `ray-open`: After it opened.
1882
+ - `ray-close` (detail `{ returnValue: string }`): After it closed; detail: { returnValue }.
1883
+ - `ray-request-close` (detail `{ source: "escape" | "backdrop" | "button" }`): Escape, backdrop or close button; cancelable (preventDefault keeps it open). detail: { source }.
1884
+
1885
+ Slots:
1886
+
1887
+ - (default): Body.
1888
+ - `header`: Extra header content, next to the title.
1889
+ - `footer`: Actions, aligned to the end.
1890
+
1891
+ Parts (`::part()`):
1892
+
1893
+ - `dialog`: The native <dialog>.
1894
+ - `title`: The heading.
1895
+ - `description`: The line under the heading.
1896
+ - `header`: The header: title, description, the header slot and the close button.
1897
+ - `body`: The scrollable body.
1898
+ - `footer`: The footer.
1899
+ - `close`: The close button.
1900
+
1901
+ Methods and properties:
1902
+
1903
+ - `show(): void`: Opens it.
1904
+ - `close(returnValue?: string): void`: Closes it with an optional return value.
1905
+ - `returnValue: string`: The value it was closed with.
1906
+
1907
+ Vue `v-model`: `open` (updated on ray-open, ray-close).
1908
+
1909
+ Exports (from `@raylang/elements/dialog` and `@raylang/elements`):
1910
+
1911
+ - `function confirmDialog(options?: ConfirmOptions): Promise<boolean>`: A confirmation dialog; resolves true when confirmed. With a native host, the system dialog (native: false keeps the ray-dialog).
1912
+
1913
+ Types:
1914
+
1915
+ - `{ label?: string; message?: string; confirmLabel?: string; cancelLabel?: string; color?: string; native?: boolean }`: Options of confirmDialog().
1916
+
1917
+ #### In a raylang app
1918
+
1919
+ With [the native bridge](https://elements.raylang.dev/raylang.html#using-the-bridge), `confirmDialog()` asks with the system's modal dialog instead of a `ray-dialog`, with the same answer. A red confirmation (a destructive action) gets the warning style. `native: false` keeps the page's dialog, for a question that needs more than a sentence.
1920
+
1921
+ ```js
1922
+ if (await confirmDialog({ label: "Delete 3 builds?", message: "This cannot be undone.", confirmLabel: "Delete", color: "red" })) {
1923
+ window.ray.send("delete:" + ids.join(","));
1924
+ }
1925
+ ```
1926
+
1927
+ `ray-dialog` itself is always the page's: a form, a settings panel or a wizard stay in the page.
1928
+
1929
+ ### Drawer
1930
+
1931
+ A panel sliding in from an edge: a RayDialog (focus, Escape, persistent, data-dialog-close, returnValue) with another look; modeless for side panels that keep the page interactive.
1932
+
1933
+ Import: `import "@raylang/elements/drawer";` · Category: Overlays
1934
+
1935
+ #### `<ray-drawer>` (RayDrawer, extends RayElement)
1936
+
1937
+ Any slotted element with data-dialog-close closes it. JS: show(), close(returnValue).
1938
+
1939
+ Properties:
1940
+
1941
+ - `open`: boolean, reflects. Shown.
1942
+ - `label`: string. Heading (also the accessible name).
1943
+ - `description`: string. A line under the title (the drawer's accessible description).
1944
+ - `position`: `right` | `left` | `top` | `bottom`, default `right`, reflects. The edge it slides from.
1945
+ - `size`: `"xs" | "sm" | "md" | "lg" | "xl" | "full" | (string & {})`, default `md`, reflects. Width (left/right) or height (top/bottom): xs…xl, full, or any CSS length.
1946
+ - `modeless`: boolean, reflects. No backdrop nor scroll lock: the page stays interactive (a side panel).
1947
+ - `floating`: boolean, reflects. Detached from the edge, with rounded corners.
1948
+ - `persistent`: boolean, reflects. Escape and backdrop clicks do not close it.
1949
+ - `hideClose` (attribute `hide-close`): boolean, reflects. No close button in the header.
1950
+ - `overlayBlur` (attribute `overlay-blur`): string. Blur of the page behind: px ("8"), a CSS length or "none". Default: --ray-overlay-blur ([overlay] blur in tokens.toml).
1951
+
1952
+ Events:
1953
+
1954
+ - `ray-open`: After it opened.
1955
+ - `ray-close` (detail `{ returnValue: string }`): After it closed; detail: { returnValue }.
1956
+ - `ray-request-close` (detail `{ source: "escape" | "backdrop" | "button" }`): Escape, backdrop or close button; cancelable.
1957
+
1958
+ Slots:
1959
+
1960
+ - (default): Body (scrolls).
1961
+ - `header`: Extra header content.
1962
+ - `footer`: Actions, at the bottom.
1963
+
1964
+ Parts (`::part()`):
1965
+
1966
+ - `drawer`: The native <dialog>.
1967
+ - `body`: The body.
1968
+
1969
+ Methods and properties:
1970
+
1971
+ - `show(): void`: Opens it.
1972
+ - `close(returnValue?: string): void`: Closes it with an optional return value.
1973
+ - `returnValue: string`: The value it was closed with.
1974
+
1975
+ Vue `v-model`: `open` (updated on ray-open, ray-close).
1976
+
1977
+ ### Menu
1978
+
1979
+ A dropdown menu (menu button pattern: arrows, Home/End, typeahead, Enter, Escape) or, with context, a context menu at the pointer.
1980
+
1981
+ Import: `import "@raylang/elements/menu";` · Category: Overlays
1982
+
1983
+ #### `<ray-menu>` (RayMenu, extends Floating)
1984
+
1985
+ Properties:
1986
+
1987
+ - `open`: boolean, reflects. Shown.
1988
+ - `placement`: `bottom-start` | `bottom` | `bottom-end` | `top-start` | `top` | `top-end` | `right-start` | `left-start`, default `bottom-start`, reflects. Preferred side and alignment.
1989
+ - `context`: boolean, reflects. Opens on right click (contextmenu) over the trigger area, at the pointer.
1990
+ - `keepOpen` (attribute `keep-open`): boolean, reflects. Choosing an item does not close the menu.
1991
+ - `native`: boolean, reflects. With a native host (ray-elements/core/raylang.js in a std/ui window), opens as the system's context menu at the pointer: items and dividers, same ray-select.
1992
+
1993
+ Also the properties of Floating: `offset`.
1994
+
1995
+ Events:
1996
+
1997
+ - `ray-select` (detail `{ value: string; item: RayMenuItem }`): An item was chosen; detail: { value, item }.
1998
+ - `ray-open`: After it opened.
1999
+ - `ray-close`: After it closed.
2000
+
2001
+ Slots:
2002
+
2003
+ - `trigger`: The button that opens it, or the area for a context menu.
2004
+ - (default): ray-menu-item, ray-menu-label and ray-menu-divider elements.
2005
+
2006
+ Parts (`::part()`):
2007
+
2008
+ - `dropdown`: The panel.
2009
+
2010
+ Methods and properties:
2011
+
2012
+ - `popupNative(): Promise<RayMenuItem | null>`: Opens the items as the system's context menu (needs a native host); resolves to the chosen item, or null.
2013
+ - `show(): void`: Opens it.
2014
+ - `hide(): void`: Closes it.
2015
+ - `toggle(): void`: Opens or closes it.
2016
+ - `readonly trigger: Element | null`: The trigger element.
2017
+ - `readonly items: RayMenuItem[]`: The items of this menu.
2018
+
2019
+ Vue `v-model`: `open` (updated on ray-open, ray-close).
2020
+
2021
+ #### `<ray-menu-item>` (RayMenuItem, extends RayElement)
2022
+
2023
+ Properties:
2024
+
2025
+ - `value`: string, reflects. Reported in ray-select (default: the text).
2026
+ - `disabled`: boolean, reflects. Skipped by the keyboard, cannot be chosen.
2027
+ - `color`: string, reflects. Text and hover color (e.g. red for destructive actions).
2028
+
2029
+ Slots:
2030
+
2031
+ - (default): Label.
2032
+ - `left`: Icon.
2033
+ - `right`: Shortcut or badge.
2034
+
2035
+ #### `<ray-menu-label>` (RayMenuLabel, extends RayElement)
2036
+
2037
+ A section caption inside the menu.
2038
+
2039
+ #### `<ray-menu-divider>` (RayMenuDivider, extends RayElement)
2040
+
2041
+ A separator between groups of items.
2042
+
2043
+ #### In a raylang app
2044
+
2045
+ With `native` and [the native bridge](https://elements.raylang.dev/raylang.html#using-the-bridge), the menu opens as the system's context menu at the pointer: its items and dividers, disabled ones greyed out. The choice fires the same `ray-select`, so the same code handles both.
2046
+
2047
+ ```html
2048
+ <ray-menu native context>
2049
+ <div slot="trigger" class="file-row">report.csv</div>
2050
+ <ray-menu-item value="open">Open</ray-menu-item>
2051
+ <ray-menu-item value="reveal">Show in Finder</ray-menu-item>
2052
+ <ray-menu-divider></ray-menu-divider>
2053
+ <ray-menu-item value="delete" color="red">Delete</ray-menu-item>
2054
+ </ray-menu>
2055
+ ```
2056
+
2057
+ Labels, nested menus, icons and colors are the page menu's only. A dismissed native menu fires nothing.
2058
+
2059
+ ### Popover
2060
+
2061
+ A floating panel anchored to a trigger, in the top layer; closes on Escape and outside clicks.
2062
+
2063
+ Import: `import "@raylang/elements/popover";` · Category: Overlays
2064
+
2065
+ #### `<ray-popover>` (RayPopover, extends Floating)
2066
+
2067
+ Positioned in JS (flip + shift to stay in the viewport). JS: show(), hide(), toggle().
2068
+
2069
+ Properties:
2070
+
2071
+ - `open`: boolean, reflects. Shown.
2072
+ - `placement`: `bottom` | `bottom-start` | `bottom-end` | `top` | `top-start` | `top-end` | `left` | `left-start` | `left-end` | `right` | `right-start` | `right-end`, default `bottom`, reflects. Preferred side and alignment.
2073
+ - `offset`: number, default `8`. Gap to the trigger in px.
2074
+ - `width`: string. Panel width (px number or CSS length). Default: its content.
2075
+ - `matchWidth` (attribute `match-width`): boolean. At least as wide as the trigger.
2076
+ - `padding`: `0` | `xs` | `sm` | `md` | `lg`, default `md`, reflects. Panel padding.
2077
+ - `trapFocus` (attribute `trap-focus`): boolean. Moves focus into the panel when opened and keeps Tab inside it.
2078
+
2079
+ Events:
2080
+
2081
+ - `ray-open`: After it opened.
2082
+ - `ray-close`: After it closed (also by Escape or an outside click).
2083
+
2084
+ Slots:
2085
+
2086
+ - `trigger`: The element that toggles it (gets aria-haspopup and aria-expanded).
2087
+ - (default): Panel content.
2088
+
2089
+ Parts (`::part()`):
2090
+
2091
+ - `dropdown`: The panel.
2092
+
2093
+ Methods and properties:
2094
+
2095
+ - `show(): void`: Opens it.
2096
+ - `hide(): void`: Closes it.
2097
+ - `toggle(): void`: Opens or closes it.
2098
+ - `readonly trigger: Element | null`: The trigger element.
2099
+
2100
+ Vue `v-model`: `open` (updated on ray-open, ray-close).
2101
+
2102
+ ### Tooltip
2103
+
2104
+ A short hint on hover and focus of its child; the label also becomes the child's accessible description.
2105
+
2106
+ Import: `import "@raylang/elements/tooltip";` · Category: Overlays
2107
+
2108
+ #### `<ray-tooltip>` (RayTooltip, extends Floating)
2109
+
2110
+ Properties:
2111
+
2112
+ - `label`: string. Tooltip text.
2113
+ - `placement`: `top` | `bottom` | `left` | `right` | `top-start` | `top-end` | `bottom-start` | `bottom-end`, default `top`, reflects. Preferred side.
2114
+ - `openDelay` (attribute `open-delay`): number, default `300`. ms before showing.
2115
+ - `closeDelay` (attribute `close-delay`): number, default `0`. ms before hiding.
2116
+ - `color`: string. A palette color or any CSS color. Default: inverted foreground/background.
2117
+ - `disabled`: boolean. Never shows.
2118
+
2119
+ Also the properties of Floating: `open`, `offset`.
2120
+
2121
+ Slots:
2122
+
2123
+ - (default): The element the tooltip describes (one element).
2124
+
2125
+ Parts (`::part()`):
2126
+
2127
+ - `tooltip`: The tooltip box.
2128
+
2129
+ Methods and properties:
2130
+
2131
+ - `show(): void`: Opens it.
2132
+ - `hide(): void`: Closes it.
2133
+ - `toggle(): void`: Opens or closes it.
2134
+ - `readonly trigger: Element | null`: The trigger element.
2135
+
2136
+ ### Accordion
2137
+
2138
+ Collapsible sections (WAI-ARIA accordion pattern); one open at a time, or several with multiple.
2139
+
2140
+ Import: `import "@raylang/elements/accordion";` · Category: Data display
2141
+
2142
+ #### `<ray-accordion>` (RayAccordion, extends RayElement)
2143
+
2144
+ Properties:
2145
+
2146
+ - `value`: `string | string[] | undefined`. Open item's value; with multiple, an array (attribute: comma-separated).
2147
+ - `multiple`: boolean, reflects. Several items may be open.
2148
+ - `variant`: `default` | `contained` | `separated` | `filled`, default `default`, reflects. Visual style.
2149
+ - `chevronPosition` (attribute `chevron-position`): `right` | `left`, default `right`, reflects. Side of the chevron.
2150
+
2151
+ Events:
2152
+
2153
+ - `change`: The user opened or closed an item.
2154
+
2155
+ Slots:
2156
+
2157
+ - (default): ray-accordion-item elements.
2158
+
2159
+ Methods and properties:
2160
+
2161
+ - `readonly items: RayAccordionItem[]`: The items.
2162
+ - `readonly openValues: string[]`: The open values as an array, whatever the mode.
2163
+
2164
+ Vue `v-model`: `value` (updated on change).
2165
+
2166
+ #### `<ray-accordion-item>` (RayAccordionItem, extends RayElement)
2167
+
2168
+ Properties:
2169
+
2170
+ - `value`: string, reflects. Identifies the item in the accordion's value.
2171
+ - `label`: string. Header text (or slot=label).
2172
+ - `description`: string. A secondary line under the label, in the header.
2173
+ - `disabled`: boolean, reflects. Cannot be toggled.
2174
+ - `headingLevel` (attribute `heading-level`): number, default `3`. aria-level of the header.
2175
+
2176
+ Slots:
2177
+
2178
+ - (default): Panel content.
2179
+ - `label`: Rich header content.
2180
+ - `left`: Icon before the label.
2181
+
2182
+ Parts (`::part()`):
2183
+
2184
+ - `control`: The header button.
2185
+ - `description`: The secondary line under the label.
2186
+ - `panel`: The collapsible region.
2187
+
2188
+ Methods and properties:
2189
+
2190
+ - `readonly open: boolean`: Whether this item is expanded.
2191
+
2192
+ ### Attachment
2193
+
2194
+ A file in a composer, upload list or chat: thumbnail or type icon, name, size, upload progress, error, remove and download.
2195
+
2196
+ Import: `import "@raylang/elements/attachment";` · Category: Data display
2197
+
2198
+ #### `<ray-attachment>` (RayAttachment, extends RayElement)
2199
+
2200
+ Assign a File to `file` to fill name, size, type and an image thumbnail. Removing it (× button) fires a cancelable ray-remove and then removes the element.
2201
+
2202
+ Properties:
2203
+
2204
+ - `name`: string, reflects. File name (ellipsized; full name in the tooltip).
2205
+ - `size`: number. Size in bytes, shown as "12 KB", "3.4 MB".
2206
+ - `type`: string, reflects. MIME type: picks the icon (image or file) and, with the name, the extension badge.
2207
+ - `src`: string. Thumbnail URL for images (falls back to the icon if it fails to load).
2208
+ - `href`: string, reflects. Makes the name a download link.
2209
+ - `progress`: number. Upload progress 0–100: a thin bar and "Uploading… 45%". Unset: done.
2210
+ - `status`: `uploading` | `done` | `error`, reflects. Explicit state. Default: "uploading" while progress is set, else "done".
2211
+ - `error`: string. Error text shown with status="error" (default "Upload failed").
2212
+ - `removable`: boolean, reflects. Shows a remove (×) button.
2213
+ - `removeLabel` (attribute `remove-label`): string, default `Remove {name}`. Accessible label of the remove button; {name} is replaced by the file name.
2214
+ - `variant`: `row` | `card`, default `row`, reflects. row: a compact chip; card: the thumbnail on top.
2215
+ - `disabled`: boolean, reflects. Dimmed, not removable, the name is not a link.
2216
+
2217
+ Events:
2218
+
2219
+ - `ray-remove` (detail `{ name: string; file: File | null }`): The remove button was pressed; cancelable (preventDefault keeps the element).
2220
+
2221
+ Parts (`::part()`):
2222
+
2223
+ - `item`: The box.
2224
+ - `thumbnail`: The thumbnail or icon box.
2225
+ - `badge`: The extension badge (PDF, PNG…).
2226
+ - `name`: The file name (a link with href).
2227
+ - `meta`: Size, upload state or error.
2228
+ - `progress`: The upload progress bar.
2229
+ - `remove`: The remove button.
2230
+
2231
+ Methods and properties:
2232
+
2233
+ - `file: File | null`: The File shown (fills name, size, type and a thumbnail for images).
2234
+ - `readonly state: "uploading" | "done" | "error"`: The effective status.
2235
+
2236
+ #### `<ray-attachments>` (RayAttachments, extends RayElement)
2237
+
2238
+ A wrapping row of ray-attachment elements.
2239
+
2240
+ Slots:
2241
+
2242
+ - (default): ray-attachment elements.
2243
+
2244
+ ### Avatar
2245
+
2246
+ An image, the initials of a name, or a placeholder icon.
2247
+
2248
+ Import: `import "@raylang/elements/avatar";` · Category: Data display
2249
+
2250
+ #### `<ray-avatar>` (RayAvatar, extends RayElement)
2251
+
2252
+ Properties:
2253
+
2254
+ - `src`: string, reflects. Image URL; falls back to initials if it fails to load.
2255
+ - `alt`: string, reflects. Accessible name (default: name).
2256
+ - `name`: string, reflects. Person or entity name; its initials are shown without an image.
2257
+ - `color`: string. A palette color or any CSS color.
2258
+ - `variant`: `light` | `filled` | `outline` | `default`, default `light`, reflects. Style of the initials/placeholder.
2259
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `md`, reflects. Diameter.
2260
+ - `radius`: `xs` | `sm` | `md` | `lg` | `xl` | `full`. Corner radius. Default: full.
2261
+
2262
+ Slots:
2263
+
2264
+ - (default): Custom content (e.g. an icon) instead of initials.
2265
+
2266
+ Parts (`::part()`):
2267
+
2268
+ - `avatar`: The box.
2269
+ - `image`: The <img>.
2270
+
2271
+ Exports (from `@raylang/elements/avatar` and `@raylang/elements`):
2272
+
2273
+ - `function initials(name: string): string`: Up to two initials of a name: "Ada Lovelace" -> "AL".
2274
+
2275
+ ### Badge
2276
+
2277
+ A short status label.
2278
+
2279
+ Import: `import "@raylang/elements/badge";` · Category: Data display
2280
+
2281
+ #### `<ray-badge>` (RayBadge, extends RayElement)
2282
+
2283
+ Properties:
2284
+
2285
+ - `variant`: `light` | `filled` | `outline` | `dot` | `default` | `gradient`, default `light`, reflects. Visual style.
2286
+ - `gradient`: string, reflects. With variant=gradient: "from to [deg]", palette colors or CSS colors ("teal blue 90"). Default: the --ray-gradient-* tokens.
2287
+ - `color`: string. A palette color or any CSS color.
2288
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Height and font size.
2289
+ - `radius`: `xs` | `sm` | `md` | `lg` | `xl` | `full`. Corner radius. Default: full.
2290
+ - `normalCase` (attribute `normal-case`): boolean. Keeps the text as written instead of uppercase.
2291
+
2292
+ Slots:
2293
+
2294
+ - (default): The text.
2295
+
2296
+ Parts (`::part()`):
2297
+
2298
+ - `badge`: The badge box.
2299
+
2300
+ ### Blockquote
2301
+
2302
+ A quotation set apart from the text (Mantine's Blockquote): a colored edge, a quote mark on it and the attribution below. A real <blockquote> inside, with the source's URL as its cite.
2303
+
2304
+ Import: `import "@raylang/elements/blockquote";` · Category: Data display
2305
+
2306
+ #### `<ray-blockquote>` (RayBlockquote, extends RayElement)
2307
+
2308
+ Paragraphs in it are spaced and the last one has no bottom margin. The attribution is text (cite) or rich content (slot="cite": an avatar, a name, a role).
2309
+
2310
+ Properties:
2311
+
2312
+ - `cite`: string. Who said it, shown below the quote ("— Grace Hopper").
2313
+ - `href`: string. URL of the source: the inner blockquote's cite attribute.
2314
+ - `color`: string, reflects. A palette color or any CSS color, for the edge, the mark and the tint. Default: the primary.
2315
+ - `variant`: `light` | `outline` | `filled`, default `light`, reflects. light: tinted background; outline: border and edge only; filled: solid color (a pull quote).
2316
+ - `icon`: string, default `quote`. Registry icon of the mark, or none. The icon slot replaces it.
2317
+ - `size`: `sm` | `md` | `lg`, default `md`, reflects. Text size (lg for a pull quote).
2318
+ - `padding`: string, reflects. Inner spacing: xs…xl (the spacing scale), px as a number, or a CSS length. Default: md.
2319
+ - `hideEdge` (attribute `hide-edge`): boolean, reflects. No colored edge on the start side (the tint, border and mark stay).
2320
+ - `radius`: string, reflects. Corner radius: xs…xl, none, or a CSS length. Default: md.
2321
+
2322
+ Slots:
2323
+
2324
+ - (default): The quotation (text or paragraphs).
2325
+ - `cite`: Rich attribution, instead of cite.
2326
+ - `icon`: A custom mark, instead of icon.
2327
+
2328
+ Parts (`::part()`):
2329
+
2330
+ - `quote`: The <blockquote>.
2331
+ - `icon`: The disc with the mark.
2332
+ - `cite`: The attribution (a <figcaption>).
2333
+
2334
+ ### Carousel
2335
+
2336
+ Slides in a scroll-snap viewport: native swipe and scrolling, previous/next controls, indicators, keyboard, loop and autoplay with a pause button.
2337
+
2338
+ Import: `import "@raylang/elements/carousel";` · Category: Data display
2339
+
2340
+ #### `<ray-carousel>` (RayCarousel, extends RayElement)
2341
+
2342
+ Any child is a slide. With several slides in view, positions are the snap points the viewport can reach. ArrowLeft/Right (Up/Down when vertical), Home and End move it.
2343
+
2344
+ Properties:
2345
+
2346
+ - `index`: number, default `0`. Current position (0-based). Setting it scrolls there.
2347
+ - `label`: string, default `Carousel`. Accessible name of the carousel region.
2348
+ - `slideSize` (attribute `slide-size`): string. Size of each slide along the scroll axis ("100%" by default; "50%", "18rem"…).
2349
+ - `slideGap` (attribute `slide-gap`): string. Space between slides (default var(--ray-space-4)).
2350
+ - `align`: `start` | `center`, default `start`, reflects. Where a slide snaps in the viewport.
2351
+ - `orientation`: `horizontal` | `vertical`, default `horizontal`, reflects. Scroll axis (vertical needs a height; 20rem by default).
2352
+ - `loop`: boolean, reflects. next() on the last position goes to the first, prev() on the first to the last.
2353
+ - `autoplay`: number, default `0`. Milliseconds between automatic moves (0: off). Pauses on hover, focus and when the page is hidden; starts paused with reduced motion. Shows a pause/play button.
2354
+ - `hideControls` (attribute `hide-controls`): boolean, reflects. No previous/next buttons.
2355
+ - `hideIndicators` (attribute `hide-indicators`): boolean, reflects. No indicator dots.
2356
+
2357
+ Events:
2358
+
2359
+ - `change`: The current position changed (read `index`) by the user or a method (controls, indicators, keyboard, swipe, scroll, next/prev/goTo, autoplay) — not when `index` is set by code.
2360
+
2361
+ Slots:
2362
+
2363
+ - (default): The slides.
2364
+
2365
+ Parts (`::part()`):
2366
+
2367
+ - `viewport`: The scrolling viewport.
2368
+ - `previous`: The previous button.
2369
+ - `next`: The next button.
2370
+ - `indicators`: The row of indicator dots.
2371
+ - `indicator`: Each indicator dot ([aria-current] on the active one).
2372
+ - `play`: The pause/play button (with autoplay).
2373
+
2374
+ Methods and properties:
2375
+
2376
+ - `next(): void`: Goes to the next position.
2377
+ - `prev(): void`: Goes to the previous position.
2378
+ - `goTo(index: number, options?: { instant?: boolean }): void`: Scrolls to a position (smoothly unless instant or reduced motion).
2379
+ - `readonly count: number`: Number of positions.
2380
+ - `readonly slides: Element[]`: The slide elements.
2381
+
2382
+ ### Code
2383
+
2384
+ A block of source code: header with file name and language, copy button, line numbers, highlighted lines, diff lines, wrapping and a "show more" height. A small built-in highlighter, or any library through setHighlighter(), painted with the --ray-code-* tokens.
2385
+
2386
+ Import: `import "@raylang/elements/code";` · Category: Data display
2387
+
2388
+ #### `<ray-code>` (RayCode, extends RayElement)
2389
+
2390
+ The code comes from the code property, a <script type="text/plain"> child (raw text: anything but a closing script tag), a <template> child (parsed as HTML: the easiest for markup, but a < that is not a tag, as in Promise<void>, breaks it), or the element's text; common indentation and blank edges are removed. Built-in languages: js/ts (jsx, tsx), json, html/xml/svg/vue, css, shell, ray and diff; others show as plain text. Library classes painted with the tokens: Prism's .token.*, highlight.js's .hljs-*, and Shiki's css-variables theme.
2391
+
2392
+ Properties:
2393
+
2394
+ - `code` (property only): string. The code, from script (the most convenient in React and Vue). Wins over the content.
2395
+ - `language`: string, reflects. The language: js, ts, jsx, tsx, json, html, xml, svg, vue, css, sh, ray, diff… (also shown in the header). Not lang: that is the human language of the text.
2396
+ - `filename`: string. A file name or title in the header; also the scroll region's accessible name.
2397
+ - `lineNumbers` (attribute `line-numbers`): boolean, reflects. Numbers each line (not copied, not selectable).
2398
+ - `highlight`: string. Lines to highlight: "3, 5-7".
2399
+ - `wrap`: boolean, reflects. Wraps long lines instead of scrolling sideways.
2400
+ - `maxHeight` (attribute `max-height`): string. Height before it scrolls: px as a number, or a CSS length. A taller block gets a "Show all N lines" button.
2401
+ - `expanded`: boolean, reflects. Shown whole, past max-height.
2402
+ - `hideCopy` (attribute `hide-copy`): boolean, reflects. No copy button.
2403
+ - `hideHeader` (attribute `hide-header`): boolean, reflects. No header bar (the copy button floats in the corner).
2404
+ - `size`: `xs` | `sm` | `md`, default `sm`, reflects. Font size.
2405
+ - `radius`: string, reflects. Corner radius: xs…xl, none, or a CSS length. Default: md.
2406
+ - `copyLabel` (attribute `copy-label`): string, default `Copy code`. Accessible name of the copy button.
2407
+ - `copiedLabel` (attribute `copied-label`): string, default `Copied`. Shown and announced after copying.
2408
+
2409
+ Events:
2410
+
2411
+ - `ray-copy` (detail `{ code: string }`): The code was copied.
2412
+
2413
+ Slots:
2414
+
2415
+ - (default): The code: text, a <template> or a <script type="text/plain">.
2416
+
2417
+ Parts (`::part()`):
2418
+
2419
+ - `frame`: The box.
2420
+ - `header`: The bar with the file name, the language and the copy button.
2421
+ - `copy`: The copy button.
2422
+ - `scroller`: The scroll box (focusable, to scroll with the keyboard).
2423
+ - `code`: The <code> with one .line per line.
2424
+
2425
+ Methods and properties:
2426
+
2427
+ - `readonly source: string`: The code shown (dedented), whatever its source.
2428
+ - `copy(): Promise<boolean>`: Copies the code; resolves to true when it worked.
2429
+
2430
+ Exports (from `@raylang/elements/code` and `@raylang/elements`):
2431
+
2432
+ - `function setHighlighter(fn: ((code: string, lang: string) => string | Node | null | undefined | Promise<string | Node | null | undefined>) | null): void`: Hands every ray-code to a highlighter that returns HTML (Prism, highlight.js, Shiki…); null/undefined falls back to the built-in one. The HTML is inserted as is: pass only a trusted highlighter. null restores the built-in one.
2433
+ - `function tokenize(code: string, lang?: string): [type: string, text: string][]`: The built-in highlighter: tokens of type keyword, string, number, comment, function, type, tag, attr, punctuation or text.
2434
+
2435
+ ### Icon
2436
+
2437
+ An icon of the registry: the whole set (the components' too) changes with setIcons().
2438
+
2439
+ Import: `import "@raylang/elements/icon";` · Category: Data display
2440
+
2441
+ #### `<ray-icon>` (RayIcon, extends RayElement)
2442
+
2443
+ setIcons({ name: '<svg…>' }) replaces or adds icons (SVG markup or an SVGElement, drawn with currentColor); iconNames() lists them. Sizes follow the font unless size; --ray-icon-size and --ray-icon-stroke tune the whole system.
2444
+
2445
+ Properties:
2446
+
2447
+ - `name`: string, reflects. Registered icon name (iconNames()); "none" draws nothing, a blank that keeps the alignment (a menu item without its check).
2448
+ - `size`: string, reflects. xs…xl or any CSS length. Default: 1em.
2449
+ - `label`: string. Accessible name; without it the icon is decorative (hidden from screen readers).
2450
+ - `color`: string, reflects. A palette color or any CSS color. Default: the text color.
2451
+ - `stroke`: number. Stroke width for stroke icons (default: --ray-icon-stroke, 2).
2452
+
2453
+ Parts (`::part()`):
2454
+
2455
+ - `icon`: The icon box.
2456
+
2457
+ ### Indicator
2458
+
2459
+ A dot or a small label on the edge of any element (Mantine's Indicator): "New" on an avatar, an unread count on a bell, an online dot. Nine positions, an inward offset, palette or CSS colors, a border and a live pulse.
2460
+
2461
+ Import: `import "@raylang/elements/indicator";` · Category: Data display
2462
+
2463
+ #### `<ray-indicator>` (RayIndicator, extends RayElement)
2464
+
2465
+ Wraps its content as tight as it is (fit-content). The label is part of the element's text for assistive technology; a dot has none: describe it on the content (aria-label="Grace, online").
2466
+
2467
+ Properties:
2468
+
2469
+ - `label`: string. Text in the indicator (a word or a count). Empty: a dot.
2470
+ - `position`: `top-start` | `top-center` | `top-end` | `middle-start` | `middle-center` | `middle-end` | `bottom-start` | `bottom-center` | `bottom-end`, default `top-end`, reflects. Which point of the content's box it sits on.
2471
+ - `offset`: `string | number`. Moves it inward from that point: px as a number, or a CSS length. Use it on round content (an avatar), so it sits on the curve.
2472
+ - `color`: string, reflects. A palette color or any CSS color. Default: the primary.
2473
+ - `size`: `string | number`. Diameter of the dot (and minimum height of a label): px as a number, or a CSS length. Default: 10px.
2474
+ - `radius`: string, reflects. Corner radius: xs…xl, none, or a CSS length. Default: round.
2475
+ - `max`: number. A numeric label above it shows as max+ (99+).
2476
+ - `inline`: boolean, reflects. inline-block, to sit within a line of text.
2477
+ - `withBorder` (attribute `with-border`): boolean, reflects. A ring in the background color, to separate it from the content.
2478
+ - `processing`: boolean, reflects. A pulse around it (live, recording, syncing).
2479
+ - `disabled`: boolean, reflects. Hides the indicator (the content stays).
2480
+
2481
+ Slots:
2482
+
2483
+ - (default): The element the indicator sits on.
2484
+
2485
+ Parts (`::part()`):
2486
+
2487
+ - `indicator`: The dot or label.
2488
+
2489
+ ### Kbd
2490
+
2491
+ A keyboard key: a raised keycap, or a flat chip (filled or outline) for hints in menus and buttons.
2492
+
2493
+ Import: `import "@raylang/elements/kbd";` · Category: Data display
2494
+
2495
+ #### `<ray-kbd>` (RayKbd, extends RayElement)
2496
+
2497
+ Properties:
2498
+
2499
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Font size.
2500
+ - `variant`: `default` | `filled` | `outline`, default `default`, reflects. default: raised keycap; filled: flat muted chip; outline: flat with a border.
2501
+
2502
+ Slots:
2503
+
2504
+ - (default): The key name.
2505
+
2506
+ Parts (`::part()`):
2507
+
2508
+ - `kbd`: The inner <kbd>.
2509
+
2510
+ ### Stat
2511
+
2512
+ A metric tile: label, value, change against a previous period, note.
2513
+
2514
+ Import: `import "@raylang/elements/stat";` · Category: Data display
2515
+
2516
+ #### `<ray-stat>` (RayStat, extends RayElement)
2517
+
2518
+ Properties:
2519
+
2520
+ - `label`: string. What is measured.
2521
+ - `value`: string. The figure, already formatted.
2522
+ - `diff`: number. Change (positive is shown as good, in green; see inverse).
2523
+ - `diffUnit` (attribute `diff-unit`): string, default `%`. Unit of diff.
2524
+ - `note`: string. A line under the value (compared to…).
2525
+ - `inverse`: boolean, reflects. Lower is better (errors, latency): negative diffs are green.
2526
+ - `plain`: boolean, reflects. Without the card around.
2527
+
2528
+ Slots:
2529
+
2530
+ - `icon`: Icon next to the label.
2531
+ - (default): Extra content (e.g. a ray-progress).
2532
+
2533
+ ### Table
2534
+
2535
+ A data table from columns and data: sorting (aria-sort), row selection, clickable rows, sticky header, striped, empty state. Plain HTML tables: the .ray-table class of base.css.
2536
+
2537
+ Import: `import "@raylang/elements/table";` · Category: Data display
2538
+
2539
+ #### `<ray-table>` (RayTable, extends RayElement)
2540
+
2541
+ Cells are text (render may return a DOM node; strings are never parsed as HTML). The scroll height comes from --ray-table-max-height.
2542
+
2543
+ Properties:
2544
+
2545
+ - `columns` (property only): `TableColumn[]`. Columns: key, label, width, align, sortable, render(row, index), sort(a, b).
2546
+ - `data` (property only): `any[]`. Rows (objects).
2547
+ - `rowKey` (attribute `row-key`): string, default `id`. Field that identifies a row (selection).
2548
+ - `selectable`: boolean, reflects. A checkbox per row and a select-all checkbox.
2549
+ - `selection` (property only): `unknown[]`. Keys of the selected rows.
2550
+ - `sort` (property only): `TableSort | null`. Current sort; set it, or let header clicks change it.
2551
+ - `manualSort` (attribute `manual-sort`): boolean. Do not sort here: listen to ray-sort and pass sorted data.
2552
+ - `clickableRows` (attribute `clickable-rows`): boolean, reflects. Rows are focusable and fire ray-row-click (Enter too; arrows move between rows).
2553
+ - `striped`: boolean, reflects. Alternate row background.
2554
+ - `withBorder` (attribute `with-border`): boolean, reflects. Border around the table.
2555
+ - `withColumnBorders` (attribute `with-column-borders`): boolean, reflects. Borders between columns.
2556
+ - `stickyHeader` (attribute `sticky-header`): boolean, reflects. The header stays visible while scrolling (with --ray-table-max-height).
2557
+ - `noHover` (attribute `no-hover`): boolean, reflects. No row highlight on hover.
2558
+ - `density`: `xs` | `sm` | `md` | `lg`, default `sm`, reflects. Cell padding.
2559
+ - `label`: string. Caption (also the table's accessible name).
2560
+ - `emptyLabel` (attribute `empty-label`): string, default `No data`. Text without rows (or put a ray-empty-state in slot=empty).
2561
+
2562
+ Events:
2563
+
2564
+ - `ray-sort` (detail `{ key: string; direction: "asc" | "desc" | null }`): A header changed the sort.
2565
+ - `ray-selection-change` (detail `{ selection: unknown[] }`): The selection changed.
2566
+ - `ray-row-click` (detail `{ row: any; index: number }`): A row was clicked or activated with Enter (clickable-rows).
2567
+
2568
+ Slots:
2569
+
2570
+ - `empty`: Shown instead of the empty text when there are no rows.
2571
+
2572
+ Parts (`::part()`):
2573
+
2574
+ - `table`: The <table>.
2575
+ - `scroll`: The scroll container.
2576
+
2577
+ Methods and properties:
2578
+
2579
+ - `readonly rows: any[]`: The rows in display order.
2580
+
2581
+ Types:
2582
+
2583
+ - `{ key: string; label?: string; width?: number | string; align?: "left" | "center" | "right"; sortable?: boolean; render?: (row: any, index: number) => string | number | Node | null | undefined; sort?: (a: any, b: any) => number }`: A column of ray-table.
2584
+ - `{ key: string; direction: "asc" | "desc" }`: The sort state of ray-table.
2585
+
2586
+ ### Timeline
2587
+
2588
+ Events in order along a line (Mantine's Timeline): activity, history, a deploy's stages. Items up to active are reached (filled bullet, colored line); a bullet is a dot, an icon or an avatar.
2589
+
2590
+ Import: `import "@raylang/elements/timeline";` · Category: Data display
2591
+
2592
+ #### `<ray-timeline>` (RayTimeline, extends RayElement)
2593
+
2594
+ A list (role="list") of ray-timeline-item.
2595
+
2596
+ Properties:
2597
+
2598
+ - `active`: number, default `-1`, reflects. Index of the last reached item (-1: none).
2599
+ - `align`: `left` | `right`, default `left`, reflects. Side of the line.
2600
+ - `bulletSize` (attribute `bullet-size`): string. Bullet size: px as a number or a CSS length (default 20px).
2601
+ - `lineWidth` (attribute `line-width`): number. Line width in px (default 2).
2602
+ - `color`: string, reflects. A palette color or any CSS color for what is reached (default: primary).
2603
+ - `reverseActive` (attribute `reverse-active`): boolean, reflects. Counts active from the end (the latest event at the top).
2604
+
2605
+ Slots:
2606
+
2607
+ - (default): ray-timeline-item elements.
2608
+
2609
+ Methods and properties:
2610
+
2611
+ - `readonly items: RayTimelineItem[]`: The items, in order.
2612
+
2613
+ #### `<ray-timeline-item>` (RayTimelineItem, extends RayElement)
2614
+
2615
+ Properties:
2616
+
2617
+ - `label`: string. The title of the event.
2618
+ - `time`: string. When ("2 h ago", a date).
2619
+ - `icon`: string. An icon of the registry in the bullet.
2620
+ - `color`: string, reflects. Its own color (a failed step in red).
2621
+ - `lineVariant` (attribute `line-variant`): `solid` | `dashed` | `dotted`, default `solid`, reflects. The line to the next item (dashed: not happened yet).
2622
+
2623
+ Slots:
2624
+
2625
+ - (default): Details under the title.
2626
+ - `bullet`: A custom bullet (an avatar, an image).
2627
+
2628
+ Parts (`::part()`):
2629
+
2630
+ - `bullet`: The bullet.
2631
+ - `line`: The line to the next item.
2632
+ - `body`: Title, details and time.
2633
+ - `title`: The title.
2634
+ - `time`: The time.
2635
+
2636
+ ### Alert
2637
+
2638
+ An inline message: title, text, an icon of the registry, the color variants and an optional close button.
2639
+
2640
+ Import: `import "@raylang/elements/alert";` · Category: Feedback
2641
+
2642
+ #### `<ray-alert>` (RayAlert, extends RayElement)
2643
+
2644
+ Announced as an alert. The icon follows the color (info, circle-check, alert-triangle, circle-x) unless icon or slot=icon.
2645
+
2646
+ Properties:
2647
+
2648
+ - `label`: string. Title.
2649
+ - `color`: string, reflects. A palette color or any CSS color.
2650
+ - `variant`: `light` | `filled` | `outline` | `default` | `transparent`, default `light`, reflects. Visual style.
2651
+ - `radius`: `xs` | `sm` | `md` | `lg` | `xl`. Corner radius.
2652
+ - `icon`: string, reflects. A registered icon name, or none.
2653
+ - `closable`: boolean, reflects. A close button; closing hides the alert (cancel ray-close to keep it).
2654
+ - `closeLabel` (attribute `close-label`): string, default `Dismiss`. Accessible name of the close button.
2655
+
2656
+ Events:
2657
+
2658
+ - `ray-close`: The close button was pressed; cancelable.
2659
+
2660
+ Slots:
2661
+
2662
+ - (default): Text.
2663
+ - `icon`: A custom icon.
2664
+
2665
+ Parts (`::part()`):
2666
+
2667
+ - `alert`: The box.
2668
+ - `close`: The close button.
2669
+
2670
+ ### Empty state
2671
+
2672
+ What a list, table or pane shows when it is empty: icon, title, text and the action that fills it.
2673
+
2674
+ Import: `import "@raylang/elements/empty-state";` · Category: Feedback
2675
+
2676
+ #### `<ray-empty-state>` (RayEmptyState, extends RayElement)
2677
+
2678
+ Properties:
2679
+
2680
+ - `label`: string. Title.
2681
+ - `compact`: boolean, reflects. Less padding.
2682
+ - `withBorder` (attribute `with-border`): boolean, reflects. Dashed border.
2683
+
2684
+ Slots:
2685
+
2686
+ - (default): Text.
2687
+ - `icon`: Icon, shown in a circle.
2688
+ - `actions`: Buttons.
2689
+
2690
+ ### Notification
2691
+
2692
+ Toasts: notify(), updateNotification(), hideNotification(), clearNotifications(); shown in a ray-toaster (a polite live region in the top layer). ray-notification is usable on its own.
2693
+
2694
+ Import: `import "@raylang/elements/notification";` · Category: Feedback
2695
+
2696
+ #### `<ray-notification>` (RayNotification, extends RayElement)
2697
+
2698
+ notify({ id, title, message, color, icon, loading, autoClose (ms, default 4000; false = stays), closable, withBorder, onClose }) returns its id. A color adds a status icon in that color: green/teal a check, red/pink an error, yellow/orange a warning, others info. The status icon and the loader are 1.5rem with a 1.5 stroke; set --ray-notification-icon-size and --ray-notification-icon-stroke to change them.
2699
+
2700
+ Properties:
2701
+
2702
+ - `label`: string. Title.
2703
+ - `color`: string, reflects. Status color: tints the status icon (and a slotted icon's circle).
2704
+ - `icon`: string. Status icon from the registry (default: from the color); "none" for no icon.
2705
+ - `loading`: boolean, reflects. Shows a spinner (notify() does not auto-close it).
2706
+ - `hideClose` (attribute `hide-close`): boolean, reflects. No close button.
2707
+ - `withBorder` (attribute `with-border`): boolean, reflects. Draws a border.
2708
+ - `actionLabel` (attribute `action-label`): string. Text of an action button (e.g. "Undo"); pressing it fires ray-action.
2709
+
2710
+ Events:
2711
+
2712
+ - `ray-close`: The close button was pressed.
2713
+ - `ray-action`: The action button was pressed (notify() runs action.onClick and closes it).
2714
+
2715
+ Slots:
2716
+
2717
+ - (default): Message.
2718
+ - `icon`: Your own icon, in a colored circle (replaces the status icon).
2719
+
2720
+ Parts (`::part()`):
2721
+
2722
+ - `status-icon`: The status icon.
2723
+
2724
+ #### `<ray-toaster>` (RayToaster, extends RayElement)
2725
+
2726
+ Created by notify() when missing; add one yourself to choose its position. A stack (newest in front, older ones peeking behind) that spreads into a list on hover or keyboard focus; on touch screens a tap expands it, a tap outside collapses it, and a sideways swipe dismisses a toast. Auto-close pauses while expanded. Full width on phones.
2727
+
2728
+ Properties:
2729
+
2730
+ - `position`: `bottom-right` | `bottom-left` | `bottom-center` | `top-right` | `top-left` | `top-center`, default `bottom-right`, reflects. Corner of the stack.
2731
+ - `limit`: number, default `5`. Maximum kept; the oldest go first.
2732
+ - `visible`: number, default `3`. Toasts shown in the collapsed stack (the rest wait, hidden).
2733
+ - `expand`: boolean, reflects. Always expanded: a list instead of a stack.
2734
+ - `gap`: number, default `12`. Pixels between toasts when expanded.
2735
+
2736
+ Methods and properties:
2737
+
2738
+ - `expanded: boolean`: Whether the stack is spread out (set it to expand or collapse it).
2739
+ - `layout(): void`: Places the toasts again (done automatically on changes).
2740
+ - `raise(): void`: Brings the stack above everything else in the top layer.
2741
+
2742
+ Exports (from `@raylang/elements/notification` and `@raylang/elements`):
2743
+
2744
+ - `function notify(options?: NotifyOptions): string`: Shows a notification; returns its id.
2745
+ - `function updateNotification(id: string, options?: NotifyOptions): boolean`: Changes a shown notification and restarts its auto-close.
2746
+ - `function hideNotification(id: string): boolean`: Removes a notification.
2747
+ - `function clearNotifications(): void`: Removes every notification.
2748
+ - `function statusIcon(color: string): string`: The status icon a color gets: circle-check, circle-x, alert-triangle or info.
2749
+
2750
+ Types:
2751
+
2752
+ - `{ id?: string; title?: string; message?: string; color?: string; icon?: string; loading?: boolean; autoClose?: number | false; closable?: boolean; withBorder?: boolean; action?: { label: string; onClick?: () => void }; onClose?: () => void }`: Options of notify() and updateNotification().
2753
+
2754
+ ### Progress
2755
+
2756
+ A determinate or (without value) indeterminate progress bar, announced as a progressbar.
2757
+
2758
+ Import: `import "@raylang/elements/progress";` · Category: Feedback
2759
+
2760
+ #### `<ray-progress>` (RayProgress, extends RayElement)
2761
+
2762
+ Properties:
2763
+
2764
+ - `value`: number. Progress, from 0 to max. Unset: indeterminate.
2765
+ - `max`: number, default `100`. The value of a full bar.
2766
+ - `color`: string, reflects. A palette color or any CSS color.
2767
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `md`, reflects. Bar height.
2768
+ - `radius`: `xs` | `sm` | `md` | `lg` | `xl` | `full`. Corner radius. Default: full.
2769
+ - `striped`: boolean, reflects. Diagonal stripes.
2770
+ - `animated`: boolean, reflects. Moving stripes (with striped).
2771
+ - `showValue` (attribute `show-value`): boolean, reflects. Shows the percentage: inside the bar on lg and xl, beside it on smaller sizes.
2772
+ - `label`: string. Accessible name (default: Progress).
2773
+
2774
+ Parts (`::part()`):
2775
+
2776
+ - `track`: The background track.
2777
+ - `bar`: The filled bar.
2778
+ - `value`: The percentage beside the bar (show-value on xs, sm, md).
2779
+
2780
+ ### Skeleton
2781
+
2782
+ A placeholder while content loads: a shimmering block, a circle or text lines; with loaded it shows its content.
2783
+
2784
+ Import: `import "@raylang/elements/skeleton";` · Category: Feedback
2785
+
2786
+ #### `<ray-skeleton>` (RaySkeleton, extends RayElement)
2787
+
2788
+ aria-busy="true" on the host while loading; the placeholder is aria-hidden.
2789
+
2790
+ Properties:
2791
+
2792
+ - `width`: string. Width (CSS length, a number is px). Default: 100% (a circle: 2.5rem).
2793
+ - `height`: string. Height of a block or of each line (CSS length, a number is px). Default: 1rem.
2794
+ - `circle`: boolean, reflects. A circle (avatar placeholder): its diameter is width, else height.
2795
+ - `lines`: number, reflects. Number of text lines (the last one is shorter).
2796
+ - `radius`: string, reflects. Corner radius: xs…xl, full or a CSS length. Default: sm.
2797
+ - `animation`: `shimmer` | `pulse` | `none`, default `shimmer`, reflects. The loading effect (always none with reduced motion).
2798
+ - `loaded`: boolean, reflects. Shows the slotted content instead of the placeholder.
2799
+
2800
+ Slots:
2801
+
2802
+ - (default): The real content, shown with loaded.
2803
+
2804
+ Parts (`::part()`):
2805
+
2806
+ - `skeleton`: The placeholder container.
2807
+ - `bone`: Each block or line.
2808
+
2809
+ ### Spinner
2810
+
2811
+ An indeterminate loading indicator, announced as a status.
2812
+
2813
+ Import: `import "@raylang/elements/spinner";` · Category: Feedback
2814
+
2815
+ #### `<ray-spinner>` (RaySpinner, extends RayElement)
2816
+
2817
+ Properties:
2818
+
2819
+ - `color`: string. A palette color or any CSS color. Default: the primary color.
2820
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `md`, reflects. Diameter.
2821
+ - `label`: string, default `Loading`. Text read by screen readers.
2822
+
2823
+ Parts (`::part()`):
2824
+
2825
+ - `spinner`: The ring.
2826
+
2827
+ ### App bar
2828
+
2829
+ The top bar of a phone screen (Material's top app bar, the iOS navigation bar): back or menu, a title and subtitle, actions, and an optional row under it. It elevates once the content scrolls, or hides while scrolling down.
2830
+
2831
+ Import: `import "@raylang/elements/app-bar";` · Category: Layout
2832
+
2833
+ #### `<ray-app-bar>` (RayAppBar, extends RayElement)
2834
+
2835
+ It follows the scroller of its ray-app-shell, else scroll-target, else the window; clear of the notch (safe-area inset). The title is plain text: put a heading in the default slot when the page needs one.
2836
+
2837
+ Properties:
2838
+
2839
+ - `label`: string. The title.
2840
+ - `description`: string. A line under the title.
2841
+ - `center`: boolean, reflects. The title centered (iOS).
2842
+ - `variant`: `default` | `filled` | `transparent`, default `default`, reflects. default: the page background; filled: the primary color; transparent: until it elevates.
2843
+ - `size`: `sm` | `md` | `lg`, default `md`, reflects. Height: 48, 56 or 64 px.
2844
+ - `scrollBehavior` (attribute `scroll-behavior`): `elevate` | `hide` | `none`, default `elevate`, reflects. While the content scrolls: elevate (border and shadow), hide (also slides away going down, back going up), none.
2845
+ - `sticky`: boolean, reflects. Sticks to the top of the window (outside a shell).
2846
+ - `scrollTarget` (attribute `scroll-target`): string. A selector of the element whose scrolling it follows (default: its shell's, else the window).
2847
+
2848
+ Slots:
2849
+
2850
+ - (default): Title content after the label (a heading, a select).
2851
+ - `start`: Before the title: back or menu button.
2852
+ - `end`: Actions.
2853
+ - `bottom`: A row under the bar: tabs, a search field.
2854
+
2855
+ Parts (`::part()`):
2856
+
2857
+ - `bar`: The bar.
2858
+ - `start`: The start area.
2859
+ - `title`: The title area.
2860
+ - `end`: The actions area.
2861
+ - `bottom`: The row under the bar.
2862
+
2863
+ Methods and properties:
2864
+
2865
+ - `readonly concealed: boolean`: Whether scroll-behavior="hide" has slid it away.
2866
+
2867
+ ### App shell
2868
+
2869
+ The frame of an app (Mantine's AppShell): header, navbar, main, aside and footer on wide screens; on phones one column with a bottom bar. The main content scrolls, the bars stay.
2870
+
2871
+ Import: `import "@raylang/elements/app-shell";` · Category: Layout
2872
+
2873
+ #### `<ray-app-shell>` (RayAppShell, extends RayElement)
2874
+
2875
+ The layout follows the shell's own width (a phone-sized frame shows the phone layout). Below breakpoint the navbar and the aside take no room (a ray-sidebar there still opens as its drawer) and the bottom slot shows. It fills the window's height (100dvh) unless sized. In a std/ui full_content window (ray-elements/core/raylang.js) the header becomes the title bar: room for the window buttons, and it drags the window; with layout="alt" or no header, the navbar and main start below it.
2876
+
2877
+ Properties:
2878
+
2879
+ - `layout`: `default` | `alt`, default `default`, reflects. default: the header across the top; alt: the navbar full height, the header beside it.
2880
+ - `breakpoint`: string, default `48em`. Width (px, em or rem) below which it takes the phone layout.
2881
+ - `padding`: string, reflects. Padding of the main area: xs…xl, a number (px) or a CSS length.
2882
+
2883
+ Events:
2884
+
2885
+ - `ray-breakpoint` (detail `{ mobile: boolean }`): It switched between the wide and the phone layout.
2886
+
2887
+ Slots:
2888
+
2889
+ - (default): The main content (it scrolls).
2890
+ - `header`: Top bar: a ray-app-bar or a header of your own.
2891
+ - `navbar`: Side navigation (a ray-sidebar). Wide screens only.
2892
+ - `aside`: A panel on the other side (details, an inspector). Wide screens only.
2893
+ - `footer`: Under the main content.
2894
+ - `bottom`: Phones only: a ray-bottom-nav.
2895
+
2896
+ Parts (`::part()`):
2897
+
2898
+ - `shell`: The grid.
2899
+ - `header`: The header area.
2900
+ - `navbar`: The navbar area.
2901
+ - `main`: The scrolling main area.
2902
+ - `aside`: The aside area.
2903
+ - `footer`: The footer area.
2904
+ - `bottom`: The bottom bar area.
2905
+
2906
+ Methods and properties:
2907
+
2908
+ - `readonly scroller: HTMLElement`: The element that scrolls the main content.
2909
+ - `readonly mobile: boolean`: Whether it is in the phone layout.
2910
+
2911
+ #### In a raylang app
2912
+
2913
+ In a `std/ui` window opened as `full_content` (the page under a transparent title bar, macOS), with [the native bridge](https://elements.raylang.dev/raylang.html#using-the-bridge), the header becomes the title bar: at least as tall, with room for the window buttons, and dragging it moves the window (buttons in it stay buttons). With `layout="alt"` or without a header, the navbar and the main content start below the title bar.
2914
+
2915
+ ```ray
2916
+ var o = ui.options(1100, 720);
2917
+ o.kind = "full_content";
2918
+ let h = ui.open_with("Builds", "ray://app/index.html", o)?;
2919
+ ```
2920
+
2921
+ The bridge also keeps the window's background and title bar in the theme's background, so switching to dark, resizing or reopening never flashes the other theme.
2922
+
2923
+ ### Aspect ratio
2924
+
2925
+ A box with a fixed width/height ratio; its image, video or iframe fills it.
2926
+
2927
+ Import: `import "@raylang/elements/aspect-ratio";` · Category: Layout
2928
+
2929
+ #### `<ray-aspect-ratio>` (RayAspectRatio, extends RayElement)
2930
+
2931
+ Properties:
2932
+
2933
+ - `ratio`: string, default `16/9`, reflects. Width/height: "16/9", "4:3", "1" or a number.
2934
+ - `fit`: `cover` | `contain`, default `cover`, reflects. How the media fills the box (object-fit).
2935
+ - `radius`: string, reflects. Corner radius: xs…xl, full or a CSS length.
2936
+
2937
+ Slots:
2938
+
2939
+ - (default): The media (img, video, iframe or any element); it fills the box.
2940
+
2941
+ Exports (from `@raylang/elements/aspect-ratio` and `@raylang/elements`):
2942
+
2943
+ - `function parseRatio(value: string | number): string | null`: A ratio ("16/9", "4:3", 1.5) as a CSS aspect-ratio value, or null.
2944
+
2945
+ ### Card
2946
+
2947
+ A surface for grouped content, with optional media, header and footer.
2948
+
2949
+ Import: `import "@raylang/elements/card";` · Category: Layout
2950
+
2951
+ #### `<ray-card>` (RayCard, extends RayElement)
2952
+
2953
+ Properties:
2954
+
2955
+ - `padding`: `0` | `xs` | `sm` | `md` | `lg` | `xl`, default `md`, reflects. Inner spacing (named space scale).
2956
+ - `radius`: `xs` | `sm` | `md` | `lg` | `xl`. Corner radius. Default: --ray-radius-default.
2957
+ - `shadow`: `xs` | `sm` | `md` | `lg` | `xl`. Elevation.
2958
+ - `withBorder` (attribute `with-border`): boolean. Draws a border.
2959
+ - `variant`: `default` | `filled` | `outline`, default `default`, reflects. default: card surface; filled: muted surface; outline: border without fill.
2960
+
2961
+ Slots:
2962
+
2963
+ - (default): The body.
2964
+ - `media`: Full-bleed image or media at the top.
2965
+ - `header`: Header content.
2966
+ - `footer`: Footer content (actions).
2967
+
2968
+ Parts (`::part()`):
2969
+
2970
+ - `card`: The surface.
2971
+ - `header`: The header area.
2972
+ - `body`: The body area.
2973
+ - `footer`: The footer area.
2974
+
2975
+ ### Center
2976
+
2977
+ Its content centered on both axes (Mantine's Center): empty states, loaders, a sign-in card.
2978
+
2979
+ Import: `import "@raylang/elements/center";` · Category: Layout
2980
+
2981
+ #### `<ray-center>` (RayCenter, extends RayElement)
2982
+
2983
+ It fills its parent's width; give it a height (or a flex or grid parent that stretches it) to center vertically.
2984
+
2985
+ Properties:
2986
+
2987
+ - `inline`: boolean, reflects. As wide as its content (inline-flex): an icon beside text.
2988
+
2989
+ Slots:
2990
+
2991
+ - (default): The content.
2992
+
2993
+ ### Container
2994
+
2995
+ Its content centered, up to a maximum width, with side padding (Mantine's Container): the column of a page.
2996
+
2997
+ Import: `import "@raylang/elements/container";` · Category: Layout
2998
+
2999
+ #### `<ray-container>` (RayContainer, extends RayElement)
3000
+
3001
+ Properties:
3002
+
3003
+ - `size`: string, default `md`, reflects. Maximum width: xs 540px, sm 720px, md 960px, lg 1140px, xl 1320px, or any CSS length.
3004
+ - `padding`: string, default `md`, reflects. Side padding: xs…xl, a number (px) or a CSS length.
3005
+ - `fluid`: boolean, reflects. No maximum width: the whole width, still padded.
3006
+
3007
+ Slots:
3008
+
3009
+ - (default): The content.
3010
+
3011
+ Exports (from `@raylang/elements/container` and `@raylang/elements`):
3012
+
3013
+ - `const CONTAINER_SIZES: { xs: string; sm: string; md: string; lg: string; xl: string }`: The maximum widths of size.
3014
+
3015
+ ### Grid
3016
+
3017
+ A responsive grid: a column count per width (cols="1 sm:2 lg:4") measured on the grid itself, or as many columns of a minimum width as fit. Children span columns with data-span.
3018
+
3019
+ Import: `import "@raylang/elements/grid";` · Category: Layout
3020
+
3021
+ #### `<ray-grid>` (RayGrid, extends RayElement)
3022
+
3023
+ The widths are the grid's own (container queries: xs 36em, sm 48em, md 62em, lg 75em, xl 88em), so a grid in a narrow column or a phone frame drops to fewer columns. It needs a width from its parent: in a flex row give it one or let it grow. A child spans with data-span="2"…"12" or "full".
3024
+
3025
+ Properties:
3026
+
3027
+ - `cols`: string, default `1`, reflects. Columns: a count, then counts from a width up ("1 sm:2 lg:4").
3028
+ - `minColWidth` (attribute `min-col-width`): string. Instead of cols: as many columns of at least this width as fit ("14rem", 220).
3029
+ - `gap`: string, default `md`, reflects. Space between cells: xs…xl, a number (px) or a CSS length.
3030
+ - `rowGap` (attribute `row-gap`): string. Space between rows when it differs from gap.
3031
+ - `align`: `stretch` | `start` | `center` | `end`, default `stretch`, reflects. Vertical alignment of the cells in a row.
3032
+
3033
+ Slots:
3034
+
3035
+ - (default): The cells (data-span="2" or "full" to span).
3036
+
3037
+ Parts (`::part()`):
3038
+
3039
+ - `grid`: The grid element.
3040
+
3041
+ Exports (from `@raylang/elements/grid` and `@raylang/elements`):
3042
+
3043
+ - `function parseCols(value: string | number | undefined): { base?: number; xs?: number; sm?: number; md?: number; lg?: number; xl?: number }`: "1 sm:2 lg:4" as counts per width.
3044
+ - `const BREAKPOINTS: { xs: string; sm: string; md: string; lg: string; xl: string }`: The widths of cols (36em, 48em, 62em, 75em, 88em).
3045
+
3046
+ ### Group
3047
+
3048
+ Its children in a row (Mantine's Group): spaced by the space scale, centered, wrapping when they do not fit. Toolbars, form actions, chips.
3049
+
3050
+ Import: `import "@raylang/elements/group";` · Category: Layout
3051
+
3052
+ #### `<ray-group>` (RayGroup, extends RayElement)
3053
+
3054
+ A flex row on the host: the children are laid out directly, no wrapper.
3055
+
3056
+ Properties:
3057
+
3058
+ - `gap`: string, default `md`, reflects. Space between children: xs…xl (the space scale), a number (px) or any CSS length.
3059
+ - `align`: `center` | `start` | `end` | `stretch` | `baseline`, default `center`, reflects. Cross-axis alignment.
3060
+ - `justify`: `start` | `center` | `end` | `space-between` | `space-around` | `space-evenly`, default `start`, reflects. Main-axis distribution: space-between for a title on one side and actions on the other.
3061
+ - `nowrap`: boolean, reflects. Keeps the children on one line.
3062
+ - `grow`: boolean, reflects. The children share the width equally.
3063
+
3064
+ Slots:
3065
+
3066
+ - (default): The children.
3067
+
3068
+ ### Scroll area
3069
+
3070
+ A box that scrolls its content with the native scrolling and a thin themed scrollbar (Mantine's ScrollArea). Edge shadows tell there is more; ray-reach-end fires at the end (load the next page).
3071
+
3072
+ Import: `import "@raylang/elements/scroll-area";` · Category: Layout
3073
+
3074
+ #### `<ray-scroll-area>` (RayScrollArea, extends RayElement)
3075
+
3076
+ Give it a size: height, max-height, CSS, or a flex/grid parent. The scrolling box is focusable (keyboard scrolling); name it with label when it holds a region of its own.
3077
+
3078
+ Properties:
3079
+
3080
+ - `height`: string. Height (CSS length).
3081
+ - `maxHeight` (attribute `max-height`): string. Maximum height: it grows with its content up to this, then scrolls.
3082
+ - `orientation`: `vertical` | `horizontal` | `both`, default `vertical`, reflects. Which ways it scrolls.
3083
+ - `type`: `auto` | `hover` | `never`, default `auto`, reflects. The scrollbar: auto (when it scrolls), hover (while hovered or scrolling), never (still scrolls).
3084
+ - `noShadows` (attribute `no-shadows`): boolean, reflects. No edge shadows.
3085
+ - `threshold`: number, default `48`. Distance from the end (px) at which ray-reach-end fires.
3086
+ - `label`: string. Accessible name: makes the scrolling box a named region.
3087
+
3088
+ Events:
3089
+
3090
+ - `ray-reach-end` (detail `{ edge: "bottom" | "right" }`): The end came within threshold (once per arrival).
3091
+
3092
+ Slots:
3093
+
3094
+ - (default): The content.
3095
+
3096
+ Parts (`::part()`):
3097
+
3098
+ - `viewport`: The scrolling box.
3099
+ - `shadow`: The edge shadows.
3100
+
3101
+ Methods and properties:
3102
+
3103
+ - `readonly viewport: HTMLElement`: The scrolling element (scrollTop, scrollTo…).
3104
+ - `scrollToStart(options?: { behavior?: ScrollBehavior }): void`: Scrolls to the top (left).
3105
+ - `scrollToEnd(options?: { behavior?: ScrollBehavior }): void`: Scrolls to the bottom (right when horizontal).
3106
+
3107
+ ### Separator
3108
+
3109
+ A horizontal or vertical rule, optionally labeled (Mantine's Divider).
3110
+
3111
+ Import: `import "@raylang/elements/separator";` · Category: Layout
3112
+
3113
+ #### `<ray-separator>` (RaySeparator, extends RayElement)
3114
+
3115
+ Properties:
3116
+
3117
+ - `orientation`: `horizontal` | `vertical`, default `horizontal`, reflects. Direction of the rule.
3118
+ - `label`: string, reflects. Text in the middle of a horizontal rule.
3119
+ - `labelPosition` (attribute `label-position`): `left` | `center` | `right`, default `center`, reflects. Where the label sits.
3120
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `xs`, reflects. Thickness (1–5px).
3121
+ - `variant`: `solid` | `dashed` | `dotted`, default `solid`, reflects. Line style.
3122
+
3123
+ Parts (`::part()`):
3124
+
3125
+ - `line`: The rule without label.
3126
+ - `label`: The labeled rule.
3127
+
3128
+ ### Split
3129
+
3130
+ Two panes with a draggable, keyboard-accessible divider (window splitter pattern); the size can be remembered.
3131
+
3132
+ Import: `import "@raylang/elements/split";` · Category: Layout
3133
+
3134
+ #### `<ray-split>` (RaySplit, extends RayElement)
3135
+
3136
+ Divider keys: arrows move it (Shift: faster), Home/End go to min/max, Enter or double click collapse the start pane.
3137
+
3138
+ Properties:
3139
+
3140
+ - `orientation`: `horizontal` | `vertical`, default `horizontal`, reflects. horizontal: side by side; vertical: stacked.
3141
+ - `position`: string, default `50%`. Initial size of the start pane: px (280) or any CSS length (30%, 20rem).
3142
+ - `min`: number, default `0`. Minimum size of the start pane in px.
3143
+ - `max`: number. Maximum size of the start pane in px.
3144
+ - `collapsed`: boolean, reflects. The start pane is hidden.
3145
+ - `disabled`: boolean, reflects. The divider cannot be moved.
3146
+ - `autosave`: string. A key: the size is saved in localStorage and restored.
3147
+
3148
+ Events:
3149
+
3150
+ - `ray-resize` (detail `{ size: number; collapsed: boolean }`): After a drag, a key or a collapse.
3151
+
3152
+ Slots:
3153
+
3154
+ - `start`: The sized pane (sidebar).
3155
+ - `end`: The pane that takes the rest.
3156
+
3157
+ Parts (`::part()`):
3158
+
3159
+ - `divider`: The separator.
3160
+ - `start`: The start pane.
3161
+ - `end`: The end pane.
3162
+
3163
+ Methods and properties:
3164
+
3165
+ - `readonly size: number`: The start pane's size in px.
3166
+ - `toggle(): void`: Collapses or restores the start pane.
3167
+
3168
+ ### Stack
3169
+
3170
+ Its children in a column, spaced by the space scale (Mantine's Stack): forms, panels, anything stacked.
3171
+
3172
+ Import: `import "@raylang/elements/stack";` · Category: Layout
3173
+
3174
+ #### `<ray-stack>` (RayStack, extends RayElement)
3175
+
3176
+ A flex column on the host: the children are laid out directly, no wrapper.
3177
+
3178
+ Properties:
3179
+
3180
+ - `gap`: string, default `md`, reflects. Space between children: xs…xl (the space scale), a number (px) or any CSS length.
3181
+ - `align`: `stretch` | `start` | `center` | `end` | `baseline`, default `stretch`, reflects. Cross-axis alignment: stretch fills the width.
3182
+ - `justify`: `start` | `center` | `end` | `space-between` | `space-around` | `space-evenly`, default `start`, reflects. Main-axis distribution (with a height to distribute).
3183
+
3184
+ Slots:
3185
+
3186
+ - (default): The children.
3187
+
3188
+ Exports (from `@raylang/elements/stack` and `@raylang/elements`):
3189
+
3190
+ - `function applyFlex(el: HTMLElement, options: { gap?: string; align?: string; justify?: string }, alignDefault: string): void`: Gap, align and justify of a stack or group onto an element's custom properties (for a layout component of your own).
3191
+
3192
+ ### Status bar
3193
+
3194
+ The bar at the bottom of an app window: items on the left and on the right; items with action are buttons.
3195
+
3196
+ Import: `import "@raylang/elements/statusbar";` · Category: Layout
3197
+
3198
+ #### `<ray-statusbar>` (RayStatusbar, extends RayElement)
3199
+
3200
+ Properties:
3201
+
3202
+ - `variant`: `default` | `accent`, default `default`, reflects. accent: the primary color (e.g. while debugging).
3203
+
3204
+ Slots:
3205
+
3206
+ - (default): Items on the left.
3207
+ - `right`: Items on the right.
3208
+
3209
+ #### `<ray-statusbar-item>` (RayStatusbarItem, extends RayElement)
3210
+
3211
+ Properties:
3212
+
3213
+ - `action`: boolean, reflects. A button (listen to click).
3214
+ - `color`: string, reflects. Text color (red for errors…).
3215
+ - `label`: string. Accessible name and tooltip (for icon-only or terse items).
3216
+
3217
+ Slots:
3218
+
3219
+ - (default): Text.
3220
+ - `icon`: Icon.
3221
+
3222
+ ### Theme toggle
3223
+
3224
+ Icon button that cycles the document theme: system, light, dark.
3225
+
3226
+ Import: `import "@raylang/elements/theme-toggle";` · Category: Theme
3227
+
3228
+ #### `<ray-theme-toggle>` (RayThemeToggle, extends RayElement)
3229
+
3230
+ Properties:
3231
+
3232
+ - `size`: `xs` | `sm` | `md` | `lg` | `xl`, default `sm`, reflects. Control height.
3233
+
3234
+ Events:
3235
+
3236
+ - `ray-theme-change` (detail `{ theme: "light" | "dark" | "system"; resolved: "light" | "dark"; primary: string | null }`): Fired on the document root by setTheme(); detail: { theme, resolved, primary }.
3237
+
3238
+ Parts (`::part()`):
3239
+
3240
+ - `button`: The inner button.
3241
+
3242
+ ## Tokens
3243
+
3244
+ Use them as `var(--ray-…)` in your own CSS. Values are resolved; the semantic ones change with the theme (light / dark).
3245
+
3246
+ - Palette: `--ray-<color>-0` (lightest) … `--ray-<color>-9` (darkest), colors `dark`, `gray`, `red`, `pink`, `violet`, `indigo`, `blue`, `cyan`, `teal`, `green`, `yellow`, `orange`. The same in both themes.
3247
+ - Per color and for `primary`: `--ray-<color>-<variant>`, variants `filled`, `filled-hover`, `light`, `light-hover`, `light-color`, `outline`, `outline-hover`, `contrast`; theme-aware.
3248
+ - Primary: `--ray-primary-0` … `-9` and its variants, aliases of the primary color (`blue`; `data-primary` or `setPrimary()` changes it).
3249
+
3250
+ base:
3251
+
3252
+ - `--ray-white`: #ffffff
3253
+ - `--ray-black`: #000000
3254
+
3255
+ semantic:
3256
+
3257
+ - `--ray-background`: #ffffff / #141414
3258
+ - `--ray-foreground`: #212529 / #f1f3f5
3259
+ - `--ray-card`: #ffffff / #1f1f1f
3260
+ - `--ray-card-foreground`: #212529 / #f1f3f5
3261
+ - `--ray-popover`: #ffffff / #1f1f1f
3262
+ - `--ray-popover-foreground`: #212529 / #f1f3f5
3263
+ - `--ray-primary`: #1971c2
3264
+ - `--ray-primary-hover`: #1864ab
3265
+ - `--ray-primary-foreground`: #ffffff
3266
+ - `--ray-secondary`: #f1f3f5 / #2e2e2e
3267
+ - `--ray-secondary-hover`: #e9ecef / #3b3b3b
3268
+ - `--ray-secondary-foreground`: #212529 / #f1f3f5
3269
+ - `--ray-default`: #ffffff / color-mix(in srgb, #ffffff 3%, transparent)
3270
+ - `--ray-default-hover`: #f1f3f5 / color-mix(in srgb, #ffffff 7%, transparent)
3271
+ - `--ray-raised`: #ffffff / #424242
3272
+ - `--ray-muted`: #f8f9fa / #2e2e2e
3273
+ - `--ray-muted-foreground`: color-mix(in srgb, #495057 50%, #868e96) / color-mix(in srgb, #b8b8b8 75%, #828282)
3274
+ - `--ray-accent`: #f1f3f5 / #2e2e2e
3275
+ - `--ray-accent-foreground`: #212529 / #f1f3f5
3276
+ - `--ray-destructive`: #c92a2a
3277
+ - `--ray-destructive-hover`: color-mix(in srgb, #c92a2a 85%, #000000)
3278
+ - `--ray-destructive-foreground`: #ffffff
3279
+ - `--ray-success`: color-mix(in srgb, #2b8a3e 80%, #000000) / #51cf66
3280
+ - `--ray-warning`: color-mix(in srgb, #e67700 62%, #000000) / #fcc419
3281
+ - `--ray-info`: color-mix(in srgb, #0b7285 90%, #000000) / #3bc9db
3282
+ - `--ray-border`: #dee2e6 / #2e2e2e
3283
+ - `--ray-input`: #ced4da / #3b3b3b
3284
+ - `--ray-ring`: color-mix(in srgb, #228be6 55%, transparent) / color-mix(in srgb, #4dabf7 60%, transparent)
3285
+ - `--ray-overlay`: color-mix(in srgb, #000000 10%, transparent) / color-mix(in srgb, #000000 50%, transparent)
3286
+ - `--ray-overlay-border`: color-mix(in srgb, #000000 16%, transparent) / color-mix(in srgb, #ffffff 14%, transparent)
3287
+ - `--ray-selection`: color-mix(in srgb, #228be6 22%, transparent) / color-mix(in srgb, #4dabf7 30%, transparent)
3288
+
3289
+ chart:
3290
+
3291
+ - `--ray-chart-1`: #228be6 / #339af0
3292
+ - `--ray-chart-2`: #e8590c / #fd7e14
3293
+ - `--ray-chart-3`: #099268 / #20c997
3294
+ - `--ray-chart-4`: #7950f2 / #845ef7
3295
+ - `--ray-chart-5`: #e64980 / #f06595
3296
+ - `--ray-chart-6`: color-mix(in srgb, #e67700 70%, #2b8a3e) / #fcc419
3297
+ - `--ray-chart-7`: #0b7285 / #22b8cf
3298
+ - `--ray-chart-8`: #868e96
3299
+ - `--ray-chart-grid`: #e9ecef / #2e2e2e
3300
+ - `--ray-chart-axis`: color-mix(in srgb, #495057 50%, #868e96)
3301
+ - `--ray-chart-text`: #212529
3302
+ - `--ray-chart-tooltip`: #ffffff
3303
+ - `--ray-chart-tooltip-text`: #212529
3304
+ - `--ray-chart-tooltip-border`: #dee2e6
3305
+
3306
+ code:
3307
+
3308
+ - `--ray-code-background`: #f8f9fa / #19191a
3309
+ - `--ray-code-text`: #212529
3310
+ - `--ray-code-tag`: color-mix(in srgb, #2b8a3e 80%, #000000)
3311
+ - `--ray-code-attr`: #5f3dc4
3312
+ - `--ray-code-string`: #1864ab
3313
+ - `--ray-code-keyword`: #a61e4d
3314
+ - `--ray-code-number`: color-mix(in srgb, #d9480f 78%, #000000)
3315
+ - `--ray-code-comment`: color-mix(in srgb, #495057 50%, #868e96)
3316
+ - `--ray-code-punctuation`: color-mix(in srgb, #495057 50%, #868e96)
3317
+ - `--ray-code-function`: #364fc7
3318
+ - `--ray-code-type`: color-mix(in srgb, #087f5b 90%, #000000)
3319
+ - `--ray-code-added`: color-mix(in srgb, #2b8a3e 80%, #000000)
3320
+ - `--ray-code-removed`: color-mix(in srgb, #c92a2a 90%, #000000)
3321
+
3322
+ font:
3323
+
3324
+ - `--ray-font-sans`: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif
3325
+ - `--ray-font-mono`: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace
3326
+
3327
+ font-size:
3328
+
3329
+ - `--ray-font-size-xs`: 0.75rem
3330
+ - `--ray-font-size-sm`: 0.875rem
3331
+ - `--ray-font-size-md`: 1rem
3332
+ - `--ray-font-size-lg`: 1.125rem
3333
+ - `--ray-font-size-xl`: 1.25rem
3334
+ - `--ray-font-size-2xl`: 1.5rem
3335
+ - `--ray-font-size-3xl`: 1.875rem
3336
+ - `--ray-font-size-4xl`: 2.25rem
3337
+
3338
+ line-height:
3339
+
3340
+ - `--ray-line-height-tight`: 1.25
3341
+ - `--ray-line-height-heading`: 1.3
3342
+ - `--ray-line-height-xs`: 1.4
3343
+ - `--ray-line-height-sm`: 1.45
3344
+ - `--ray-line-height-md`: 1.55
3345
+ - `--ray-line-height-lg`: 1.6
3346
+ - `--ray-line-height-xl`: 1.65
3347
+
3348
+ font-weight:
3349
+
3350
+ - `--ray-font-weight-regular`: 400
3351
+ - `--ray-font-weight-medium`: 500
3352
+ - `--ray-font-weight-semibold`: 600
3353
+ - `--ray-font-weight-bold`: 700
3354
+
3355
+ space:
3356
+
3357
+ - `--ray-space-0`: 0
3358
+ - `--ray-space-1`: 0.25rem
3359
+ - `--ray-space-2`: 0.5rem
3360
+ - `--ray-space-3`: 0.75rem
3361
+ - `--ray-space-4`: 1rem
3362
+ - `--ray-space-5`: 1.25rem
3363
+ - `--ray-space-6`: 1.5rem
3364
+ - `--ray-space-8`: 2rem
3365
+ - `--ray-space-10`: 2.5rem
3366
+ - `--ray-space-12`: 3rem
3367
+ - `--ray-space-16`: 4rem
3368
+ - `--ray-space-xs`: 0.625rem
3369
+ - `--ray-space-sm`: 0.75rem
3370
+ - `--ray-space-md`: 1rem
3371
+ - `--ray-space-lg`: 1.25rem
3372
+ - `--ray-space-xl`: 2rem
3373
+
3374
+ radius:
3375
+
3376
+ - `--ray-radius-xs`: 0.125rem
3377
+ - `--ray-radius-sm`: 0.25rem
3378
+ - `--ray-radius-md`: 0.5rem
3379
+ - `--ray-radius-lg`: 1rem
3380
+ - `--ray-radius-xl`: 2rem
3381
+ - `--ray-radius-full`: 9999px
3382
+ - `--ray-radius-default`: 0.5rem
3383
+
3384
+ control-height:
3385
+
3386
+ - `--ray-control-height-xs`: 1.875rem
3387
+ - `--ray-control-height-sm`: 2.25rem
3388
+ - `--ray-control-height-md`: 2.625rem
3389
+ - `--ray-control-height-lg`: 3.125rem
3390
+ - `--ray-control-height-xl`: 3.75rem
3391
+
3392
+ shadow:
3393
+
3394
+ - `--ray-shadow-xs`: 0 1px 3px color-mix(in srgb, #000000 5%, transparent), 0 1px 2px color-mix(in srgb, #000000 10%, transparent)
3395
+ - `--ray-shadow-sm`: 0 1px 3px color-mix(in srgb, #000000 5%, transparent), 0 10px 15px -5px color-mix(in srgb, #000000 5%, transparent), 0 7px 7px -5px color-mix(in srgb, #000000 4%, transparent)
3396
+ - `--ray-shadow-md`: 0 1px 3px color-mix(in srgb, #000000 5%, transparent), 0 20px 25px -5px color-mix(in srgb, #000000 5%, transparent), 0 10px 10px -5px color-mix(in srgb, #000000 4%, transparent)
3397
+ - `--ray-shadow-lg`: 0 1px 3px color-mix(in srgb, #000000 5%, transparent), 0 28px 23px -7px color-mix(in srgb, #000000 5%, transparent), 0 12px 12px -7px color-mix(in srgb, #000000 4%, transparent)
3398
+ - `--ray-shadow-xl`: 0 1px 3px color-mix(in srgb, #000000 5%, transparent), 0 36px 28px -7px color-mix(in srgb, #000000 5%, transparent), 0 17px 17px -7px color-mix(in srgb, #000000 4%, transparent)
3399
+
3400
+ gradient:
3401
+
3402
+ - `--ray-gradient-from`: #3b5bdb
3403
+ - `--ray-gradient-to`: #6741d9
3404
+ - `--ray-gradient-deg`: 45deg
3405
+
3406
+ overlay:
3407
+
3408
+ - `--ray-overlay-blur`: 4px
3409
+
3410
+ focus:
3411
+
3412
+ - `--ray-focus-ring-width`: 2px
3413
+ - `--ray-focus-ring-offset`: 2px
3414
+
3415
+ duration:
3416
+
3417
+ - `--ray-duration-fast`: 120ms
3418
+ - `--ray-duration-base`: 200ms
3419
+ - `--ray-duration-slow`: 300ms
3420
+
3421
+ easing:
3422
+
3423
+ - `--ray-easing-standard`: cubic-bezier(0.2, 0, 0, 1)
3424
+ - `--ray-easing-in`: cubic-bezier(0.3, 0, 1, 1)
3425
+ - `--ray-easing-out`: cubic-bezier(0, 0, 0, 1)
3426
+
3427
+ z:
3428
+
3429
+ - `--ray-z-base`: 0
3430
+ - `--ray-z-sticky`: 200
3431
+ - `--ray-z-dropdown`: 300
3432
+ - `--ray-z-overlay`: 400
3433
+ - `--ray-z-modal`: 500
3434
+ - `--ray-z-popover`: 600
3435
+ - `--ray-z-toast`: 700
3436
+ - `--ray-z-tooltip`: 800
3437
+
3438
+ breakpoint:
3439
+
3440
+ - `breakpoint-xs` (tokens.json only): 36em
3441
+ - `breakpoint-sm` (tokens.json only): 48em
3442
+ - `breakpoint-md` (tokens.json only): 62em
3443
+ - `breakpoint-lg` (tokens.json only): 75em
3444
+ - `breakpoint-xl` (tokens.json only): 88em
3445
+
3446
+ ## Icons
3447
+
3448
+ The names `<ray-icon name>` and `setIcons()` know (more with `setIcons`):
3449
+
3450
+ `close`, `check`, `minus`, `plus`, `chevron-down`, `chevron-up`, `chevron-right`, `chevron-left`, `chevrons-left`, `chevrons-right`, `search`, `arrow-up-right`, `arrow-down-right`, `sun`, `moon`, `monitor`, `user`, `info`, `circle-check`, `alert-triangle`, `circle-x`, `menu`, `more-horizontal`, `file`, `folder`, `pause`, `play`, `terminal`, `calendar`, `image`, `download`, `eye`, `eye-off`, `bell`, `copy`, `pipette`, `star`, `upload`, `paperclip`, `panel-left`, `settings`, `home`, `arrow-left`, `message-circle`
3451
+
3452
+ ## Core API
3453
+
3454
+ What `@raylang/elements/core` (and `@raylang/elements`) exports besides the components: theme, icons, the native host, the base classes for your own components.
3455
+
3456
+ ```ts
3457
+ // Types of the ray-elements core runtime and extension API (core.js, form.js,
3458
+ // floating.js, styles.js, position.js, focus.js, icons.js, host.js, raylang.js). Hand-written;
3459
+ // the component declarations are generated after them into ray-elements.d.ts.
3460
+
3461
+ export declare const PREFIX: string;
3462
+ export declare const THEME_EVENT: "ray-theme-change";
3463
+
3464
+ export type Theme = "light" | "dark" | "system";
3465
+ export interface ThemeDetail {
3466
+ theme: Theme;
3467
+ resolved: "light" | "dark";
3468
+ primary: string | null;
3469
+ }
3470
+
3471
+ // --- styles and registration -------------------------------------------------
3472
+
3473
+ /** A constructable stylesheet from CSS text, shared by every user of the same text. */
3474
+ export declare function css(strings: TemplateStringsArray | string, ...values: unknown[]): CSSStyleSheet;
3475
+ /** The base sheet every component adopts first. */
3476
+ export declare const hostStyles: CSSStyleSheet;
3477
+ /** Registers a custom element unless the tag is already taken. */
3478
+ export declare function define(tag: string, cls: CustomElementConstructor): void;
3479
+ /** A document-unique id with the given stem. */
3480
+ export declare function uid(stem?: string): string;
3481
+
3482
+ /**
3483
+ * App-wide settings. `defaults` apply, per tag, to elements connected afterwards,
3484
+ * for the properties their markup and code leave unset.
3485
+ */
3486
+ export declare function configure(options?: { defaults?: Record<string, Record<string, unknown>> }): void;
3487
+ /** The defaults configure() set for a tag. */
3488
+ export declare function getDefaults(tag: string): Record<string, unknown>;
3489
+
3490
+ // --- theme -------------------------------------------------------------------
3491
+
3492
+ export declare function getTheme(el?: Element): Theme;
3493
+ export declare function resolvedTheme(el?: Element): "light" | "dark";
3494
+ export declare function setTheme(theme: Theme, options?: { el?: Element; persist?: boolean }): void;
3495
+ export declare function getPrimary(el?: Element): string | null;
3496
+ export declare function setPrimary(color: string | null, options?: { el?: Element; persist?: boolean }): void;
3497
+ export declare function onThemeChange(cb: (detail: ThemeDetail) => void): () => void;
3498
+ /**
3499
+ * Makes any CSS color the primary (data-primary="custom"): ten OKLCH shades,
3500
+ * white or black text by contrast; warns below WCAG AA.
3501
+ */
3502
+ export declare function definePrimary(
3503
+ color: string,
3504
+ options?: { el?: Element; persist?: boolean },
3505
+ ): { shades: string[]; filled: string; contrast: "white" | "black"; ratio: number; aa: boolean };
3506
+ /** The color last given to definePrimary() for an element, as "#rrggbb" (null if none). */
3507
+ export declare function getCustomPrimary(el?: Element): string | null;
3508
+
3509
+ // --- icons -------------------------------------------------------------------
3510
+
3511
+ /** Replaces or adds icons (SVG markup or an SVGElement); repaints every component. */
3512
+ export declare function setIcons(icons: Record<string, string | SVGElement>): void;
3513
+ /** The SVG markup of a registered icon ("" if unknown). */
3514
+ export declare function getIcon(name: string): string;
3515
+ /** The registered icon names. */
3516
+ export declare function iconNames(): string[];
3517
+
3518
+ // --- base classes ------------------------------------------------------------
3519
+
3520
+ export interface PropertyOptions {
3521
+ type?: StringConstructor | NumberConstructor | BooleanConstructor;
3522
+ reflect?: boolean;
3523
+ attribute?: string | false;
3524
+ default?: unknown;
3525
+ }
3526
+
3527
+ /**
3528
+ * Base class of ray-elements components. Members whose name starts with `_` or `#`
3529
+ * are internal: do not use them, and do not name your own members with `_`.
3530
+ */
3531
+ export declare class RayElement extends HTMLElement {
3532
+ static properties: Record<string, PropertyOptions>;
3533
+ static styles: CSSStyleSheet[];
3534
+ static template: string;
3535
+ static delegatesFocus: boolean;
3536
+ /** Adds stylesheets to this component and its subclasses, live instances included. */
3537
+ static extendStyles(...sheets: CSSStyleSheet[]): void;
3538
+ connectedCallback(): void;
3539
+ disconnectedCallback(): void;
3540
+ attributeChangedCallback(attr: string, old: string | null, value: string | null): void;
3541
+ /** Schedules update() for the next microtask. */
3542
+ requestUpdate(): void;
3543
+ /** Protected: called after property changes with their previous values. */
3544
+ protected update(changed: Map<string, unknown>): void;
3545
+ /** Protected: sets a declared property without reflecting it (state changed by the user). */
3546
+ commitProperty(name: string, value: unknown): boolean;
3547
+ /** Protected: whether a declared property has its own value (not the default). */
3548
+ hasValue(name: string): boolean;
3549
+ /** Protected: fills [data-ray-icon] placeholders from the icon registry. */
3550
+ paintIcons(root?: ParentNode): void;
3551
+ /** Dispatches a bubbling, composed CustomEvent; false if a listener canceled it. */
3552
+ emit<T = unknown>(type: string, detail?: T, options?: { cancelable?: boolean }): boolean;
3553
+ /** querySelector inside the shadow root. */
3554
+ $<E extends Element = HTMLElement>(selector: string): E | null;
3555
+ }
3556
+
3557
+ /** A form-associated ray-elements element (ElementInternals). */
3558
+ export declare class FormControl extends RayElement {
3559
+ static formAssociated: true;
3560
+ readonly internals: ElementInternals;
3561
+ readonly form: HTMLFormElement | null;
3562
+ readonly validity: ValidityState;
3563
+ readonly validationMessage: string;
3564
+ readonly willValidate: boolean;
3565
+ /** Disabled by its own attribute or by a disabled <fieldset>. */
3566
+ readonly effectivelyDisabled: boolean;
3567
+ checkValidity(): boolean;
3568
+ reportValidity(): boolean;
3569
+ /** Protected: re-dispatches a non-composed event (e.g. change) from the host. */
3570
+ forward(event: Event): void;
3571
+ formDisabledCallback(disabled: boolean): void;
3572
+ }
3573
+
3574
+ /**
3575
+ * A FormControl around one native control (#control in the shadow root),
3576
+ * with label, description, error, required and their ARIA.
3577
+ */
3578
+ export declare class FieldControl extends FormControl {
3579
+ /** Spread into `static properties`: name, label, description, error, required, disabled, size, radius, variant. */
3580
+ static fieldProperties: Record<string, PropertyOptions>;
3581
+ /** The native control in the shadow root. */
3582
+ readonly control: HTMLInputElement & HTMLTextAreaElement & HTMLSelectElement;
3583
+ name: string | undefined;
3584
+ label: string | undefined;
3585
+ description: string | undefined;
3586
+ error: string | undefined;
3587
+ required: boolean | undefined;
3588
+ disabled: boolean | undefined;
3589
+ size: string;
3590
+ radius: string | undefined;
3591
+ variant: string;
3592
+ descriptionPosition: string;
3593
+ /** Protected hook: attach listeners once, on first connection. */
3594
+ wire?(): void;
3595
+ /** Protected: label, description, error, ARIA and validity (call from update). */
3596
+ syncField(): void;
3597
+ /** Protected: mirrors the native control's validity into the form. */
3598
+ syncValidity(): void;
3599
+ }
3600
+ /** The field wrapper markup around `control` (an element with id="control" class="control"). */
3601
+ export declare function fieldTemplate(control: string, options?: { sections?: boolean }): string;
3602
+ export declare const fieldStyles: CSSStyleSheet;
3603
+ export declare const boxStyles: CSSStyleSheet;
3604
+
3605
+ /** Base of trigger + floating panel components (Popover API, anchored placement). */
3606
+ export declare class Floating extends RayElement {
3607
+ /** popover attribute of the panel: "manual" (default; light dismiss and exit animation done by Floating) or "auto" (the browser's, no exit animation). */
3608
+ static popoverMode: "auto" | "manual";
3609
+ /** Close on Escape and outside presses (default true; tooltips: false). */
3610
+ static lightDismiss: boolean;
3611
+ /** aria-haspopup of the trigger (null: none). */
3612
+ static haspopup: string | null;
3613
+ /** Selector of the slot holding the trigger. */
3614
+ static triggerSlot: string;
3615
+ open: boolean | undefined;
3616
+ placement: string;
3617
+ offset: number;
3618
+ /** The [popover] panel in the shadow root (set on connection). */
3619
+ panel: HTMLElement;
3620
+ readonly trigger: Element | null;
3621
+ /** Whether focus was inside the panel when it started closing. */
3622
+ focusWasInside: boolean | undefined;
3623
+ show(): void;
3624
+ hide(): void;
3625
+ toggle(): void;
3626
+ /** Places the panel again (scroll and resize already do it). */
3627
+ reposition(): void;
3628
+ /** Protected hooks. */
3629
+ wireTrigger(trigger: Element): void;
3630
+ anchorRect(): { left: number; top: number; right: number; bottom: number; width: number; height: number };
3631
+ placeOptions(): PlaceOptions;
3632
+ popupKind(): string | null;
3633
+ toggled(open: boolean): void;
3634
+ /** Keyframes the panel leaves with (default: fade + scale 0.97). */
3635
+ exitKeyframes(): Keyframe[];
3636
+ /** Whether the same pointer gesture just light-dismissed the panel. */
3637
+ justClosed(): boolean;
3638
+ }
3639
+ export declare const floatingStyles: CSSStyleSheet;
3640
+
3641
+ // --- shared styles -----------------------------------------------------------
3642
+
3643
+ export declare const COLORS: string[];
3644
+ export declare const VARIANT_TOKENS: string[];
3645
+ /** Points an element's --_<variant> properties at a palette color, any CSS color, or the primary. */
3646
+ export declare function applyColor(el: HTMLElement, color: string | undefined): void;
3647
+ /** A spacing value as CSS: xs…xl as its --ray-space token, a bare number as px, else a CSS length; null when empty. */
3648
+ export declare function spaceValue(value: string | number | undefined): string | null;
3649
+ /** :host size scale: --_h, --_fs, --_px, --_gap by [size]. */
3650
+ export declare const sizeStyles: CSSStyleSheet;
3651
+ /** :host radius: --_r by [radius]. */
3652
+ export declare const radiusStyles: CSSStyleSheet;
3653
+ /** [data-variant] backgrounds/colors from the --_<variant> properties. */
3654
+ export declare const variantStyles: CSSStyleSheet;
3655
+ /** The backdrop of modal overlays: --ray-overlay and --ray-overlay-blur on dialog::backdrop. */
3656
+ export declare const overlayStyles: CSSStyleSheet;
3657
+ // --- motion and light dismiss ------------------------------------------------
3658
+
3659
+ /** A duration token in ms ("fast" | "base" | "slow"). */
3660
+ export declare function duration(el: Element, name?: "fast" | "base" | "slow"): number;
3661
+ /** False with reduced motion, a zero duration token or a hidden page. */
3662
+ export declare function motionAllowed(el: Element, name?: "fast" | "base" | "slow"): boolean;
3663
+ /** Plays keyframes (fill: forwards); resolves at once when motion is not allowed. Call cancel() after hiding. */
3664
+ export declare function play(el: Element, keyframes: Keyframe[], options?: { speed?: "fast" | "base" | "slow"; ease?: "standard" | "in" | "out"; pseudoElement?: string }): { finished: Promise<void>; cancel(): void };
3665
+ /** Waits for several play() results. */
3666
+ export declare function playAll(list: Array<{ finished: Promise<void>; cancel(): void }>): { finished: Promise<void>; cancel(): void };
3667
+ /** Fades and folds an element to zero height. */
3668
+ export declare function collapseOut(el: Element, options?: { speed?: "fast" | "base" | "slow" }): { finished: Promise<void>; cancel(): void };
3669
+ /** The default exit of floating panels. */
3670
+ export declare const POP_OUT: Keyframe[];
3671
+ /** Registers an open manual panel for Escape / outside-press dismissal; returns the unregister function. */
3672
+ export declare function dismissable(entry: { panel: Element; owner: Element; trigger?: Element | null; close: (reason: "outside" | "escape" | "replaced") => void }): () => void;
3673
+
3674
+ /** Sets --ray-overlay-blur on an element: a number (px), a CSS length or "none"; empty removes it. */
3675
+ export declare function applyOverlayBlur(el: HTMLElement, value: string | number | null | undefined): void;
3676
+ /** A ring spinner: <span class="loader">. */
3677
+ export declare const loaderStyles: CSSStyleSheet;
3678
+ /** .sr-only: hidden but announced. */
3679
+ export declare const srOnlyStyles: CSSStyleSheet;
3680
+
3681
+ // --- positioning and focus ---------------------------------------------------
3682
+
3683
+ export interface PlaceOptions {
3684
+ placement?: string;
3685
+ offset?: number;
3686
+ padding?: number;
3687
+ flip?: boolean;
3688
+ matchWidth?: boolean;
3689
+ }
3690
+ export declare function place(
3691
+ anchor: { left: number; top: number; right: number; bottom: number; width: number; height: number },
3692
+ floating: HTMLElement,
3693
+ options?: PlaceOptions,
3694
+ ): string;
3695
+ export declare function pointRect(x: number, y: number): DOMRectReadOnly;
3696
+ export declare function autoUpdate(anchor: Element | object, floating: HTMLElement, update: () => void): () => void;
3697
+ /** Tabbable elements under root, through shadow roots and slots. */
3698
+ export declare function tabbables(root: Element | ShadowRoot, options?: { lightOnly?: boolean }): HTMLElement[];
3699
+ /** Focuses the first [autofocus] or tabbable element; whether something got focus. */
3700
+ export declare function focusFirst(root: Element | ShadowRoot, options?: { lightOnly?: boolean }): boolean;
3701
+
3702
+ // --- charts (core/charts.js) -----------------------------------------------------
3703
+
3704
+ /** Number of series colors (--ray-chart-1 … --ray-chart-8). */
3705
+ export declare const CHART_SERIES: number;
3706
+ /** The chart tokens resolved to concrete colors for the theme of an element. */
3707
+ export interface ChartTheme {
3708
+ scheme: "light" | "dark";
3709
+ /** Series colors, in order (#rrggbb). */
3710
+ series: string[];
3711
+ background: string;
3712
+ grid: string;
3713
+ axis: string;
3714
+ text: string;
3715
+ tooltip: { background: string; text: string; border: string };
3716
+ font: { family: string; size: number };
3717
+ }
3718
+ export declare function chartTheme(el?: Element): ChartTheme;
3719
+ /** Calls cb with the new chart theme whenever the theme changes; returns a stop function. */
3720
+ export declare function onChartThemeChange(cb: (theme: ChartTheme) => void, el?: Element): () => void;
3721
+ /** A color with an alpha, as rgba(): withAlpha("#1c7ed6", 0.2). */
3722
+ export declare function withAlpha(color: string, alpha: number): string;
3723
+
3724
+ // --- scrolling ---------------------------------------------------------------
3725
+
3726
+ /** The scroller of an element: `target`, else the content of its ray-app-shell or ray-scroll-area, else the window. */
3727
+ export declare function scrollerOf(el: Element, target?: Element | string | null): Element | Window;
3728
+ /** Calls cb with the scroll position and direction ("down" | "up") once per frame; returns a stop function. */
3729
+ export declare function watchScroll(scroller: Element | Window, cb: (state: { y: number; direction: "up" | "down" }) => void, options?: { tolerance?: number }): () => void;
3730
+
3731
+ // --- native host (core/host.js, core/raylang.js) -----------------------------
3732
+
3733
+ /** A file a native host chose: a path on disk, with the File fields components read. */
3734
+ export declare class HostFile {
3735
+ constructor(init: { path: string; name?: string; size?: number; type?: string; lastModified?: number });
3736
+ readonly path: string;
3737
+ readonly name: string;
3738
+ readonly size: number;
3739
+ readonly type: string;
3740
+ readonly lastModified: number;
3741
+ }
3742
+ export interface FileFilter {
3743
+ name: string;
3744
+ extensions: string[];
3745
+ }
3746
+ /** What the program around the page can do natively; components use it when it is there. */
3747
+ export interface Host {
3748
+ name: string;
3749
+ can(op: "pick_files" | "pick_path" | "confirm" | "menu_items" | "run_menu" | "popup_menu" | "window_colors" | "set_edited" | (string & {})): boolean;
3750
+ pickFiles?(options?: { title?: string; multiple?: boolean; directory?: string; filters?: FileFilter[] }): Promise<HostFile[]>;
3751
+ pickPath?(options?: { mode?: "open" | "folder" | "save"; title?: string; directory?: string; suggested?: string; filters?: FileFilter[] }): Promise<string | null>;
3752
+ menuItems?(): Promise<HostMenuItem[]>;
3753
+ runMenu?(tag: string): Promise<true>;
3754
+ popupMenu?(items: { title?: string; enabled?: boolean; checked?: boolean; separator?: boolean }[]): Promise<number | null>;
3755
+ setEdited?(edited: boolean): Promise<true>;
3756
+ setWindowColors?(colors: { background?: string; titlebar?: string }): Promise<true>;
3757
+ /** Set when the page runs under a transparent title bar (px). */
3758
+ titlebar?: { height: number; inset: number } | null;
3759
+ confirm?(options?: { title?: string; message?: string; confirmLabel?: string; cancelLabel?: string; style?: "" | "info" | "warning" | "error" }): Promise<boolean>;
3760
+ }
3761
+ /** An item of the app's native menu bar, as a host lists it. */
3762
+ export interface HostMenuItem {
3763
+ menu: string;
3764
+ tag: string;
3765
+ title: string;
3766
+ /** A chord such as "cmd+shift+s" (cmd: ⌘ on macOS, Ctrl elsewhere); "" for none. */
3767
+ shortcut: string;
3768
+ enabled: boolean;
3769
+ checked: boolean;
3770
+ }
3771
+ export declare function setHost(host: Host | null): void;
3772
+ export declare function getHost(): Host | null;
3773
+ export declare function hostCan(op: string): boolean;
3774
+ /** Calls cb whenever the host changes; returns the unsubscribe function. */
3775
+ export declare function onHostChange(cb: (host: Host | null) => void): () => void;
3776
+ /** The title bar the page runs under ({ height, inset } px), or null. */
3777
+ export declare function titlebar(): { height: number; inset: number } | null;
3778
+ /** Makes el drag the window under a host's title bar (data-ray-drag); returns the undo function. */
3779
+ export declare function dragRegion(el: Element): () => void;
3780
+ export interface EditTracker {
3781
+ readonly dirty: boolean;
3782
+ /** Takes the current values as saved. */
3783
+ clean(): void;
3784
+ check(): void;
3785
+ stop(): void;
3786
+ }
3787
+ /** Follows whether a form has unsaved changes; with a host, the window shows it. */
3788
+ export declare function trackEdits(form: HTMLFormElement, options?: { onChange?: (dirty: boolean) => void }): EditTracker;
3789
+ /** The MIME type of a file name, from its extension ("" when unknown). */
3790
+ export declare function typeOfName(name: string): string;
3791
+ /** The file dialog filters of an accept list ([] = any file); `name` defaults to the extensions. */
3792
+ export declare function acceptFilters(accept: string | null | undefined, name?: string): FileFilter[];
3793
+ /** The extensions of a MIME type or pattern ("image/*"). */
3794
+ export declare function extensionsOfType(type: string): string[];
3795
+
3796
+ /** The version of the ray-elements bridge protocol the page speaks. */
3797
+ export declare const PROTOCOL: number;
3798
+ export interface RaylangHost extends Host {
3799
+ name: "raylang";
3800
+ platform: string;
3801
+ version: string;
3802
+ }
3803
+ /**
3804
+ * In a std/ui window whose program calls elements/bridge's handle(), installs the
3805
+ * raylang host; null in a browser or when the program does not answer in `timeout` ms.
3806
+ */
3807
+ export declare function enableRaylang(options?: { timeout?: number; ray?: unknown; windowColors?: boolean }): Promise<RaylangHost | null>;
3808
+ ```