@vestra-player/sdk 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README.md +1 -0
- package/dist/commands.d.ts +1 -1
- package/dist/plugin/appearance.js +1 -1
- package/dist/plugin/types.d.ts +36 -16
- package/package.json +1 -1
- package/slint/palette.slint +34 -24
- package/slint/vestra/icons.slint +99 -0
- package/slint/vestra/markdown.slint +6 -8
- package/slint/vestra/theme.slint +12 -8
- package/slint/vestra/widgets.slint +15 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.5.0
|
|
4
|
+
|
|
5
|
+
**Own visual identity: the Aurora palettes and the V-Line icons** (player 0.4.0). Additive; `apiVersion` stays `vestra/1`. Plugins that use the additions set `"minPlayerVersion": "0.4.0"`.
|
|
6
|
+
|
|
7
|
+
- **`ThemeId` gains `"vestra-light"`**, a light palette whose video area stays dark. `plugin.appearance.set("vestra-light")` switches every view; `TestHost` accepts it like the player. A player older than 0.4.0 answers it with `vestra` (an id it does not have).
|
|
8
|
+
- **New colours for `vestra`.** The palette is now Aurora, drawn from the logo's full spectrum: magenta accent (`#f72aa6`), cyan for what is playing (`Theme.playing`, `#2bb6ff`, violet before), `Theme.accent-fill` from amber through magenta and violet to cyan, and a visible `Theme.line` (`#2b2734`; it was near-black). Token names are unchanged; code that reads `Theme` follows.
|
|
9
|
+
- **Rounder corners**: `Theme.radius-control` 4px (was 3px), `Theme.radius-panel` 8px (was 6px). Sizes are otherwise unchanged.
|
|
10
|
+
- **`@vestra/icons.slint`** (new library file, `slint/vestra/icons.slint`): `Icon { name: "play"; color: Theme.text; }` draws one icon of the player's own set (round-capped 1.5px lines), and `Icons.commands(name)` / `box-width` / `box-height` / `line` give its path data. The names are listed in **Windows, panels, settings pages, dialogs and the OSD**.
|
|
11
|
+
- **`@vestra/widgets.slint`**: the bar slider's thumb is a white core in a 2px accent ring; the panel slider's track is `Theme.line`; stroked icon buttons use round caps and joins; tooltips have rounded corners. Geometry and API are unchanged.
|
|
12
|
+
- **std-widgets in a light palette**: the player still compiles plugin files with `fluent-dark` and switches the std-widgets colour scheme (`Palette.color-scheme`) to light for `vestra-light`, so `CheckBox`, `ComboBox`, `LineEdit`, `ScrollView` and the other std-widgets controls follow. The player's palette file (`slint/palette.slint`, not part of the library) now imports `std-widgets.slint` for that.
|
|
13
|
+
|
|
14
|
+
## 1.4.1
|
|
15
|
+
|
|
16
|
+
Documentation only; no code or type changes.
|
|
17
|
+
|
|
18
|
+
- **Built-in menus keep their place** (player 0.3.0). `CommandOptions` and `CommandOptions.order` document the player's menu rule: the seven built-in top-level menus (`@open` … `@settings`) sit at fixed orders (Open 110, Playback 200, Subtitles 300, Video 400, Audio 500, Screen 710, Settings 830), whether a path names them by id or by title, so a plugin's item never moves them. Directly inside a built-in menu, `order` 0 (the default) sorts after every other order, so an item without `order` goes at the end. Players before 0.3.0 move the whole menu to the top for such an item; give it an order in the menu's range there.
|
|
19
|
+
- The Blur walkthrough explains `order` inside the Video menu accordingly.
|
|
20
|
+
|
|
3
21
|
## 1.4.0
|
|
4
22
|
|
|
5
23
|
**One palette.** `ThemeId` is now `"vestra"` only: the second palette that earlier versions listed is gone from the player. This is a minor version although a type narrows, because the only plugins it affects compare `plugin.appearance.theme` with, or `set` the removed id:
|
package/README.md
CHANGED
|
@@ -82,6 +82,7 @@ Complete, tested plugins in [`examples/`](https://github.com/vestrasys/vestra-pl
|
|
|
82
82
|
| 1.2 | `vestra/1` | 0.2 or newer | 26 (shipped with the player) |
|
|
83
83
|
| 1.3 | `vestra/1` | 0.2 or newer; 0.3 for the 1.3 additions (menu ids, `Theme.danger`, empty video chains) | 26 (shipped with the player) |
|
|
84
84
|
| 1.4 | `vestra/1` | 0.2 or newer; 0.3 for the 1.3 additions. `ThemeId` is `"vestra"` only (see the CHANGELOG) | 26 (shipped with the player) |
|
|
85
|
+
| 1.5 | `vestra/1` | 0.2 or newer; 0.3 for the 1.3 additions; 0.4 for the 1.5 additions (`vestra-light`, `@vestra/icons.slint`) | 26 (shipped with the player) |
|
|
85
86
|
|
|
86
87
|
Minor releases only add backwards-compatible API; a breaking change gets a new `apiVersion` and a new major version. `@vestra-player/sdk/runtime` is for the player only and not covered by semver.
|
|
87
88
|
|
package/dist/commands.d.ts
CHANGED
|
@@ -54,7 +54,7 @@ export type CommandDeclaration = {
|
|
|
54
54
|
title: string;
|
|
55
55
|
/** Complete primary menu path INCLUDING its leaf; empty = not in the main menu. */
|
|
56
56
|
path: string[];
|
|
57
|
-
/** Sibling order, ascending; a submenu takes its first command's order. */
|
|
57
|
+
/** Sibling order, ascending; a submenu takes its first command's order (a built-in menu keeps a fixed one). */
|
|
58
58
|
order: number;
|
|
59
59
|
/** Separator label: adjacent siblings of different groups get a line. */
|
|
60
60
|
group: string;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { failure } from "./runtime.js";
|
|
3
3
|
import { windowOf } from "./window.js";
|
|
4
4
|
/** The palettes this SDK knows, the default first. */
|
|
5
|
-
export const THEMES = ["vestra"];
|
|
5
|
+
export const THEMES = ["vestra", "vestra-light"];
|
|
6
6
|
/**
|
|
7
7
|
* One per plugin: the value comes with the `window.state` read before
|
|
8
8
|
* activation; with `events`, `appearance.changed` keeps it current once
|
package/dist/plugin/types.d.ts
CHANGED
|
@@ -376,6 +376,21 @@ export type MenuId = "open" | "playback" | "subtitles" | "video" | "audio" | "sc
|
|
|
376
376
|
* ranges: `open` 100–199, `domain` 200–699 (playback, subtitles, video,
|
|
377
377
|
* audio…), `screen` 700–799, `windows` 800–899, `exit` 900–999.
|
|
378
378
|
*
|
|
379
|
+
* Built-in menus keep their place. The seven built-in top-level menus
|
|
380
|
+
* ({@link MenuId}) sit at fixed orders, whatever is inside them: Open 110,
|
|
381
|
+
* Playback 200, Subtitles 300, Video 400, Audio 500, Screen 710, Settings
|
|
382
|
+
* 830 (player 0.3.0). This holds whether the path names the menu by id
|
|
383
|
+
* (`["@video", "Blur"]`) or by its title (`["视频", "Blur"]`), so a plugin's
|
|
384
|
+
* item never moves the player's menu. Directly inside a built-in menu,
|
|
385
|
+
* `order` 0 (the default) sorts after every other order: an item without
|
|
386
|
+
* `order` goes at the end, after the player's own items (which all use 100
|
|
387
|
+
* or more). Give a positive order to sit between them (the player's orders
|
|
388
|
+
* are listed in its menu table, doc/product/menus.md), or a negative one to
|
|
389
|
+
* come first. Deeper levels (a plugin's own submenu) have no such rule.
|
|
390
|
+
* Players before 0.3.0 place every submenu at its smallest order, so there
|
|
391
|
+
* an item without `order` moves the whole menu to the top; to avoid that,
|
|
392
|
+
* give it an order in the menu's range (Video: 400–499).
|
|
393
|
+
*
|
|
379
394
|
* {@link Commands.add} throws `invalid` synchronously for a bad path,
|
|
380
395
|
* order, group or binding. The same path registered twice, or a path that
|
|
381
396
|
* is both an item and a submenu, fails with `conflict` (through `ready`).
|
|
@@ -406,8 +421,10 @@ export interface CommandOptions {
|
|
|
406
421
|
title?: string;
|
|
407
422
|
/**
|
|
408
423
|
* Sibling order in the menu, ascending (integer, default 0). A submenu sits
|
|
409
|
-
* where its first command sits
|
|
410
|
-
*
|
|
424
|
+
* where its first command sits, except a built-in menu, which keeps its
|
|
425
|
+
* fixed place. Directly inside a built-in menu, 0 (the default) sorts last.
|
|
426
|
+
* Equal orders: plugin id, then declaration order. Range ±1,000,000. See
|
|
427
|
+
* {@link CommandOptions} for the menu order rules.
|
|
411
428
|
*/
|
|
412
429
|
order?: number;
|
|
413
430
|
/** Separator label: a line is drawn between adjacent items of different groups. Default `"domain"`. */
|
|
@@ -1562,19 +1579,20 @@ export interface Drops {
|
|
|
1562
1579
|
provide(handler: DropHandler): Disposable;
|
|
1563
1580
|
}
|
|
1564
1581
|
/**
|
|
1565
|
-
* The player's palettes
|
|
1566
|
-
*
|
|
1567
|
-
* `Theme` instead of
|
|
1582
|
+
* The player's palettes: `vestra`, the dark default, and `vestra-light`
|
|
1583
|
+
* (player 0.4.0, SDK 1.5.0), a light palette whose video area stays dark.
|
|
1584
|
+
* Both draw on the logo's colours. Read colours from `Theme` instead of
|
|
1585
|
+
* branching on the id: a later version may add palettes.
|
|
1568
1586
|
*
|
|
1569
1587
|
* @remarks
|
|
1570
|
-
*
|
|
1571
|
-
*
|
|
1572
|
-
*
|
|
1588
|
+
* The player treats an id it does not have as `vestra`: plugins built with an
|
|
1589
|
+
* older SDK that still ask for a palette removed in SDK 1.4.0 keep working,
|
|
1590
|
+
* and a player older than 0.4.0 answers `vestra-light` with `vestra`.
|
|
1573
1591
|
*
|
|
1574
1592
|
* @since 1.0.0
|
|
1575
1593
|
* @category UI
|
|
1576
1594
|
*/
|
|
1577
|
-
export type ThemeId = "vestra";
|
|
1595
|
+
export type ThemeId = "vestra" | "vestra-light";
|
|
1578
1596
|
/**
|
|
1579
1597
|
* The player's palette, which every view uses. `plugin.appearance`.
|
|
1580
1598
|
*
|
|
@@ -1584,7 +1602,9 @@ export type ThemeId = "vestra";
|
|
|
1584
1602
|
* and again when the palette changes. Slint code that reads its colours from
|
|
1585
1603
|
* `Theme` (`import { Theme } from "@vestra/theme.slint"`) follows it with no
|
|
1586
1604
|
* plugin code; hard-coded colours do not. Only colours change: corner radii,
|
|
1587
|
-
* font sizes and control sizes are the same in every palette.
|
|
1605
|
+
* font sizes and control sizes are the same in every palette. A light palette
|
|
1606
|
+
* also switches the std-widgets controls (`std-widgets.slint`) to their light
|
|
1607
|
+
* colours, and keeps the video area dark.
|
|
1588
1608
|
*
|
|
1589
1609
|
* The player saves the choice; it stays after the plugin that set it stops.
|
|
1590
1610
|
* Tell the user about a change yourself (for example with
|
|
@@ -1593,14 +1613,14 @@ export type ThemeId = "vestra";
|
|
|
1593
1613
|
* @capability None to read `theme`; `events` to follow changes; `ui.theme`
|
|
1594
1614
|
* to change it.
|
|
1595
1615
|
*
|
|
1596
|
-
* @example A menu item that selects the palette
|
|
1616
|
+
* @example A menu item that selects the light palette
|
|
1597
1617
|
* ```ts
|
|
1598
1618
|
* plugin.commands.add({
|
|
1599
|
-
* id: "
|
|
1600
|
-
* path: ["@settings", "
|
|
1619
|
+
* id: "light-colours",
|
|
1620
|
+
* path: ["@settings", "Light colours"],
|
|
1601
1621
|
* radio: true,
|
|
1602
|
-
* checked: () => plugin.appearance.theme === "vestra",
|
|
1603
|
-
* run: () => plugin.appearance.set("vestra"),
|
|
1622
|
+
* checked: () => plugin.appearance.theme === "vestra-light",
|
|
1623
|
+
* run: () => plugin.appearance.set("vestra-light"),
|
|
1604
1624
|
* });
|
|
1605
1625
|
* ```
|
|
1606
1626
|
*
|
|
@@ -1657,7 +1677,7 @@ export interface Appearance {
|
|
|
1657
1677
|
*
|
|
1658
1678
|
* @example
|
|
1659
1679
|
* ```ts
|
|
1660
|
-
* await plugin.appearance.set("vestra");
|
|
1680
|
+
* await plugin.appearance.set("vestra-light");
|
|
1661
1681
|
* ```
|
|
1662
1682
|
*
|
|
1663
1683
|
* @since 1.0.0
|
package/package.json
CHANGED
package/slint/palette.slint
CHANGED
|
@@ -1,32 +1,42 @@
|
|
|
1
1
|
// The player's colour palette (R-H6) and per-system fonts. Not part of the
|
|
2
2
|
// plugin library: the player sets these `in` properties on every view;
|
|
3
3
|
// `Theme` in @vestra/theme.slint reads them as `out` properties. Defaults:
|
|
4
|
-
//
|
|
4
|
+
// the Aurora colours of the `vestra` palette, the macOS fonts.
|
|
5
|
+
import { Palette } from "std-widgets.slint";
|
|
6
|
+
|
|
5
7
|
export global VestraPalette {
|
|
6
|
-
in property <color> bg-bar: #
|
|
7
|
-
in property <color> bg-video: #
|
|
8
|
-
in property <color> bg-list: #
|
|
9
|
-
in property <color> bg-panel: #
|
|
10
|
-
in property <color> line: #
|
|
11
|
-
in property <color> hover-bg: #
|
|
12
|
-
in property <color> press-bg: #
|
|
13
|
-
in property <color> selected-bg: #
|
|
14
|
-
in property <color> text: #
|
|
15
|
-
in property <color> text-dim: #
|
|
16
|
-
in property <color> text-list: #
|
|
17
|
-
in property <color> text-played: #
|
|
18
|
-
in property <color> accent: #
|
|
19
|
-
in property <color> accent-press: #
|
|
20
|
-
in property <color> accent-disabled: #
|
|
21
|
-
in property <color> icon-disabled: #
|
|
22
|
-
in property <color> playing: #
|
|
23
|
-
in property <color> button-bg: #
|
|
24
|
-
in property <color> button-hover: #
|
|
25
|
-
in property <color> button-press: #
|
|
26
|
-
in property <color> button-disabled: #
|
|
8
|
+
in property <color> bg-bar: #16141c;
|
|
9
|
+
in property <color> bg-video: #0a090e;
|
|
10
|
+
in property <color> bg-list: #1a1821;
|
|
11
|
+
in property <color> bg-panel: #201d28;
|
|
12
|
+
in property <color> line: #2b2734;
|
|
13
|
+
in property <color> hover-bg: #28232f;
|
|
14
|
+
in property <color> press-bg: #110f16;
|
|
15
|
+
in property <color> selected-bg: #2f2840;
|
|
16
|
+
in property <color> text: #f5f3fa;
|
|
17
|
+
in property <color> text-dim: #8e88a0;
|
|
18
|
+
in property <color> text-list: #bdb8cb;
|
|
19
|
+
in property <color> text-played: #6e6980;
|
|
20
|
+
in property <color> accent: #f72aa6;
|
|
21
|
+
in property <color> accent-press: #c41a83;
|
|
22
|
+
in property <color> accent-disabled: #5a1d48;
|
|
23
|
+
in property <color> icon-disabled: #3b3646;
|
|
24
|
+
in property <color> playing: #2bb6ff;
|
|
25
|
+
in property <color> button-bg: #2f2a3b;
|
|
26
|
+
in property <color> button-hover: #3a3448;
|
|
27
|
+
in property <color> button-press: #25202e;
|
|
28
|
+
in property <color> button-disabled: #1b1922;
|
|
27
29
|
// Errors and destructive actions (failed status, delete).
|
|
28
|
-
in property <color> danger: #
|
|
30
|
+
in property <color> danger: #ff5a5f;
|
|
29
31
|
// The system's monospace family (platform::monospace_font).
|
|
30
32
|
in property <string> font-mono: "Menlo";
|
|
31
|
-
|
|
33
|
+
// Each palette's progress gradient, logo amber → magenta → violet → cyan.
|
|
34
|
+
// The player copies one into `accent-fill` (Slint's Rust API cannot
|
|
35
|
+
// build gradients).
|
|
36
|
+
out property <brush> fill-vestra: @linear-gradient(90deg, #fcc402 0%, #fb5a35 20%, #fa0aa8 45%, #7a0afa 72%, #10a8fc 100%);
|
|
37
|
+
out property <brush> fill-vestra-light: @linear-gradient(90deg, #f5a700 0%, #f0442f 20%, #e0089a 45%, #6a08e8 72%, #0a95e6 100%);
|
|
38
|
+
in property <brush> accent-fill: self.fill-vestra;
|
|
39
|
+
// The std-widgets (fluent) controls follow the palette: the player sets
|
|
40
|
+
// `light` for a light palette.
|
|
41
|
+
in-out property <ColorScheme> color-scheme <=> Palette.color-scheme;
|
|
32
42
|
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// The V-Line icon set (doc/product/ui-spec.md §2.4): round-capped, round-joined
|
|
2
|
+
// lines, 1.5px (1.25px for the small glyphs), never filled. The V of the
|
|
3
|
+
// logo recurs: « » for back and forward, ∧ ∨ for moving rows, a small V for
|
|
4
|
+
// every menu, list and scroll arrow.
|
|
5
|
+
// import { Icon } from "@vestra/icons.slint";
|
|
6
|
+
// Icon { name: "play"; color: Theme.text; }
|
|
7
|
+
// Each icon is drawn in its own box (`Icons.box-width` × `Icons.box-height`),
|
|
8
|
+
// which is also the Icon's default size; an unknown name draws nothing.
|
|
9
|
+
import { Theme } from "theme.slint";
|
|
10
|
+
|
|
11
|
+
export global Icons {
|
|
12
|
+
// Path data in the icon's box.
|
|
13
|
+
public pure function commands(name: string) -> string {
|
|
14
|
+
if name == "play" { return "M 2.2 2.0 L 10.9 7 L 2.2 12.0 Z"; }
|
|
15
|
+
if name == "pause" { return "M 1.75 1.75 H 4.5 V 12.25 H 1.75 Z M 7.5 1.75 H 10.25 V 12.25 H 7.5 Z"; }
|
|
16
|
+
if name == "stop" { return "M 3.6 1.5 H 8.4 Q 10.5 1.5 10.5 3.6 V 8.4 Q 10.5 10.5 8.4 10.5 H 3.6 Q 1.5 10.5 1.5 8.4 V 3.6 Q 1.5 1.5 3.6 1.5 Z"; }
|
|
17
|
+
if name == "back" { return "M 6.5 1.25 L 2.5 5 L 6.5 8.75 M 12 1.25 L 8 5 L 12 8.75"; }
|
|
18
|
+
if name == "forward" { return "M 2 1.25 L 6 5 L 2 8.75 M 7.5 1.25 L 11.5 5 L 7.5 8.75"; }
|
|
19
|
+
if name == "open" { return "M 1.5 3.2 Q 1.5 1.5 3.2 1.5 H 5.2 L 6.8 3.2 H 10.8 Q 12.5 3.2 12.5 4.9 V 8.8 Q 12.5 10.5 10.8 10.5 H 3.2 Q 1.5 10.5 1.5 8.8 Z"; }
|
|
20
|
+
if name == "volume" { return "M 1 3.6 H 3 L 6 1.2 V 8.8 L 3 6.4 H 1 Z M 8.6 3.4 Q 9.7 5 8.6 6.6 M 10.6 1.6 Q 12.6 5 10.6 8.4"; }
|
|
21
|
+
if name == "mute" { return "M 1 3.6 H 3 L 6 1.2 V 8.8 L 3 6.4 H 1 Z M 8.8 3.4 L 12 6.6 M 12 3.4 L 8.8 6.6"; }
|
|
22
|
+
if name == "playlist" { return "M 1.25 1.5 H 11.75 M 1.25 5 H 11.75 M 1.25 8.5 H 6.5 M 9.2 7.2 L 10.5 8.5 L 11.8 7.2"; }
|
|
23
|
+
if name == "detach" { return "M 5.5 1.5 H 3.3 Q 1.5 1.5 1.5 3.3 V 8.7 Q 1.5 10.5 3.3 10.5 H 8.7 Q 10.5 10.5 10.5 8.7 V 6.5 M 8.5 1.5 H 12.5 V 5.5 M 12.5 1.5 L 6.5 7.5"; }
|
|
24
|
+
if name == "attach" { return "M 5.5 1.5 H 3.3 Q 1.5 1.5 1.5 3.3 V 8.7 Q 1.5 10.5 3.3 10.5 H 8.7 Q 10.5 10.5 10.5 8.7 V 6.5 M 12.5 1.5 L 7 7 M 7 3.5 V 7 H 10.5"; }
|
|
25
|
+
if name == "close" { return "M 3.5 3 L 10.5 10 M 10.5 3 L 3.5 10"; }
|
|
26
|
+
if name == "failed" { return "M 5 1.3 L 9.1 8.7 H 0.9 Z M 5 4.1 V 5.8 M 5 7.3 V 7.35"; }
|
|
27
|
+
if name == "move-top" { return "M 2.5 1.75 H 11.5 M 3 9.75 L 7 5.75 L 11 9.75"; }
|
|
28
|
+
if name == "move-up" { return "M 3 8 L 7 4 L 11 8"; }
|
|
29
|
+
if name == "move-down" { return "M 3 4 L 7 8 L 11 4"; }
|
|
30
|
+
if name == "move-bottom" { return "M 3 2.25 L 7 6.25 L 11 2.25 M 2.5 10.25 H 11.5"; }
|
|
31
|
+
if name == "search" { return "M 9 5.25 A 3.75 3.75 0 1 1 1.5 5.25 A 3.75 3.75 0 1 1 9 5.25 Z M 8 8 L 11.25 10.75"; }
|
|
32
|
+
if name == "chapter" { return "M 2.5 11 V 1.2 M 2.5 1.6 H 9.6 L 7.9 4.1 L 9.6 6.6 H 2.5"; }
|
|
33
|
+
if name == "bookmark" { return "M 3.2 1.2 H 8.8 V 10.6 L 6 8.3 L 3.2 10.6 Z"; }
|
|
34
|
+
if name == "check-task" { return "M 2.75 5.75 L 4.75 7.75 L 8.25 3.25"; }
|
|
35
|
+
if name == "check-box" { return "M 1.5 4.75 L 3.6 6.75 L 7.5 2.25"; }
|
|
36
|
+
if name == "menu-check" { return "M 4 7.25 L 6.25 9.5 L 10 4.75"; }
|
|
37
|
+
if name == "submenu" { return "M 1.25 1.25 L 3.75 4 L 1.25 6.75"; }
|
|
38
|
+
if name == "scroll-up" { return "M 1.25 3.75 L 4 1.25 L 6.75 3.75"; }
|
|
39
|
+
if name == "scroll-down" { return "M 1.25 1.25 L 4 3.75 L 6.75 1.25"; }
|
|
40
|
+
if name == "caret-down" { return "M 1.25 1.25 L 4 3.75 L 6.75 1.25"; }
|
|
41
|
+
if name == "sort-asc" { return "M 1 3.25 L 3.5 0.75 L 6 3.25"; }
|
|
42
|
+
if name == "sort-desc" { return "M 1 0.75 L 3.5 3.25 L 6 0.75"; }
|
|
43
|
+
if name == "tag-remove" { return "M 1.5 1.5 L 5.5 5.5 M 5.5 1.5 L 1.5 5.5"; }
|
|
44
|
+
if name == "preview-play" { return "M 1.5 1.3 L 6.9 4.5 L 1.5 7.7 Z"; }
|
|
45
|
+
if name == "add" { return "M 5 1.5 V 8.5 M 1.5 5 H 8.5"; }
|
|
46
|
+
if name == "remove" { return "M 1.5 5 H 8.5"; }
|
|
47
|
+
if name == "sort" { return "M 3 1.5 V 8.5 M 1.2 6.7 L 3 8.5 L 4.8 6.7 M 7 8.5 V 1.5 M 5.2 3.3 L 7 1.5 L 8.8 3.3"; }
|
|
48
|
+
return "";
|
|
49
|
+
}
|
|
50
|
+
// Line width.
|
|
51
|
+
public pure function line(name: string) -> length {
|
|
52
|
+
if name == "failed" || name == "chapter" || name == "bookmark" || name == "submenu" || name == "scroll-up" || name == "scroll-down" || name == "caret-down" || name == "tag-remove" || name == "preview-play" { return 1.25px; }
|
|
53
|
+
if name == "sort-asc" || name == "sort-desc" { return 1.1px; }
|
|
54
|
+
return 1.5px;
|
|
55
|
+
}
|
|
56
|
+
// The box the commands are drawn in.
|
|
57
|
+
public pure function box-width(name: string) -> length {
|
|
58
|
+
if name == "play" || name == "pause" || name == "stop" || name == "chapter" || name == "bookmark" { return 12px; }
|
|
59
|
+
if name == "failed" || name == "add" || name == "remove" || name == "sort" { return 10px; }
|
|
60
|
+
if name == "scroll-up" || name == "scroll-down" || name == "caret-down" || name == "preview-play" { return 8px; }
|
|
61
|
+
if name == "volume" || name == "mute" || name == "playlist" { return 13px; }
|
|
62
|
+
if name == "sort-asc" || name == "sort-desc" || name == "tag-remove" { return 7px; }
|
|
63
|
+
if name == "check-task" { return 11px; }
|
|
64
|
+
if name == "check-box" { return 9px; }
|
|
65
|
+
if name == "submenu" { return 5px; }
|
|
66
|
+
return 14px;
|
|
67
|
+
}
|
|
68
|
+
public pure function box-height(name: string) -> length {
|
|
69
|
+
if name == "back" || name == "forward" || name == "volume" || name == "mute" || name == "playlist" || name == "failed" || name == "add" || name == "remove" || name == "sort" { return 10px; }
|
|
70
|
+
if name == "play" || name == "pause" || name == "menu-check" { return 14px; }
|
|
71
|
+
if name == "scroll-up" || name == "scroll-down" || name == "caret-down" { return 5px; }
|
|
72
|
+
if name == "check-box" || name == "preview-play" { return 9px; }
|
|
73
|
+
if name == "sort-asc" || name == "sort-desc" { return 4px; }
|
|
74
|
+
if name == "close" { return 13px; }
|
|
75
|
+
if name == "check-task" { return 11px; }
|
|
76
|
+
if name == "submenu" { return 8px; }
|
|
77
|
+
if name == "tag-remove" { return 7px; }
|
|
78
|
+
return 12px;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// One icon, stroked in `color`; scaled when the caller sets another size.
|
|
83
|
+
export component Icon {
|
|
84
|
+
in property <string> name;
|
|
85
|
+
in property <brush> color: Theme.text;
|
|
86
|
+
width: Icons.box-width(root.name);
|
|
87
|
+
height: Icons.box-height(root.name);
|
|
88
|
+
Path {
|
|
89
|
+
width: 100%;
|
|
90
|
+
height: 100%;
|
|
91
|
+
viewbox-width: Icons.box-width(root.name) / 1px;
|
|
92
|
+
viewbox-height: Icons.box-height(root.name) / 1px;
|
|
93
|
+
commands: Icons.commands(root.name);
|
|
94
|
+
stroke: root.color;
|
|
95
|
+
stroke-width: Icons.line(root.name);
|
|
96
|
+
stroke-line-cap: round;
|
|
97
|
+
stroke-line-join: round;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// open (usually `plugin.system.openUrl`).
|
|
7
7
|
import { ScrollView } from "std-widgets.slint";
|
|
8
8
|
import { Theme } from "theme.slint";
|
|
9
|
+
import { Icon } from "icons.slint";
|
|
9
10
|
|
|
10
11
|
// One table row (cells are plain text).
|
|
11
12
|
export struct MarkdownRow {
|
|
@@ -86,18 +87,15 @@ component MarkdownBlockView {
|
|
|
86
87
|
y: 3px;
|
|
87
88
|
width: 11px;
|
|
88
89
|
height: 11px;
|
|
89
|
-
border-width: 1px;
|
|
90
|
-
border-radius:
|
|
90
|
+
border-width: block.task == 2 ? 0px : 1px;
|
|
91
|
+
border-radius: 3px;
|
|
91
92
|
border-color: Theme.text-dim;
|
|
92
93
|
background: block.task == 2 ? Theme.accent : transparent;
|
|
93
|
-
if block.task == 2:
|
|
94
|
+
if block.task == 2: Icon {
|
|
94
95
|
width: 100%;
|
|
95
96
|
height: 100%;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
commands: "M 2.5 5.5 L 4.5 7.5 L 8.5 3";
|
|
99
|
-
stroke: Theme.text;
|
|
100
|
-
stroke-width: 1.5px;
|
|
97
|
+
name: "check-task";
|
|
98
|
+
color: #ffffff;
|
|
101
99
|
}
|
|
102
100
|
}
|
|
103
101
|
}
|
package/slint/vestra/theme.slint
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Vestra theme tokens (doc/product/ui-spec.md §2.1–2.3). Import from any
|
|
2
2
|
// plugin or host Slint file: import { Theme } from "@vestra/theme.slint";
|
|
3
|
-
// Colours follow the player's palette (R-H6:
|
|
4
|
-
// view through ../palette.slint, which is not
|
|
3
|
+
// Colours follow the player's palette (R-H6: `vestra`, the dark default, or
|
|
4
|
+
// `vestra-light`, set on every view through ../palette.slint, which is not
|
|
5
|
+
// part of this library). They are
|
|
5
6
|
// `out` properties: Slint code reads them but cannot assign them. So is
|
|
6
7
|
// font-mono (set per system). Corner radii, font sizes and control sizes
|
|
7
8
|
// stay constants.
|
|
@@ -9,8 +10,10 @@
|
|
|
9
10
|
import { VestraPalette } from "../palette.slint";
|
|
10
11
|
|
|
11
12
|
export global Theme {
|
|
12
|
-
// Colours:
|
|
13
|
-
//
|
|
13
|
+
// Colours: the Aurora palette drawn from the logo's full spectrum (magenta
|
|
14
|
+
// accent, cyan for what is playing, amber → magenta → violet → cyan fills;
|
|
15
|
+
// violet-tinted near-black, or near-white in vestra-light, whose video area
|
|
16
|
+
// stays dark). Sizes below are the player's control geometry
|
|
14
17
|
// (doc/product/ui-spec.md §2.3), the same whatever the palette.
|
|
15
18
|
out property <color> bg-bar: VestraPalette.bg-bar;
|
|
16
19
|
out property <color> bg-video: VestraPalette.bg-video;
|
|
@@ -35,11 +38,12 @@ export global Theme {
|
|
|
35
38
|
out property <color> button-disabled: VestraPalette.button-disabled;
|
|
36
39
|
// Errors and destructive actions: a failed status line, a Delete button.
|
|
37
40
|
out property <color> danger: VestraPalette.danger;
|
|
38
|
-
// Brand gradient for "progress" fills (seek bar, volume, sliders).
|
|
41
|
+
// Brand gradient for "progress" fills (seek bar, volume, sliders, accents).
|
|
39
42
|
out property <brush> accent-fill: VestraPalette.accent-fill;
|
|
40
|
-
// Soft corners echo the logo
|
|
41
|
-
|
|
42
|
-
out property <length> radius-
|
|
43
|
+
// Soft corners echo the logo: controls, menu rows and hover plates use
|
|
44
|
+
// radius-control; menus, panels and the OSD radius-panel.
|
|
45
|
+
out property <length> radius-control: 4px;
|
|
46
|
+
out property <length> radius-panel: 8px;
|
|
43
47
|
// §2.2 fonts. No default family: every window uses the system UI font,
|
|
44
48
|
// and Slint falls back per character for scripts a font lacks (CJK in
|
|
45
49
|
// font-mono included). font-mono is the system's own monospace family,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Compact controls built on the Vestra theme (core-ui-design.md §2.1):
|
|
2
2
|
// import { Button, Slider, ToolTipArea, UrlInputRow } from "@vestra/widgets.slint";
|
|
3
|
-
// Other controls come from std-widgets, which the
|
|
3
|
+
// Icons: @vestra/icons.slint. Other controls come from std-widgets, which the
|
|
4
|
+
// host compiles as fluent-dark and switches to light for a light palette.
|
|
4
5
|
import { TextEdit } from "std-widgets.slint";
|
|
5
6
|
import { Theme } from "theme.slint";
|
|
6
7
|
|
|
@@ -49,6 +50,7 @@ export component ToolTipArea {
|
|
|
49
50
|
background: Theme.bg-panel;
|
|
50
51
|
border-color: Theme.line;
|
|
51
52
|
border-width: 1px;
|
|
53
|
+
border-radius: Theme.radius-control;
|
|
52
54
|
HorizontalLayout {
|
|
53
55
|
padding-left: 5px; padding-right: 5px; padding-top: 2px; padding-bottom: 2px;
|
|
54
56
|
Text { text: root.text; color: Theme.text; font-size: Theme.font-body; }
|
|
@@ -59,7 +61,8 @@ export component ToolTipArea {
|
|
|
59
61
|
|
|
60
62
|
// Dialog button: text (21px, or 18px when `small`), or an icon button when
|
|
61
63
|
// `text` is empty and `icon` holds Path data drawn in an icon-width × icon-height
|
|
62
|
-
// viewbox (filled, or 1.5px lines when `stroked
|
|
64
|
+
// viewbox (filled, or 1.5px round-capped lines when `stroked`, as the
|
|
65
|
+
// @vestra/icons.slint set). The caller sizes icon buttons.
|
|
63
66
|
export component Button {
|
|
64
67
|
in property <string> text;
|
|
65
68
|
in property <string> icon;
|
|
@@ -112,6 +115,8 @@ export component Button {
|
|
|
112
115
|
fill: root.stroked ? transparent : root.tint;
|
|
113
116
|
stroke: root.stroked ? root.tint : transparent;
|
|
114
117
|
stroke-width: root.stroked ? 1.5px : 0px;
|
|
118
|
+
stroke-line-cap: round;
|
|
119
|
+
stroke-line-join: round;
|
|
115
120
|
}
|
|
116
121
|
touch := TouchArea {
|
|
117
122
|
enabled: root.enabled;
|
|
@@ -119,8 +124,9 @@ export component Button {
|
|
|
119
124
|
}
|
|
120
125
|
}
|
|
121
126
|
|
|
122
|
-
// 2px line slider. Bar style (default): 8px round thumb,
|
|
123
|
-
// Panel style (`panel: true`): 14×12 thumb,
|
|
127
|
+
// 2px line slider. Bar style (default): 8px round thumb, a white core in a
|
|
128
|
+
// 2px accent ring, gradient fill. Panel style (`panel: true`): 14×12 thumb,
|
|
129
|
+
// gradient fill. The track is `Theme.line` in both.
|
|
124
130
|
export component Slider {
|
|
125
131
|
in-out property <float> value;
|
|
126
132
|
in property <float> minimum: 0;
|
|
@@ -146,7 +152,8 @@ export component Slider {
|
|
|
146
152
|
Rectangle {
|
|
147
153
|
y: (parent.height - 2px) / 2;
|
|
148
154
|
height: 2px;
|
|
149
|
-
|
|
155
|
+
border-radius: 1px;
|
|
156
|
+
background: Theme.line;
|
|
150
157
|
}
|
|
151
158
|
Rectangle {
|
|
152
159
|
y: (parent.height - 2px) / 2;
|
|
@@ -162,10 +169,9 @@ export component Slider {
|
|
|
162
169
|
width: root.thumb-width;
|
|
163
170
|
height: root.thumb-height;
|
|
164
171
|
border-radius: root.panel ? Theme.radius-control : self.height / 2;
|
|
165
|
-
background: !root.enabled ? Theme.icon-disabled
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
: touch.has-hover ? Theme.accent : Theme.text;
|
|
172
|
+
background: !root.enabled ? Theme.icon-disabled : root.panel ? Theme.text : #ffffff;
|
|
173
|
+
border-width: root.panel || !root.enabled ? 0px : 2px;
|
|
174
|
+
border-color: touch.pressed ? Theme.accent-press : Theme.accent;
|
|
169
175
|
}
|
|
170
176
|
touch := TouchArea {
|
|
171
177
|
enabled: root.enabled;
|