@orochibraru/ui 1.0.0 → 1.0.1-canary.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 (112) hide show
  1. package/README.md +84 -3
  2. package/dist/components/blocks/accent-toggle.svelte +7 -3
  3. package/dist/components/blocks/accent-toggle.svelte.d.ts +1 -1
  4. package/dist/components/blocks/bottom-nav.svelte +1 -1
  5. package/dist/components/blocks/command-palette.svelte +268 -0
  6. package/dist/components/blocks/command-palette.svelte.d.ts +37 -0
  7. package/dist/components/blocks/error-page.svelte +23 -7
  8. package/dist/components/blocks/error-page.svelte.d.ts +4 -0
  9. package/dist/components/blocks/fab.svelte +1 -1
  10. package/dist/components/blocks/install-prompt.svelte +14 -8
  11. package/dist/components/blocks/install-prompt.svelte.d.ts +2 -1
  12. package/dist/components/blocks/music-player/labelled-slider.svelte +3 -12
  13. package/dist/components/blocks/music-player/labelled-slider.svelte.d.ts +1 -2
  14. package/dist/components/blocks/music-player.svelte +13 -12
  15. package/dist/components/blocks/otp-field.svelte +77 -33
  16. package/dist/components/blocks/otp-field.svelte.d.ts +7 -0
  17. package/dist/components/blocks/password-input.svelte +56 -16
  18. package/dist/components/blocks/password-input.svelte.d.ts +3 -0
  19. package/dist/components/blocks/stepper/stepper-phone-header.svelte +93 -0
  20. package/dist/components/blocks/stepper/stepper-phone-header.svelte.d.ts +13 -0
  21. package/dist/components/blocks/stepper.svelte +175 -0
  22. package/dist/components/blocks/stepper.svelte.d.ts +30 -0
  23. package/dist/components/blocks/time-range-picker.svelte +229 -0
  24. package/dist/components/blocks/time-range-picker.svelte.d.ts +33 -0
  25. package/dist/components/blocks/time-series-chart/data-table.svelte +43 -0
  26. package/dist/components/blocks/time-series-chart/data-table.svelte.d.ts +15 -0
  27. package/dist/components/blocks/time-series-chart/legend.svelte +23 -0
  28. package/dist/components/blocks/time-series-chart/legend.svelte.d.ts +10 -0
  29. package/dist/components/blocks/time-series-chart/marks.svelte +118 -0
  30. package/dist/components/blocks/time-series-chart/marks.svelte.d.ts +29 -0
  31. package/dist/components/blocks/time-series-chart/messages.d.ts +13 -0
  32. package/dist/components/blocks/time-series-chart/messages.js +12 -0
  33. package/dist/components/blocks/time-series-chart/readout.svelte +44 -0
  34. package/dist/components/blocks/time-series-chart/readout.svelte.d.ts +15 -0
  35. package/dist/components/blocks/time-series-chart/scale.d.ts +24 -0
  36. package/dist/components/blocks/time-series-chart/scale.js +136 -0
  37. package/dist/components/blocks/time-series-chart/time.d.ts +7 -0
  38. package/dist/components/blocks/time-series-chart/time.js +96 -0
  39. package/dist/components/blocks/time-series-chart.svelte +492 -0
  40. package/dist/components/blocks/time-series-chart.svelte.d.ts +18 -0
  41. package/dist/components/blocks/top-loading-bar.svelte +1 -1
  42. package/dist/components/blocks/video-player/center-controls.svelte +7 -7
  43. package/dist/components/blocks/video-player/control-bar.svelte +41 -35
  44. package/dist/components/blocks/video-player/control-button.svelte +1 -1
  45. package/dist/components/blocks/video-player/option-menu.svelte +1 -1
  46. package/dist/components/blocks/video-player/scrub-bar.svelte +39 -12
  47. package/dist/components/blocks/video-player/scrub-bar.svelte.d.ts +2 -0
  48. package/dist/components/blocks/video-player.svelte +2 -2
  49. package/dist/components/kit/accordion.svelte +70 -0
  50. package/dist/components/kit/accordion.svelte.d.ts +37 -0
  51. package/dist/components/kit/avatar-group.svelte +84 -0
  52. package/dist/components/kit/avatar-group.svelte.d.ts +14 -0
  53. package/dist/components/kit/bar-list.svelte +104 -0
  54. package/dist/components/kit/bar-list.svelte.d.ts +22 -0
  55. package/dist/components/kit/breadcrumbs.svelte +102 -0
  56. package/dist/components/kit/breadcrumbs.svelte.d.ts +14 -0
  57. package/dist/components/kit/checkbox-list.svelte +98 -0
  58. package/dist/components/kit/checkbox-list.svelte.d.ts +15 -0
  59. package/dist/components/kit/checkbox.svelte +84 -0
  60. package/dist/components/kit/checkbox.svelte.d.ts +8 -0
  61. package/dist/components/kit/confirm-dialog.svelte +127 -0
  62. package/dist/components/kit/confirm-dialog.svelte.d.ts +19 -0
  63. package/dist/components/kit/data-table.svelte +280 -0
  64. package/dist/components/kit/data-table.svelte.d.ts +46 -0
  65. package/dist/components/kit/date-field.svelte +210 -0
  66. package/dist/components/kit/date-field.svelte.d.ts +14 -0
  67. package/dist/components/kit/field-frame.svelte +71 -0
  68. package/dist/components/kit/field-frame.svelte.d.ts +26 -0
  69. package/dist/components/kit/fieldset-frame.svelte +69 -0
  70. package/dist/components/kit/fieldset-frame.svelte.d.ts +14 -0
  71. package/dist/components/kit/file-dropzone/files.d.ts +14 -0
  72. package/dist/components/kit/file-dropzone/files.js +69 -0
  73. package/dist/components/kit/file-dropzone.svelte +253 -0
  74. package/dist/components/kit/file-dropzone.svelte.d.ts +25 -0
  75. package/dist/components/kit/form.svelte +335 -0
  76. package/dist/components/kit/form.svelte.d.ts +61 -0
  77. package/dist/components/kit/input.svelte +73 -0
  78. package/dist/components/kit/input.svelte.d.ts +9 -0
  79. package/dist/components/kit/menu.svelte +163 -0
  80. package/dist/components/kit/menu.svelte.d.ts +28 -0
  81. package/dist/components/kit/pagination.svelte +134 -0
  82. package/dist/components/kit/pagination.svelte.d.ts +17 -0
  83. package/dist/components/kit/radio-list.svelte +131 -0
  84. package/dist/components/kit/radio-list.svelte.d.ts +15 -0
  85. package/dist/components/kit/segmented-control/segment.svelte +47 -0
  86. package/dist/components/kit/segmented-control/segment.svelte.d.ts +11 -0
  87. package/dist/components/kit/segmented-control.svelte +70 -0
  88. package/dist/components/kit/segmented-control.svelte.d.ts +16 -0
  89. package/dist/components/kit/select.svelte +244 -0
  90. package/dist/components/kit/select.svelte.d.ts +26 -0
  91. package/dist/components/kit/status-badge.svelte +54 -0
  92. package/dist/components/kit/status-badge.svelte.d.ts +31 -0
  93. package/dist/components/kit/switch.svelte +84 -0
  94. package/dist/components/kit/switch.svelte.d.ts +8 -0
  95. package/dist/components/kit/tabs.svelte +86 -0
  96. package/dist/components/kit/tabs.svelte.d.ts +20 -0
  97. package/dist/components/kit/textarea.svelte +92 -0
  98. package/dist/components/kit/textarea.svelte.d.ts +11 -0
  99. package/dist/components/ui/drawer/drawer-content.svelte +1 -1
  100. package/dist/components/ui/input-group/input-group-input.svelte.d.ts +1 -1
  101. package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +1 -1
  102. package/dist/components/ui/sonner/sonner.svelte +2 -4
  103. package/dist/mcp-content.json +1 -1
  104. package/dist/mcp.js +11 -11
  105. package/dist/server/hooks.d.ts +9 -0
  106. package/dist/server/hooks.js +41 -0
  107. package/dist/server/logger.d.ts +39 -0
  108. package/dist/server/logger.js +144 -0
  109. package/dist/server/telemetry.d.ts +23 -0
  110. package/dist/server/telemetry.js +82 -0
  111. package/dist/theme.css +18 -6
  112. package/package.json +40 -1
