@514sid/signagekit 0.0.0-stage → 0.0.1

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.
Files changed (95) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/LICENSE +44 -0
  3. package/README.md +102 -2
  4. package/bin/signagekit.js +4 -0
  5. package/dist/chunks/chart-DT-Y4YWA.js +2 -0
  6. package/dist/chunks/empty--6iNLsra.js +2 -0
  7. package/dist/chunks/icon-paths-Dl0Rqja7.js +2 -0
  8. package/dist/chunks/lists-DYyvtVni.js +2 -0
  9. package/dist/chunks/measures-_ZIjSN7n.js +2 -0
  10. package/dist/chunks/media-DI-zWZSx.js +3 -0
  11. package/dist/chunks/qr-size-Dq23do6_.js +2 -0
  12. package/dist/chunks/ready-DI3QO8E5.js +2 -0
  13. package/dist/chunks/share-CtG_q4RM.js +2 -0
  14. package/dist/chunks/stat-DIAOyDND.js +2 -0
  15. package/dist/chunks/time-sq9LV8dr.js +2 -0
  16. package/dist/cli.js +10 -0
  17. package/dist/index.js +3 -0
  18. package/dist/style.css +2 -0
  19. package/dist/types/alert.d.ts +20 -0
  20. package/dist/types/binds.d.ts +6 -0
  21. package/dist/types/chart.d.ts +16 -0
  22. package/dist/types/check.d.ts +31 -0
  23. package/dist/types/checks.d.ts +30 -0
  24. package/dist/types/colors.d.ts +18 -0
  25. package/dist/types/components.d.ts +13 -0
  26. package/dist/types/cycle-fit.d.ts +6 -0
  27. package/dist/types/data.d.ts +19 -0
  28. package/dist/types/empty.d.ts +6 -0
  29. package/dist/types/fit.d.ts +3 -0
  30. package/dist/types/flow.d.ts +7 -0
  31. package/dist/types/icon-paths.d.ts +2 -0
  32. package/dist/types/icon.d.ts +7 -0
  33. package/dist/types/icons.d.ts +3 -0
  34. package/dist/types/index.d.ts +20 -0
  35. package/dist/types/lists.d.ts +28 -0
  36. package/dist/types/measure.d.ts +4 -0
  37. package/dist/types/measures.d.ts +22 -0
  38. package/dist/types/media.d.ts +15 -0
  39. package/dist/types/mount.d.ts +45 -0
  40. package/dist/types/parse.d.ts +11 -0
  41. package/dist/types/qr-size.d.ts +2 -0
  42. package/dist/types/ready.d.ts +3 -0
  43. package/dist/types/share.d.ts +33 -0
  44. package/dist/types/sizes.d.ts +15 -0
  45. package/dist/types/specs.d.ts +7 -0
  46. package/dist/types/stat.d.ts +38 -0
  47. package/dist/types/table-fit.d.ts +8 -0
  48. package/dist/types/table.d.ts +11 -0
  49. package/dist/types/time.d.ts +15 -0
  50. package/dist/types/trend-fit.d.ts +14 -0
  51. package/dist/types/type-scale.d.ts +10 -0
  52. package/dist/types/types.d.ts +271 -0
  53. package/dist/types/validate-layout.d.ts +2 -0
  54. package/dist/types/validate.d.ts +7 -0
  55. package/dist/types/version.d.ts +24 -0
  56. package/dist/types/views.d.ts +29 -0
  57. package/docs/api.md +106 -0
  58. package/docs/assistants.md +55 -0
  59. package/docs/format.md +183 -0
  60. package/docs/getting-started.md +77 -0
  61. package/docs/preview.md +84 -0
  62. package/examples/clinic-queue/data.json +17 -0
  63. package/examples/clinic-queue/layout.yml +43 -0
  64. package/examples/fire-alarm/data.yml +23 -0
  65. package/examples/fire-alarm/layout.yml +30 -0
  66. package/examples/gym-classes/data.yml +17 -0
  67. package/examples/gym-classes/layout.yml +47 -0
  68. package/examples/hotel-lobby/data.yml +2 -0
  69. package/examples/hotel-lobby/layout.yml +29 -0
  70. package/examples/lunch/data.yml +16 -0
  71. package/examples/lunch/layout.yml +43 -0
  72. package/examples/meeting-room/data.json +19 -0
  73. package/examples/meeting-room/layout.json +107 -0
  74. package/examples/noc-wall/data.yml +18 -0
  75. package/examples/noc-wall/layout.yml +63 -0
  76. package/examples/oee-line/data.yml +25 -0
  77. package/examples/oee-line/layout.yml +55 -0
  78. package/examples/office-air/data.yml +25 -0
  79. package/examples/office-air/layout.yml +71 -0
  80. package/examples/sales-today/data.json +28 -0
  81. package/examples/sales-today/layout.json +62 -0
  82. package/examples/snow-closure/data.yml +28 -0
  83. package/examples/snow-closure/layout.json +35 -0
  84. package/examples/station-departures/data.json +24 -0
  85. package/examples/station-departures/layout.json +34 -0
  86. package/examples/store-promo/data.yml +18 -0
  87. package/examples/store-promo/layout.yml +54 -0
  88. package/examples/storm-banner/data.json +20 -0
  89. package/examples/storm-banner/layout.json +33 -0
  90. package/examples/trading-floor/data.json +23 -0
  91. package/examples/trading-floor/layout.json +65 -0
  92. package/examples/warehouse/data.json +20 -0
  93. package/examples/warehouse/layout.json +50 -0
  94. package/package.json +100 -4
  95. package/schema.json +962 -0
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Sizes a cycle to its longest message, so the size never jumps between
3
+ * messages. One line suits a banner; a tall, narrow zone wraps instead,
4
+ * whichever lets the text be larger.
5
+ */
6
+ export declare function fitMessages(el: HTMLElement, messages: string[]): void;
@@ -0,0 +1,19 @@
1
+ import type { Data, Value } from './types';
2
+ /** Reads "/menu/0/price" from the data. Missing paths give undefined. */
3
+ export declare function getPath(data: unknown, path: string): unknown;
4
+ export declare function isBind(v: unknown): v is {
5
+ bind: string;
6
+ fallback?: string | number;
7
+ };
8
+ /**
9
+ * Resolves a value to display text. A bind that is missing or empty in the
10
+ * data shows its `fallback`; without one it resolves to "" and the component
11
+ * shows its own empty state.
12
+ */
13
+ export declare function text(v: Value | undefined, data: Data): string;
14
+ /** Resolves a value that should be a list, literal or bound. */
15
+ export declare function items<T>(v: T[] | {
16
+ bind: string;
17
+ }, data: Data): unknown[];
18
+ /** Deep merge: objects merge key by key, arrays and values are replaced. */
19
+ export declare function merge(base: unknown, over: unknown): unknown;
@@ -0,0 +1,6 @@
1
+ /** Stands in for a missing single value: a stat, a meter, a table cell. */
2
+ export declare const DASH = "\u2014";
3
+ /** Shown instead of an empty list, table, chart or image. */
4
+ export declare function Empty({ text }: {
5
+ text?: string;
6
+ }): import("preact").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import { fitMessages } from './cycle-fit';
2
+ export { fitMessages };
3
+ export declare function fitAll(root: ParentNode): void;
@@ -0,0 +1,7 @@
1
+ import type { FlowLayout, GridLayout, Layout } from './types';
2
+ export declare const COLUMNS = 12;
3
+ /** Reference canvas: 1080 px on the short side, the long side follows the screen. */
4
+ export declare function canvasSize(viewW: number, viewH: number): [number, number];
5
+ export declare const isFlow: (l: Layout) => l is FlowLayout;
6
+ export declare function flowGrid(l: FlowLayout, width: number): GridLayout;
7
+ export declare function toGrid(l: Layout, width: number): GridLayout;
@@ -0,0 +1,2 @@
1
+ import type { IconName } from './icons';
2
+ export declare const ICONS: Record<IconName, string>;
@@ -0,0 +1,7 @@
1
+ import type { IconName } from './icons';
2
+ export declare function loadIcons(): Promise<Record<string, string>>;
3
+ /** A named icon from the set in icons.ts, drawn in the current text color. */
4
+ export declare function Icon({ name, cls }: {
5
+ name: IconName;
6
+ cls?: string;
7
+ }): import("preact").JSX.Element;
@@ -0,0 +1,3 @@
1
+ export declare const ICON_NAMES: readonly ["info", "check", "warning", "danger", "fire", "evacuate", "assembly", "medical", "first-aid", "storm", "wind", "snow", "flood", "heat", "lockdown", "shelter", "security", "power", "water", "network", "closed", "delay", "maintenance", "announcement", "phone", "biohazard", "radiation", "chemical", "event", "location", "accessibility"];
2
+ export type IconName = (typeof ICON_NAMES)[number];
3
+ export declare const isIcon: (v: unknown) => v is IconName;
@@ -0,0 +1,20 @@
1
+ import './style.css';
2
+ export { mount } from './mount';
3
+ export type { MountOptions, ScreenHandle, Update } from './mount';
4
+ export { check } from './check';
5
+ export type { CheckOptions, CheckResult, Source } from './check';
6
+ export { validate } from './validate';
7
+ export type { Result as ValidateResult } from './validate';
8
+ export { canvasSize } from './flow';
9
+ export { COLOR_KEYS, SCHEMES } from './colors';
10
+ export type { ColorKey, Colors, Palette, Scheme } from './colors';
11
+ export { ICON_NAMES } from './icons';
12
+ export type { IconName } from './icons';
13
+ export { LEVELS } from './alert';
14
+ export type { Level } from './alert';
15
+ export type * from './types';
16
+ export { pack, previewUrl, unpack, PREVIEW_BASE } from './share';
17
+ export type { PreviewOptions, Shared } from './share';
18
+ export { FORMAT } from './version';
19
+ export { DEFAULT_SIZES, parseSize, SIZES } from './sizes';
20
+ export type { Size } from './sizes';
@@ -0,0 +1,28 @@
1
+ import type { Clocks, Data, Queue, Schedule, Status } from './types';
2
+ export declare function StatusView({ c, data }: {
3
+ c: Status;
4
+ data: Data;
5
+ }): import("preact").JSX.Element;
6
+ export interface Entry {
7
+ start: string;
8
+ title: string;
9
+ detail: string;
10
+ tag: 'now' | 'next' | '';
11
+ }
12
+ /**
13
+ * Entries from the current one onward. An entry ends at its `end`, else when
14
+ * the next one starts, else an hour after it starts.
15
+ */
16
+ export declare function upcoming(raw: unknown[], data: Data, now: Date, limit: number): Entry[];
17
+ export declare function ScheduleView({ c, data }: {
18
+ c: Schedule;
19
+ data: Data;
20
+ }): import("preact").JSX.Element;
21
+ export declare function QueueView({ c, data }: {
22
+ c: Queue;
23
+ data: Data;
24
+ }): import("preact").JSX.Element;
25
+ export declare function ClocksView({ c, data }: {
26
+ c: Clocks;
27
+ data: Data;
28
+ }): import("preact").JSX.Element;
@@ -0,0 +1,4 @@
1
+ /** Font size, in px, that components are measured at before scaling. */
2
+ export declare const PROBE = 100;
3
+ /** The box a component fills: its parent, without padding. */
4
+ export declare function contentBox(box: HTMLElement): [number, number];
@@ -0,0 +1,22 @@
1
+ import type { Bars, Data, Meter, Meters, Split } from './types';
2
+ export declare function MeterView({ c, data }: {
3
+ c: Meter;
4
+ data: Data;
5
+ }): import("preact").JSX.Element;
6
+ export declare function MetersView({ c, data }: {
7
+ c: Meters;
8
+ data: Data;
9
+ }): import("preact").JSX.Element;
10
+ /** Ranked bars, largest first, all against the largest value. */
11
+ export declare function BarsView({ c, data }: {
12
+ c: Bars;
13
+ data: Data;
14
+ }): import("preact").JSX.Element;
15
+ /**
16
+ * One whole split into parts. Each block prints its share when it is wide
17
+ * enough; the legend repeats name and share, so no value is lost.
18
+ */
19
+ export declare function SplitView({ c, data }: {
20
+ c: Split;
21
+ data: Data;
22
+ }): import("preact").JSX.Element;
@@ -0,0 +1,15 @@
1
+ import type { Data, Qr, Slideshow } from './types';
2
+ /** Swaps images instantly on a timer and preloads the next one. */
3
+ export declare function SlideshowView({ c, data }: {
4
+ c: Slideshow;
5
+ data: Data;
6
+ }): import("preact").JSX.Element;
7
+ /**
8
+ * One SVG path for all dark modules, with a four-module quiet zone. Always
9
+ * black on white: many phone scanners fail on inverted codes.
10
+ */
11
+ export declare function qrPath(grid: boolean[][]): string;
12
+ export declare function QrView({ c, data }: {
13
+ c: Qr;
14
+ data: Data;
15
+ }): import("preact").JSX.Element;
@@ -0,0 +1,45 @@
1
+ import { type Source } from './check';
2
+ import { type Colors, type Scheme } from './colors';
3
+ export interface MountOptions {
4
+ /** The screen document: JSON or YAML text, or a parsed object. */
5
+ layout: Source;
6
+ /** Values that binds read: JSON or YAML text, or an object. */
7
+ data?: Source;
8
+ /** Scheme used when the document doesn't set one. Default dark. */
9
+ scheme?: Scheme;
10
+ /** Accent used when the document doesn't set one. Default #2563eb. */
11
+ accent?: string;
12
+ /**
13
+ * Colors that win over the document's own, like `{ scheme: 'light' }` to
14
+ * see a screen in the other scheme.
15
+ */
16
+ colors?: Colors;
17
+ /** IANA time zone for clocks and schedules. Default the device's. */
18
+ timeZone?: string;
19
+ /** BCP 47 locale for dates and times. Default the device's. */
20
+ locale?: string;
21
+ /** Show errors and warnings over the screen. Default false. */
22
+ showProblems?: boolean;
23
+ /** Freezes the clock at this time, for screenshots and tests. */
24
+ now?: Date;
25
+ }
26
+ export interface Update {
27
+ layout?: Source;
28
+ data?: Source;
29
+ }
30
+ export interface ScreenHandle {
31
+ /** Errors from the last check, plus any reported with report(). */
32
+ readonly errors: string[];
33
+ readonly warnings: string[];
34
+ /** Replaces the layout, the data or both, and renders again. */
35
+ update(changes: Update): Promise<void>;
36
+ /** Adds an error, shown over the screen when showProblems is on. */
37
+ report(message: string): void;
38
+ /** Stops watching the element's size and removes the screen. */
39
+ destroy(): void;
40
+ }
41
+ /**
42
+ * Renders a screen document into `container` and resolves once it is drawn,
43
+ * charts included. The container sets the size; the screen fills it.
44
+ */
45
+ export declare function mount(container: HTMLElement, options: MountOptions): Promise<ScreenHandle>;
@@ -0,0 +1,11 @@
1
+ export interface Parsed {
2
+ value: unknown;
3
+ error?: string;
4
+ }
5
+ /**
6
+ * `layout` uses the YAML core schema, so `fit: true` and `gap: 24` keep their
7
+ * types. `data` uses the failsafe schema, which reads every scalar as a
8
+ * string: a price written as 4.50 stays "4.50" instead of becoming 4.5.
9
+ */
10
+ export type Mode = 'layout' | 'data';
11
+ export declare function parseText(src: string, mode: Mode): Promise<Parsed>;
@@ -0,0 +1,2 @@
1
+ /** QR codes: the largest square that fits beside their caption. */
2
+ export declare function sizeQr(root: ParentNode): void;
@@ -0,0 +1,3 @@
1
+ export declare function track(p: Promise<unknown>): void;
2
+ /** Resolves when tracked work is done, or after `timeout` ms at the latest. */
3
+ export declare function settled(timeout?: number): Promise<void>;
@@ -0,0 +1,33 @@
1
+ export declare const PREVIEW_BASE = "https://signagekit.514sid.com/preview/";
2
+ export interface PreviewOptions {
3
+ /** `screen` (default), `sizes`, `schemes` or `edit`. */
4
+ mode?: 'screen' | 'sizes' | 'schemes' | 'edit';
5
+ /**
6
+ * Resolution: a name like `fullhd` or `portrait`, or `WIDTHxHEIGHT`. One
7
+ * for `screen` and `schemes`, a list for `sizes`.
8
+ */
9
+ size?: string | string[];
10
+ scheme?: 'dark' | 'light';
11
+ accent?: string;
12
+ timeZone?: string;
13
+ locale?: string;
14
+ /** Show errors and warnings over the screen. */
15
+ problems?: boolean;
16
+ /** Freeze the clock at this ISO time, like 2026-11-14T09:30. */
17
+ now?: string;
18
+ /** Preview page to link to. Default the public site. */
19
+ base?: string;
20
+ }
21
+ export interface Shared {
22
+ layout: string;
23
+ data?: string;
24
+ }
25
+ /** Packs layout and data text into the `s` value of a preview link. */
26
+ export declare function pack(shared: Shared): Promise<string>;
27
+ /** Reverses pack(). Throws on a damaged value. */
28
+ export declare function unpack(s: string): Promise<Shared>;
29
+ /**
30
+ * A link to the preview page showing this layout and data. Pass the text as
31
+ * written, JSON or YAML, or objects, which are sent as JSON.
32
+ */
33
+ export declare function previewUrl(layout: string | object, data?: string | object, options?: PreviewOptions): Promise<string>;
@@ -0,0 +1,15 @@
1
+ export interface Size {
2
+ name: string;
3
+ width: number;
4
+ height: number;
5
+ label: string;
6
+ }
7
+ /** Every named resolution, keyed by name. */
8
+ export declare const SIZES: Record<string, Size>;
9
+ /** The sizes the preview compares when none are given. */
10
+ export declare const DEFAULT_SIZES: string[];
11
+ /**
12
+ * Reads `fullhd`, `1080p` or `1366x768` (also `1366×768`). Returns null for
13
+ * anything else, or for sizes under 64 or over 16384 px.
14
+ */
15
+ export declare function parseSize(text: string): Size | null;
@@ -0,0 +1,7 @@
1
+ import { type Check } from './checks';
2
+ import type { ComponentType } from './types';
3
+ export interface Spec {
4
+ required: Record<string, Check>;
5
+ optional: Record<string, Check>;
6
+ }
7
+ export declare const SPECS: Record<ComponentType, Spec>;
@@ -0,0 +1,38 @@
1
+ import type { Component, Data, Stat as StatSpec, Thresholds, Value } from './types';
2
+ type Props = {
3
+ c: StatSpec;
4
+ data: Data;
5
+ };
6
+ export declare const STATE_WORDS: Record<string, string>;
7
+ /** good, warning or danger; anything else, unknown included, is neutral. */
8
+ export declare function stateText(v: Value | undefined, data: Data): string;
9
+ /**
10
+ * A state from thresholds: past danger is danger, past warning is warning,
11
+ * anything else neutral. With danger below warning, lower values are worse.
12
+ */
13
+ export declare function thresholdState(n: number, t: Thresholds | undefined): string;
14
+ /**
15
+ * The state that marks a whole zone. Only stats and meters set one: an
16
+ * explicit `state` wins, else `thresholds` decide from the value.
17
+ */
18
+ export declare function stateOf(c: Component, data: Data): string;
19
+ export declare function StateIcon({ state }: {
20
+ state: string;
21
+ }): import("preact").JSX.Element;
22
+ /**
23
+ * up, down or flat, or none. With good_when set, a move that way is good
24
+ * (green) and the opposite is bad (red); without it the arrow stays neutral,
25
+ * since a rising number is not always good news.
26
+ */
27
+ export declare function trendOf(c: StatSpec, data: Data): {
28
+ dir: string;
29
+ tone: string;
30
+ } | null;
31
+ /**
32
+ * Numbers of 10,000 and up are shortened (1M, 12.9K) unless format is full,
33
+ * so a big value doesn't shrink every stat in its row. Smaller numbers get
34
+ * thousands separators; text that isn't a number is shown as written.
35
+ */
36
+ export declare function formatValue(raw: string, format?: 'compact' | 'full'): string;
37
+ export declare function Stat({ c, data }: Props): import("preact").JSX.Element;
38
+ export {};
@@ -0,0 +1,8 @@
1
+ export declare function tableOverflow(el: HTMLElement): void;
2
+ /**
3
+ * Shows every row a table could show at once, all of them or the first
4
+ * page_rows, and hides its pager, so fitting and paging measure the same
5
+ * content on every pass. Returns a function that hands rows back to the
6
+ * table's own paging.
7
+ */
8
+ export declare function showAllRows(root: ParentNode): () => void;
@@ -0,0 +1,11 @@
1
+ import type { Data, Table as TableSpec } from './types';
2
+ /**
3
+ * A table that sizes its text to fit. Rows that don't fit at a readable size
4
+ * are shown a page at a time, flipping instantly; page_rows caps the page
5
+ * size by hand. Rows off the page are collapsed, not removed, so column widths
6
+ * stay the same on every page and nothing jumps.
7
+ */
8
+ export declare function Table({ c, data }: {
9
+ c: TableSpec;
10
+ data: Data;
11
+ }): import("preact").JSX.Element;
@@ -0,0 +1,15 @@
1
+ type Listener = (now: Date) => void;
2
+ export declare function setFixedTime(d: Date | undefined): void;
3
+ export declare const currentTime: () => Date;
4
+ export declare function onMinute(fn: Listener): () => void;
5
+ export declare function useMinute(): Date;
6
+ export declare function setTimeContext(tz: string | undefined, loc: string | undefined): void;
7
+ /** The time in another zone, for world clocks. */
8
+ export declare function formatClockIn(now: Date, zone: string, hour12: boolean | undefined): string;
9
+ /** Minutes since midnight on the screen's clock, for "HH:MM" schedules. */
10
+ export declare function minutesOfDay(now: Date): number;
11
+ export declare function formatClock(now: Date, hour12: boolean | undefined): string;
12
+ export declare function formatDate(now: Date): string;
13
+ /** "3 d 4 h", "4 h 12 min", "12 min", or "" once the time has passed. */
14
+ export declare function formatCountdown(to: Date, now: Date): string;
15
+ export {};
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Fits a stat in each arrangement it can take, using `fitLine`, which returns
3
+ * the size the element fits at as it stands, or less than `floor` by how far
4
+ * it is from fitting at all. Leaves the best one in place
5
+ * and remembers every size for the row pass. Returns false when there is
6
+ * nothing to choose, so the caller fits the stat normally.
7
+ */
8
+ export declare function fitTrend(el: HTMLElement, fitLine: () => number, floor: number): boolean;
9
+ /**
10
+ * Picks one arrangement for a row of figures: the one whose smallest size is
11
+ * largest. A stat that can't take an arrangement keeps its own nearest one.
12
+ * Returns the size the row shares.
13
+ */
14
+ export declare function alignTrends(group: HTMLElement[], sizeOf: (el: HTMLElement) => number, floor?: number): number;
@@ -0,0 +1,10 @@
1
+ export declare const RANGES: Record<string, [number, number]>;
2
+ /** The type scale every fitted size snaps down to. */
3
+ export declare const STEPS: number[];
4
+ /** Components made of rows; they share one body size across the screen. */
5
+ export declare const BODY: string[];
6
+ /** Display text kept within this many times the body size. */
7
+ export declare const DISPLAY: string[];
8
+ export declare const DISPLAY_RATIO = 3.5;
9
+ /** List-like components may grow this much past the shared body size. */
10
+ export declare const BODY_SPREAD = 1.4;
@@ -0,0 +1,271 @@
1
+ import type { Colors } from './colors';
2
+ /** A literal, or a pointer into the data, like { "bind": "/menu/0/price" }. */
3
+ export type Bind = {
4
+ bind: string;
5
+ /** Shown when the path is missing or empty in the data. */
6
+ fallback?: string | number;
7
+ };
8
+ export type Value = string | number | Bind;
9
+ export type Surface = 'base' | 'raised' | 'accent';
10
+ export type Align = 'start' | 'center' | 'end';
11
+ export type TextSize = 's' | 'm' | 'l' | 'xl';
12
+ interface Base {
13
+ surface?: Surface;
14
+ /** Short label shown above the component, like "Menu" or "Wait time". */
15
+ title?: Value;
16
+ /** Pins the text size in px on the reference canvas, skipping fitting. */
17
+ size?: number | TextSize;
18
+ /** Share of a stack's space, relative to its siblings. Default 1. */
19
+ weight?: number;
20
+ /** A named icon shown before the title, in place of the square marker. */
21
+ icon?: string;
22
+ }
23
+ export interface Heading extends Base {
24
+ type: 'heading';
25
+ text: Value;
26
+ align?: Align;
27
+ }
28
+ export interface Text extends Base {
29
+ type: 'text';
30
+ text: Value;
31
+ size?: TextSize;
32
+ align?: Align;
33
+ fit?: boolean;
34
+ }
35
+ export type State = 'neutral' | 'good' | 'warning' | 'danger';
36
+ /**
37
+ * Sets the state from the value, so data only has to carry numbers. With
38
+ * danger above warning, higher is worse; with danger below, lower is worse.
39
+ */
40
+ export interface Thresholds {
41
+ warning?: number;
42
+ danger?: number;
43
+ }
44
+ export interface Stat extends Base {
45
+ type: 'stat';
46
+ value: Value;
47
+ label?: Value;
48
+ unit?: Value;
49
+ /** Bound or literal; anything but good, warning or danger is neutral. */
50
+ state?: Value;
51
+ /** up, down or flat; bound or literal. Anything else shows no arrow. */
52
+ trend?: Value;
53
+ /** Change shown next to the arrow, like "+4.2%". */
54
+ delta?: Value;
55
+ /** Which direction is good news; colors the arrow green or red. */
56
+ good_when?: 'up' | 'down';
57
+ /** compact (default) shortens numbers from 10,000 up; full never does. */
58
+ format?: 'compact' | 'full';
59
+ /** false keeps this stat's own size instead of matching its row. */
60
+ match_row?: boolean;
61
+ /** Recent values drawn as a sparkline under the number. */
62
+ spark?: Value[] | Bind;
63
+ thresholds?: Thresholds;
64
+ }
65
+ export interface Table extends Base {
66
+ type: 'table';
67
+ columns: string[];
68
+ rows: Value[][] | Bind;
69
+ align?: Align[];
70
+ /** Rows per page; pages flip instantly every `seconds`. */
71
+ page_rows?: number;
72
+ /** Relative column widths, like [3, 1, 1]. Long cells end in an ellipsis. */
73
+ widths?: number[];
74
+ seconds?: number;
75
+ }
76
+ export interface List extends Base {
77
+ type: 'list';
78
+ items: Value[] | Bind;
79
+ }
80
+ export interface Image extends Base {
81
+ type: 'image';
82
+ src: Value;
83
+ fit?: 'cover' | 'contain';
84
+ alt?: string;
85
+ }
86
+ export interface Clock extends Base {
87
+ type: 'clock';
88
+ hour12?: boolean;
89
+ show_date?: boolean;
90
+ }
91
+ export interface Countdown extends Base {
92
+ type: 'countdown';
93
+ to: Value;
94
+ label?: Value;
95
+ /** Shown once the time has passed. Default "Now". */
96
+ done?: Value;
97
+ }
98
+ export interface ChartSeries {
99
+ name: Value;
100
+ values: Value[] | Bind;
101
+ }
102
+ /** Line, area or column chart, drawn by uPlot. */
103
+ export interface Chart extends Base {
104
+ type: 'chart';
105
+ kind: 'line' | 'area' | 'column';
106
+ labels: Value[] | Bind;
107
+ series: ChartSeries[];
108
+ /** A horizontal target line, like an SLO or a production goal. */
109
+ target?: Value;
110
+ target_label?: Value;
111
+ /** Fixed y-axis range; either end can be left out. */
112
+ y_min?: number;
113
+ y_max?: number;
114
+ }
115
+ /** Shows one message at a time and swaps to the next instantly. */
116
+ export interface Cycle extends Base {
117
+ type: 'cycle';
118
+ items: Value[] | Bind;
119
+ seconds?: number;
120
+ align?: Align;
121
+ }
122
+ export interface Stack extends Base {
123
+ type: 'stack';
124
+ direction?: 'row' | 'column';
125
+ items: Component[];
126
+ }
127
+ export type Component = Heading | Text | Stat | Table | List | Image | Clock | Countdown | Cycle | Chart | Stack | Meter | Meters | Bars | Split | Status | Schedule | Queue | Clocks | Slideshow | Qr;
128
+ /** A labelled amount, used by meters, bars and split. */
129
+ export interface Part {
130
+ label: Value;
131
+ value: Value;
132
+ max?: Value;
133
+ state?: Value;
134
+ }
135
+ export type Parts = Part[] | Bind;
136
+ /** One value against a limit. */
137
+ export interface Meter extends Base {
138
+ type: 'meter';
139
+ value: Value;
140
+ max?: Value;
141
+ label?: Value;
142
+ unit?: Value;
143
+ state?: Value;
144
+ thresholds?: Thresholds;
145
+ }
146
+ /** Several meters, one row each, bars aligned. */
147
+ export interface Meters extends Base {
148
+ type: 'meters';
149
+ items: Parts;
150
+ max?: Value;
151
+ unit?: Value;
152
+ /** Applied to each row without its own state. */
153
+ thresholds?: Thresholds;
154
+ }
155
+ /** Ranked horizontal bars, largest first. */
156
+ export interface Bars extends Base {
157
+ type: 'bars';
158
+ items: Parts;
159
+ unit?: Value;
160
+ limit?: number;
161
+ }
162
+ /** One whole split into up to six parts. */
163
+ export interface Split extends Base {
164
+ type: 'split';
165
+ items: Parts;
166
+ }
167
+ /** Rows with a state icon each, like service health. */
168
+ export interface Status extends Base {
169
+ type: 'status';
170
+ items: {
171
+ label: Value;
172
+ state: Value;
173
+ note?: Value;
174
+ }[] | Bind;
175
+ }
176
+ /** Time-ordered entries; the current and next ones are marked. */
177
+ export interface Schedule extends Base {
178
+ type: 'schedule';
179
+ items: {
180
+ start: Value;
181
+ end?: Value;
182
+ title: Value;
183
+ detail?: Value;
184
+ }[] | Bind;
185
+ rows?: number;
186
+ }
187
+ /** "Now serving" number with the recently called ones. */
188
+ export interface Queue extends Base {
189
+ type: 'queue';
190
+ current: Value;
191
+ recent?: Value[] | Bind;
192
+ label?: Value;
193
+ }
194
+ /** Several clocks, one per time zone. */
195
+ export interface Clocks extends Base {
196
+ type: 'clocks';
197
+ /** `zone` is the older name for `timezone` and still works. */
198
+ zones: {
199
+ label: Value;
200
+ timezone?: string;
201
+ zone?: string;
202
+ }[];
203
+ hour12?: boolean;
204
+ }
205
+ /** Images that swap instantly on a timer. */
206
+ export interface Slideshow extends Base {
207
+ type: 'slideshow';
208
+ images: Value[] | Bind;
209
+ seconds?: number;
210
+ fit?: 'cover' | 'contain';
211
+ }
212
+ /** QR code, black on white for scanners, with an optional caption. */
213
+ export interface Qr extends Base {
214
+ type: 'qr';
215
+ value: Value;
216
+ label?: Value;
217
+ }
218
+ export type ComponentType = Component['type'];
219
+ /** A fixed grid: named areas, like CSS grid-template-areas. */
220
+ export interface GridLayout {
221
+ areas: string[];
222
+ columns?: string;
223
+ rows?: string;
224
+ gap?: number;
225
+ }
226
+ /** One zone in a flow layout. */
227
+ export interface FlowItem {
228
+ zone: string;
229
+ /** Columns out of 12 in the design orientation. Default 12. */
230
+ span?: number;
231
+ /** A number is a share of the free height (like fr); "150px" is fixed. */
232
+ height?: number | string;
233
+ }
234
+ /** Zones in reading order, packed into rows to suit the screen's shape. */
235
+ export interface FlowLayout {
236
+ flow: (string | FlowItem)[];
237
+ design?: 'landscape' | 'portrait';
238
+ gap?: number;
239
+ }
240
+ export type Layout = GridLayout | FlowLayout;
241
+ /**
242
+ * A screen-wide message: full screen (takeover) or a strip across the top
243
+ * (banner). It shows while its title or message is set and until `until`.
244
+ * The whole alert can also be a bind to an object in the data.
245
+ */
246
+ export interface AlertFields {
247
+ level?: 'info' | 'good' | 'warning' | 'danger' | Bind;
248
+ icon?: string | Bind;
249
+ title?: Value;
250
+ message?: Value;
251
+ /** Older name for `message`. */
252
+ text?: Value;
253
+ steps?: Value[] | Bind;
254
+ footer?: Value;
255
+ mode?: 'takeover' | 'banner';
256
+ /** ISO date and time after which the alert no longer shows. */
257
+ until?: Value;
258
+ /** Older name for `level`. */
259
+ state?: 'warning' | 'danger';
260
+ }
261
+ export type Alert = AlertFields | Bind;
262
+ export interface ScreenDoc {
263
+ /** Format version, default 1. See src/version.ts. */
264
+ version?: number;
265
+ colors?: Colors;
266
+ alert?: Alert;
267
+ layout: Layout;
268
+ zones: Record<string, Component>;
269
+ }
270
+ export type Data = Record<string, unknown>;
271
+ export {};