@@ -0,0 +1,229 @@
1
+ <script lang="ts" module>
2
+ export interface TimeRange {
3
+ preset: string;
4
+ start: Date;
5
+ end: Date;
6
+ }
7
+
8
+ export type TimeRangePreset = { id: string; label: string } & (
9
+ { duration: number } | { range: (now: Date) => { start: Date; end: Date } }
10
+ );
11
+
12
+ const day = 86_400_000;
13
+
14
+ export const defaultTimeRangePresets: readonly TimeRangePreset[] = [
15
+ { id: "24h", label: "24 hours", duration: day },
16
+ { id: "7d", label: "7 days", duration: 7 * day },
17
+ { id: "30d", label: "30 days", duration: 30 * day },
18
+ { id: "90d", label: "90 days", duration: 90 * day },
19
+ {
20
+ id: "12m",
21
+ label: "12 months",
22
+ range: (now) => {
23
+ const start = new Date(now);
24
+ start.setFullYear(start.getFullYear() - 1);
25
+ return { start, end: new Date(now) };
26
+ },
27
+ },
28
+ ];
29
+
30
+ export function rangeFor(preset: TimeRangePreset, now: Date): TimeRange {
31
+ const { start, end } =
32
+ "range" in preset
33
+ ? preset.range(now)
34
+ : {
35
+ start: new Date(now.getTime() - preset.duration),
36
+ end: new Date(now),
37
+ };
38
+ return { preset: preset.id, start, end };
39
+ }
40
+ </script>
41
+
42
+ <script lang="ts">
43
+ import {
44
+ type DateValue,
45
+ fromDate,
46
+ getLocalTimeZone,
47
+ toCalendarDate,
48
+ today,
49
+ } from "@internationalized/date";
50
+ import { MediaQuery } from "svelte/reactivity";
51
+
52
+ import { Button } from "../ui/button/index.js";
53
+ import * as Drawer from "../ui/drawer/index.js";
54
+ import * as Popover from "../ui/popover/index.js";
55
+ import { RangeCalendar } from "../ui/range-calendar/index.js";
56
+ import * as ToggleGroup from "../ui/toggle-group/index.js";
57
+ import { cn } from "../../utils.js";
58
+
59
+ const defaultMessages = {
60
+ label: "Time range",
61
+ custom: "Custom",
62
+ customTitle: "Custom range",
63
+ apply: "Apply",
64
+ cancel: "Cancel",
65
+ };
66
+
67
+ interface Props {
68
+ presets?: readonly TimeRangePreset[];
69
+ value?: TimeRange;
70
+ onchange?: (value: TimeRange) => void;
71
+ messages?: Partial<typeof defaultMessages>;
72
+ class?: string;
73
+ }
74
+
75
+ let {
76
+ presets = defaultTimeRangePresets,
77
+ value = $bindable(initialRange()),
78
+ onchange,
79
+ messages = {},
80
+ class: className,
81
+ }: Props = $props();
82
+
83
+ function initialRange(): TimeRange {
84
+ const now = new Date();
85
+ const preset = presets.find((entry) => entry.id === "30d") ?? presets[0];
86
+ return preset
87
+ ? rangeFor(preset, now)
88
+ : { preset: "", start: now, end: now };
89
+ }
90
+
91
+ const timeZone = getLocalTimeZone();
92
+ const desktop = new MediaQuery("(min-width: 768px)");
93
+ const dayFormat = new Intl.DateTimeFormat(undefined, {
94
+ day: "numeric",
95
+ month: "short",
96
+ });
97
+
98
+ let open = $state(false);
99
+ let draft = $state<{
100
+ start: DateValue | undefined;
101
+ end: DateValue | undefined;
102
+ }>({ start: undefined, end: undefined });
103
+ let placeholder = $state<DateValue>(today(timeZone));
104
+
105
+ const text = $derived({ ...defaultMessages, ...messages });
106
+ const custom = $derived(value.preset === "custom");
107
+ const customLabel = $derived(
108
+ custom ? dayFormat.formatRange(value.start, value.end) : text.custom,
109
+ );
110
+
111
+ function commit(next: TimeRange) {
112
+ value = next;
113
+ onchange?.(next);
114
+ }
115
+
116
+ function choose(id: string) {
117
+ const preset = presets.find((entry) => entry.id === id);
118
+ if (preset && id !== value.preset) {
119
+ commit(rangeFor(preset, new Date()));
120
+ }
121
+ }
122
+
123
+ function resetDraft() {
124
+ const end = toCalendarDate(fromDate(value.end, timeZone));
125
+ draft = { start: toCalendarDate(fromDate(value.start, timeZone)), end };
126
+ placeholder = desktop.current ? end.subtract({ months: 1 }) : end;
127
+ }
128
+
129
+ function apply() {
130
+ if (!draft.start || !draft.end) {
131
+ return;
132
+ }
133
+ commit({
134
+ preset: "custom",
135
+ start: draft.start.toDate(timeZone),
136
+ end: new Date(draft.end.add({ days: 1 }).toDate(timeZone).getTime() - 1),
137
+ });
138
+ open = false;
139
+ }
140
+
141
+ const itemClass =
142
+ "text-muted-foreground hover:text-foreground data-[state=on]:bg-background data-[state=on]:text-foreground h-11 rounded-full px-4 hover:bg-transparent data-[state=on]:shadow-sm md:h-8 md:px-3";
143
+ </script>
144
+
145
+ {#snippet calendar(months: number)}
146
+ <RangeCalendar
147
+ bind:value={draft}
148
+ bind:placeholder
149
+ numberOfMonths={months}
150
+ maxValue={today(timeZone)}
151
+ class="mx-auto"
152
+ />
153
+ {/snippet}
154
+
155
+ {#snippet actions()}
156
+ <Button variant="outline" class="h-11 md:h-9" onclick={() => (open = false)}
157
+ >{text.cancel}</Button
158
+ >
159
+ <Button
160
+ class="h-11 md:h-9"
161
+ disabled={!draft.start || !draft.end}
162
+ onclick={apply}>{text.apply}</Button
163
+ >
164
+ {/snippet}
165
+
166
+ <div class={cn("no-scrollbar w-full overflow-x-auto", className)}>
167
+ <div class="bg-muted inline-flex items-center gap-1 rounded-full p-1">
168
+ <ToggleGroup.Root
169
+ type="single"
170
+ spacing={1}
171
+ aria-label={text.label}
172
+ bind:value={() => value.preset, choose}
173
+ >
174
+ {#each presets as preset (preset.id)}
175
+ <ToggleGroup.Item value={preset.id} class={itemClass}
176
+ >{preset.label}</ToggleGroup.Item
177
+ >
178
+ {/each}
179
+ </ToggleGroup.Root>
180
+ {#if desktop.current}
181
+ <Popover.Root bind:open>
182
+ <Popover.Trigger
183
+ class={cn(
184
+ itemClass,
185
+ "text-sm font-medium whitespace-nowrap",
186
+ custom && "bg-background text-foreground shadow-sm",
187
+ )}
188
+ onclick={resetDraft}>{customLabel}</Popover.Trigger
189
+ >
190
+ <Popover.Content align="end" class="w-auto">
191
+ <Popover.Header>
192
+ <Popover.Title>{text.customTitle}</Popover.Title>
193
+ </Popover.Header>
194
+ {@render calendar(2)}
195
+ <div class="flex justify-end gap-2">
196
+ {@render actions()}
197
+ </div>
198
+ </Popover.Content>
199
+ </Popover.Root>
200
+ {:else}
201
+ <button
202
+ type="button"
203
+ class={cn(
204
+ itemClass,
205
+ "text-sm font-medium whitespace-nowrap",
206
+ custom && "bg-background text-foreground shadow-sm",
207
+ )}
208
+ aria-haspopup="dialog"
209
+ onclick={() => {
210
+ resetDraft();
211
+ open = true;
212
+ }}>{customLabel}</button
213
+ >
214
+ <Drawer.Root bind:open>
215
+ <Drawer.Content>
216
+ <Drawer.Header class="px-5 text-left">
217
+ <Drawer.Title>{text.customTitle}</Drawer.Title>
218
+ </Drawer.Header>
219
+ <div class="px-5">
220
+ {@render calendar(1)}
221
+ </div>
222
+ <Drawer.Footer class="pb-safe-bottom grid grid-cols-2 gap-2 px-5">
223
+ {@render actions()}
224
+ </Drawer.Footer>
225
+ </Drawer.Content>
226
+ </Drawer.Root>
227
+ {/if}
228
+ </div>
229
+ </div>
@@ -0,0 +1,33 @@
1
+ export interface TimeRange {
2
+ preset: string;
3
+ start: Date;
4
+ end: Date;
5
+ }
6
+ export type TimeRangePreset = {
7
+ id: string;
8
+ label: string;
9
+ } & ({
10
+ duration: number;
11
+ } | {
12
+ range: (now: Date) => {
13
+ start: Date;
14
+ end: Date;
15
+ };
16
+ });
17
+ export declare const defaultTimeRangePresets: readonly TimeRangePreset[];
18
+ export declare function rangeFor(preset: TimeRangePreset, now: Date): TimeRange;
19
+ declare const TimeRangePicker: import("svelte").Component<{
20
+ presets?: readonly TimeRangePreset[];
21
+ value?: TimeRange;
22
+ onchange?: (value: TimeRange) => void;
23
+ messages?: Partial<{
24
+ label: string;
25
+ custom: string;
26
+ customTitle: string;
27
+ apply: string;
28
+ cancel: string;
29
+ }>;
30
+ class?: string;
31
+ }, {}, "value">;
32
+ type TimeRangePicker = ReturnType<typeof TimeRangePicker>;
33
+ export default TimeRangePicker;
@@ -0,0 +1,43 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ caption: string;
4
+ dateHeading: string;
5
+ names: string[];
6
+ rows: { time: number; date: string; values: string[] }[];
7
+ visible: boolean;
8
+ id: string;
9
+ }
10
+
11
+ const { caption, dateHeading, names, rows, visible, id }: Props = $props();
12
+ </script>
13
+
14
+ <div
15
+ {id}
16
+ class={visible ? "mt-3 max-h-72 overflow-auto rounded-xl border" : "sr-only"}
17
+ >
18
+ <table class="w-full text-sm">
19
+ <caption class="sr-only">{caption}</caption>
20
+ <thead class="bg-muted sticky top-0">
21
+ <tr>
22
+ <th scope="col" class="px-3 py-2 text-left font-medium"
23
+ >{dateHeading}</th
24
+ >
25
+ {#each names as name, index (index)}
26
+ <th scope="col" class="px-3 py-2 text-right font-medium">{name}</th>
27
+ {/each}
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ {#each rows as row (row.time)}
32
+ <tr class="border-t">
33
+ <th scope="row" class="px-3 py-1.5 text-left font-normal"
34
+ >{row.date}</th
35
+ >
36
+ {#each row.values as value, index (index)}
37
+ <td class="px-3 py-1.5 text-right tabular">{value}</td>
38
+ {/each}
39
+ </tr>
40
+ {/each}
41
+ </tbody>
42
+ </table>
43
+ </div>
@@ -0,0 +1,15 @@
1
+ interface Props {
2
+ caption: string;
3
+ dateHeading: string;
4
+ names: string[];
5
+ rows: {
6
+ time: number;
7
+ date: string;
8
+ values: string[];
9
+ }[];
10
+ visible: boolean;
11
+ id: string;
12
+ }
13
+ declare const DataTable: import("svelte").Component<Props, {}, "">;
14
+ type DataTable = ReturnType<typeof DataTable>;
15
+ export default DataTable;
@@ -0,0 +1,23 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ entries: { name: string; color: string }[];
4
+ kind: "line" | "area" | "bar";
5
+ }
6
+
7
+ const { entries, kind }: Props = $props();
8
+ </script>
9
+
10
+ <ul class="flex flex-wrap items-center gap-x-4 gap-y-1 text-sm">
11
+ {#each entries as entry, index (index)}
12
+ <li class="flex items-center gap-2">
13
+ <span
14
+ aria-hidden="true"
15
+ class="shrink-0 {kind === 'line'
16
+ ? 'h-0.5 w-4 rounded-full'
17
+ : 'size-2.5 rounded-[3px]'}"
18
+ style:background-color={entry.color}
19
+ ></span>
20
+ {entry.name}
21
+ </li>
22
+ {/each}
23
+ </ul>
@@ -0,0 +1,10 @@
1
+ interface Props {
2
+ entries: {
3
+ name: string;
4
+ color: string;
5
+ }[];
6
+ kind: "line" | "area" | "bar";
7
+ }
8
+ declare const Legend: import("svelte").Component<Props, {}, "">;
9
+ type Legend = ReturnType<typeof Legend>;
10
+ export default Legend;
@@ -0,0 +1,118 @@
1
+ <script lang="ts">
2
+ import {
3
+ areaPath,
4
+ linePath,
5
+ type Position,
6
+ } from "./scale.js";
7
+
8
+ interface LineGeometry {
9
+ color: string;
10
+ segments: Position[][];
11
+ end: (Position & { label: string }) | null;
12
+ }
13
+
14
+ interface BarGeometry {
15
+ color: string;
16
+ bars: { path: string; column: number }[];
17
+ }
18
+
19
+ interface Props {
20
+ kind: "line" | "area" | "bar";
21
+ lines: LineGeometry[];
22
+ bars: BarGeometry[];
23
+ baseline: number;
24
+ activeColumn: number | null;
25
+ activeDots: (Position & { color: string })[];
26
+ directLabels: boolean;
27
+ }
28
+
29
+ const {
30
+ kind,
31
+ lines,
32
+ bars,
33
+ baseline,
34
+ activeColumn,
35
+ activeDots,
36
+ directLabels,
37
+ }: Props = $props();
38
+ </script>
39
+
40
+ {#if kind === "bar"}
41
+ {#each bars as entry, seriesIndex (seriesIndex)}
42
+ <g style:fill={entry.color}>
43
+ {#each entry.bars as bar (bar.column)}
44
+ <path
45
+ d={bar.path}
46
+ class="transition-opacity duration-150"
47
+ opacity={activeColumn === null || activeColumn === bar.column
48
+ ? 1
49
+ : 0.45}
50
+ />
51
+ {/each}
52
+ </g>
53
+ {/each}
54
+ {:else}
55
+ {#each lines as entry, seriesIndex (seriesIndex)}
56
+ <g style:color={entry.color}>
57
+ {#each entry.segments as segment, segmentIndex (segmentIndex)}
58
+ {#if segment.length > 1}
59
+ {#if kind === "area"}
60
+ <path
61
+ d={areaPath(segment, baseline)}
62
+ fill="currentColor"
63
+ fill-opacity="0.1"
64
+ />
65
+ {/if}
66
+ <path
67
+ d={linePath(segment)}
68
+ fill="none"
69
+ stroke="currentColor"
70
+ stroke-width="2"
71
+ stroke-linejoin="round"
72
+ stroke-linecap="round"
73
+ data-segment
74
+ />
75
+ {:else if segment[0]}
76
+ <circle
77
+ cx={segment[0].x}
78
+ cy={segment[0].y}
79
+ r="4"
80
+ fill="currentColor"
81
+ class="stroke-background"
82
+ stroke-width="2"
83
+ data-segment
84
+ />
85
+ {/if}
86
+ {/each}
87
+ {#if entry.end}
88
+ <circle
89
+ cx={entry.end.x}
90
+ cy={entry.end.y}
91
+ r="4"
92
+ fill="currentColor"
93
+ class="stroke-background"
94
+ stroke-width="2"
95
+ />
96
+ {#if directLabels}
97
+ <text
98
+ x={entry.end.x + 9}
99
+ y={entry.end.y}
100
+ dominant-baseline="middle"
101
+ class="fill-foreground text-[11px] font-medium tabular"
102
+ >{entry.end.label}</text
103
+ >
104
+ {/if}
105
+ {/if}
106
+ </g>
107
+ {/each}
108
+ {/if}
109
+ {#each activeDots as dot, index (index)}
110
+ <circle
111
+ cx={dot.x}
112
+ cy={dot.y}
113
+ r="5"
114
+ style:fill={dot.color}
115
+ class="stroke-background pointer-events-none"
116
+ stroke-width="2"
117
+ />
118
+ {/each}
@@ -0,0 +1,29 @@
1
+ import { type Position } from "./scale.js";
2
+ interface LineGeometry {
3
+ color: string;
4
+ segments: Position[][];
5
+ end: (Position & {
6
+ label: string;
7
+ }) | null;
8
+ }
9
+ interface BarGeometry {
10
+ color: string;
11
+ bars: {
12
+ path: string;
13
+ column: number;
14
+ }[];
15
+ }
16
+ interface Props {
17
+ kind: "line" | "area" | "bar";
18
+ lines: LineGeometry[];
19
+ bars: BarGeometry[];
20
+ baseline: number;
21
+ activeColumn: number | null;
22
+ activeDots: (Position & {
23
+ color: string;
24
+ })[];
25
+ directLabels: boolean;
26
+ }
27
+ declare const Marks: import("svelte").Component<Props, {}, "">;
28
+ type Marks = ReturnType<typeof Marks>;
29
+ export default Marks;
@@ -0,0 +1,13 @@
1
+ export declare const defaultMessages: {
2
+ empty: string;
3
+ noValue: string;
4
+ date: string;
5
+ peak: string;
6
+ average: string;
7
+ showTable: string;
8
+ hideTable: string;
9
+ keyboardHint: string;
10
+ summary: (title: string, start: string, end: string) => string;
11
+ seriesSummary: (name: string, low: string, high: string, latest: string) => string;
12
+ };
13
+ export type TimeSeriesChartMessages = typeof defaultMessages;
@@ -0,0 +1,12 @@
1
+ export const defaultMessages = {
2
+ empty: "No data in this range yet.",
3
+ noValue: "No data",
4
+ date: "Date",
5
+ peak: "Peak",
6
+ average: "Average",
7
+ showTable: "Show data table",
8
+ hideTable: "Hide data table",
9
+ keyboardHint: "Use the arrow keys to read each value.",
10
+ summary: (title, start, end) => `${title}, from ${start} to ${end}.`,
11
+ seriesSummary: (name, low, high, latest) => `${name}: low ${low}, high ${high}, latest ${latest}.`,
12
+ };
@@ -0,0 +1,44 @@
1
+ <script lang="ts">
2
+ interface Row {
3
+ name: string;
4
+ color: string;
5
+ value: string;
6
+ }
7
+
8
+ interface Props {
9
+ label: string;
10
+ rows: Row[];
11
+ placement: "floating" | "above";
12
+ x: number;
13
+ width: number;
14
+ }
15
+
16
+ const { label, rows, placement, x, width }: Props = $props();
17
+
18
+ const flip = $derived(x > width / 2);
19
+ </script>
20
+
21
+ <div
22
+ data-readout
23
+ aria-hidden="true"
24
+ class="bg-popover text-popover-foreground pointer-events-none absolute z-10 rounded-xl border px-3 py-2 text-xs shadow-md {placement ===
25
+ 'above'
26
+ ? 'inset-x-0 bottom-full mb-2 flex flex-wrap items-baseline gap-x-4 gap-y-1'
27
+ : 'top-0 grid gap-1 whitespace-nowrap'}"
28
+ style:left={placement === "floating" && !flip ? `${x + 12}px` : undefined}
29
+ style:right={placement === "floating" && flip
30
+ ? `${width - x + 12}px`
31
+ : undefined}
32
+ >
33
+ <p class="text-muted-foreground">{label}</p>
34
+ {#each rows as row, index (index)}
35
+ <p class="flex items-center gap-2">
36
+ <span
37
+ class="h-0.5 w-3 shrink-0 rounded-full"
38
+ style:background-color={row.color}
39
+ ></span>
40
+ <span class="font-semibold tabular">{row.value}</span>
41
+ <span class="text-muted-foreground">{row.name}</span>
42
+ </p>
43
+ {/each}
44
+ </div>
@@ -0,0 +1,15 @@
1
+ interface Row {
2
+ name: string;
3
+ color: string;
4
+ value: string;
5
+ }
6
+ interface Props {
7
+ label: string;
8
+ rows: Row[];
9
+ placement: "floating" | "above";
10
+ x: number;
11
+ width: number;
12
+ }
13
+ declare const Readout: import("svelte").Component<Props, {}, "">;
14
+ type Readout = ReturnType<typeof Readout>;
15
+ export default Readout;
@@ -0,0 +1,24 @@
1
+ export interface TimePoint {
2
+ at: Date;
3
+ value: number | null;
4
+ }
5
+ export interface TimeSeries {
6
+ name: string;
7
+ points: TimePoint[];
8
+ }
9
+ export interface Position {
10
+ x: number;
11
+ y: number;
12
+ }
13
+ export declare function niceStep(span: number, count: number): number;
14
+ export declare function niceTicks(minimum: number, maximum: number, count: number): number[];
15
+ export declare function scaleLinear(domain: [number, number], range: [number, number]): (value: number) => number;
16
+ export declare function columnsOf(series: TimeSeries[]): number[];
17
+ export declare function valueMap(series: TimeSeries): Map<number, number | null>;
18
+ export declare function valueExtent(series: TimeSeries[]): [number, number] | null;
19
+ export declare function segmentsOf(points: TimePoint[]): TimePoint[][];
20
+ export declare function nearestIndex(times: number[], target: number): number;
21
+ export declare function medianSpacing(times: number[]): number;
22
+ export declare function linePath(positions: Position[]): string;
23
+ export declare function areaPath(positions: Position[], baseline: number): string;
24
+ export declare function barPath(left: number, width: number, top: number, baseline: number): string;