markgraphy 0.1.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 (166) hide show
  1. package/LICENSE.txt +21 -0
  2. package/README.md +154 -0
  3. package/dist/animated/GraphAgni.svelte +430 -0
  4. package/dist/animated/GraphAgni.svelte.d.ts +22 -0
  5. package/dist/animated/GraphAum.svelte +294 -0
  6. package/dist/animated/GraphAum.svelte.d.ts +20 -0
  7. package/dist/animated/GraphBoot.svelte +325 -0
  8. package/dist/animated/GraphBoot.svelte.d.ts +28 -0
  9. package/dist/animated/GraphCron.svelte +476 -0
  10. package/dist/animated/GraphCron.svelte.d.ts +42 -0
  11. package/dist/animated/GraphDamru.svelte +341 -0
  12. package/dist/animated/GraphDamru.svelte.d.ts +18 -0
  13. package/dist/animated/GraphDeps.svelte +245 -0
  14. package/dist/animated/GraphDeps.svelte.d.ts +29 -0
  15. package/dist/animated/GraphDiya.svelte +330 -0
  16. package/dist/animated/GraphDiya.svelte.d.ts +22 -0
  17. package/dist/animated/GraphFire.svelte +246 -0
  18. package/dist/animated/GraphFire.svelte.d.ts +22 -0
  19. package/dist/animated/GraphFlame.svelte +258 -0
  20. package/dist/animated/GraphFlame.svelte.d.ts +14 -0
  21. package/dist/animated/GraphFlowPlayer.svelte +346 -0
  22. package/dist/animated/GraphFlowPlayer.svelte.d.ts +27 -0
  23. package/dist/animated/GraphGanga.svelte +305 -0
  24. package/dist/animated/GraphGanga.svelte.d.ts +20 -0
  25. package/dist/animated/GraphHash.svelte +251 -0
  26. package/dist/animated/GraphHash.svelte.d.ts +20 -0
  27. package/dist/animated/GraphJapa.svelte +253 -0
  28. package/dist/animated/GraphJapa.svelte.d.ts +20 -0
  29. package/dist/animated/GraphLife.svelte +312 -0
  30. package/dist/animated/GraphLife.svelte.d.ts +27 -0
  31. package/dist/animated/GraphMandala.svelte +262 -0
  32. package/dist/animated/GraphMandala.svelte.d.ts +24 -0
  33. package/dist/animated/GraphMandel.svelte +290 -0
  34. package/dist/animated/GraphMandel.svelte.d.ts +27 -0
  35. package/dist/animated/GraphPulse.svelte +248 -0
  36. package/dist/animated/GraphPulse.svelte.d.ts +24 -0
  37. package/dist/animated/GraphRain.svelte +280 -0
  38. package/dist/animated/GraphRain.svelte.d.ts +22 -0
  39. package/dist/animated/GraphScatter.svelte +395 -0
  40. package/dist/animated/GraphScatter.svelte.d.ts +31 -0
  41. package/dist/animated/GraphScope.svelte +197 -0
  42. package/dist/animated/GraphScope.svelte.d.ts +22 -0
  43. package/dist/animated/GraphSequence.svelte +247 -0
  44. package/dist/animated/GraphSequence.svelte.d.ts +18 -0
  45. package/dist/animated/GraphSpinners.svelte +109 -0
  46. package/dist/animated/GraphSpinners.svelte.d.ts +22 -0
  47. package/dist/animated/GraphState.svelte +270 -0
  48. package/dist/animated/GraphState.svelte.d.ts +14 -0
  49. package/dist/animated/GraphStream.svelte +223 -0
  50. package/dist/animated/GraphStream.svelte.d.ts +24 -0
  51. package/dist/animated/GraphSurya.svelte +268 -0
  52. package/dist/animated/GraphSurya.svelte.d.ts +22 -0
  53. package/dist/animated/GraphTerminal.svelte +238 -0
  54. package/dist/animated/GraphTerminal.svelte.d.ts +28 -0
  55. package/dist/animated/GraphTicker.svelte +163 -0
  56. package/dist/animated/GraphTicker.svelte.d.ts +21 -0
  57. package/dist/animated/GraphTypewriter.svelte +130 -0
  58. package/dist/animated/GraphTypewriter.svelte.d.ts +22 -0
  59. package/dist/animated/GraphWorkflow.svelte +570 -0
  60. package/dist/animated/GraphWorkflow.svelte.d.ts +29 -0
  61. package/dist/assets/favicon.svg +21 -0
  62. package/dist/diagram/AmplifierDiagram.svelte +206 -0
  63. package/dist/diagram/AmplifierDiagram.svelte.d.ts +12 -0
  64. package/dist/diagram/AsciiDiagram.svelte +212 -0
  65. package/dist/diagram/AsciiDiagram.svelte.d.ts +24 -0
  66. package/dist/diagram/DiagramEditor.svelte +414 -0
  67. package/dist/diagram/DiagramEditor.svelte.d.ts +3 -0
  68. package/dist/diagram/MetricsTableDiagram.svelte +125 -0
  69. package/dist/diagram/MetricsTableDiagram.svelte.d.ts +18 -0
  70. package/dist/diagram/NestedRadiiDiagram.svelte +218 -0
  71. package/dist/diagram/NestedRadiiDiagram.svelte.d.ts +12 -0
  72. package/dist/diagram/PromptLoopDiagram.svelte +331 -0
  73. package/dist/diagram/PromptLoopDiagram.svelte.d.ts +12 -0
  74. package/dist/diagram/ascii.d.ts +35 -0
  75. package/dist/diagram/ascii.js +83 -0
  76. package/dist/diagram/parser.d.ts +16 -0
  77. package/dist/diagram/parser.js +71 -0
  78. package/dist/frame/Graph.svelte +141 -0
  79. package/dist/frame/Graph.svelte.d.ts +14 -0
  80. package/dist/frame/GraphArrow.svelte +49 -0
  81. package/dist/frame/GraphArrow.svelte.d.ts +9 -0
  82. package/dist/frame/GraphBody.svelte +39 -0
  83. package/dist/frame/GraphBody.svelte.d.ts +10 -0
  84. package/dist/frame/GraphRule.svelte +21 -0
  85. package/dist/frame/GraphRule.svelte.d.ts +6 -0
  86. package/dist/frame/GraphTick.svelte +23 -0
  87. package/dist/frame/GraphTick.svelte.d.ts +9 -0
  88. package/dist/frame/GraphTrack.svelte +29 -0
  89. package/dist/frame/GraphTrack.svelte.d.ts +14 -0
  90. package/dist/frame/clock.d.ts +10 -0
  91. package/dist/frame/clock.js +62 -0
  92. package/dist/frame/glyphs.d.ts +22 -0
  93. package/dist/frame/glyphs.js +53 -0
  94. package/dist/frame/motion.css +27 -0
  95. package/dist/frame/motion.d.ts +24 -0
  96. package/dist/frame/motion.js +47 -0
  97. package/dist/frame/tone.d.ts +11 -0
  98. package/dist/frame/tone.js +64 -0
  99. package/dist/graphs/GraphActivity.svelte +387 -0
  100. package/dist/graphs/GraphActivity.svelte.d.ts +22 -0
  101. package/dist/graphs/GraphBars.svelte +194 -0
  102. package/dist/graphs/GraphBars.svelte.d.ts +20 -0
  103. package/dist/graphs/GraphBullet.svelte +208 -0
  104. package/dist/graphs/GraphBullet.svelte.d.ts +22 -0
  105. package/dist/graphs/GraphCalendar.svelte +203 -0
  106. package/dist/graphs/GraphCalendar.svelte.d.ts +20 -0
  107. package/dist/graphs/GraphCells.svelte +181 -0
  108. package/dist/graphs/GraphCells.svelte.d.ts +18 -0
  109. package/dist/graphs/GraphCompare.svelte +192 -0
  110. package/dist/graphs/GraphCompare.svelte.d.ts +18 -0
  111. package/dist/graphs/GraphCountdown.svelte +96 -0
  112. package/dist/graphs/GraphCountdown.svelte.d.ts +14 -0
  113. package/dist/graphs/GraphDiff.svelte +181 -0
  114. package/dist/graphs/GraphDiff.svelte.d.ts +18 -0
  115. package/dist/graphs/GraphFlow.svelte +137 -0
  116. package/dist/graphs/GraphFlow.svelte.d.ts +21 -0
  117. package/dist/graphs/GraphFunnel.svelte +190 -0
  118. package/dist/graphs/GraphFunnel.svelte.d.ts +21 -0
  119. package/dist/graphs/GraphGantt.svelte +258 -0
  120. package/dist/graphs/GraphGantt.svelte.d.ts +25 -0
  121. package/dist/graphs/GraphHeatmap.svelte +287 -0
  122. package/dist/graphs/GraphHeatmap.svelte.d.ts +22 -0
  123. package/dist/graphs/GraphInvoice.svelte +294 -0
  124. package/dist/graphs/GraphInvoice.svelte.d.ts +34 -0
  125. package/dist/graphs/GraphKpi.svelte +166 -0
  126. package/dist/graphs/GraphKpi.svelte.d.ts +17 -0
  127. package/dist/graphs/GraphLatency.svelte +340 -0
  128. package/dist/graphs/GraphLatency.svelte.d.ts +28 -0
  129. package/dist/graphs/GraphMeter.svelte +121 -0
  130. package/dist/graphs/GraphMeter.svelte.d.ts +16 -0
  131. package/dist/graphs/GraphPlot.svelte +226 -0
  132. package/dist/graphs/GraphPlot.svelte.d.ts +18 -0
  133. package/dist/graphs/GraphQuota.svelte +303 -0
  134. package/dist/graphs/GraphQuota.svelte.d.ts +27 -0
  135. package/dist/graphs/GraphRank.svelte +141 -0
  136. package/dist/graphs/GraphRank.svelte.d.ts +21 -0
  137. package/dist/graphs/GraphSlo.svelte +325 -0
  138. package/dist/graphs/GraphSlo.svelte.d.ts +31 -0
  139. package/dist/graphs/GraphSlope.svelte +197 -0
  140. package/dist/graphs/GraphSlope.svelte.d.ts +19 -0
  141. package/dist/graphs/GraphSpark.svelte +125 -0
  142. package/dist/graphs/GraphSpark.svelte.d.ts +15 -0
  143. package/dist/graphs/GraphSpec.svelte +69 -0
  144. package/dist/graphs/GraphSpec.svelte.d.ts +14 -0
  145. package/dist/graphs/GraphStack.svelte +266 -0
  146. package/dist/graphs/GraphStack.svelte.d.ts +25 -0
  147. package/dist/graphs/GraphStat.svelte +103 -0
  148. package/dist/graphs/GraphStat.svelte.d.ts +16 -0
  149. package/dist/graphs/GraphTable.svelte +133 -0
  150. package/dist/graphs/GraphTable.svelte.d.ts +15 -0
  151. package/dist/graphs/GraphTimeline.svelte +164 -0
  152. package/dist/graphs/GraphTimeline.svelte.d.ts +18 -0
  153. package/dist/graphs/GraphTimer.svelte +117 -0
  154. package/dist/graphs/GraphTimer.svelte.d.ts +15 -0
  155. package/dist/graphs/GraphTree.svelte +147 -0
  156. package/dist/graphs/GraphTree.svelte.d.ts +16 -0
  157. package/dist/graphs/GraphUptime.svelte +210 -0
  158. package/dist/graphs/GraphUptime.svelte.d.ts +18 -0
  159. package/dist/graphs/GraphWaffle.svelte +131 -0
  160. package/dist/graphs/GraphWaffle.svelte.d.ts +17 -0
  161. package/dist/graphs/GraphWaterfall.svelte +258 -0
  162. package/dist/graphs/GraphWaterfall.svelte.d.ts +22 -0
  163. package/dist/index.d.ts +147 -0
  164. package/dist/index.js +87 -0
  165. package/dist/themes.css +54 -0
  166. package/package.json +67 -0
@@ -0,0 +1,164 @@
1
+ <script module lang="ts">
2
+ import type { GraphPalette } from '../frame/tone';
3
+
4
+ /** Progress state of a timeline event. */
5
+ export type TimelineState = 'done' | 'now' | 'next';
6
+
7
+ export interface TimelineEvent {
8
+ date: string;
9
+ label: string;
10
+ state?: TimelineState;
11
+ }
12
+
13
+ export interface GraphTimelineProps {
14
+ title: string;
15
+ events: TimelineEvent[];
16
+ palette?: GraphPalette;
17
+ corner?: string;
18
+ class?: string;
19
+ }
20
+ </script>
21
+
22
+ <script lang="ts">
23
+ import Graph from '../frame/Graph.svelte';
24
+ import GraphBody from '../frame/GraphBody.svelte';
25
+ import { reveal, stagger } from '../frame/motion';
26
+ import { toneRole, type ToneRole } from '../frame/tone';
27
+
28
+ const MARK: Record<TimelineState, string> = {
29
+ done: '●',
30
+ now: '●',
31
+ next: '○'
32
+ };
33
+
34
+ let {
35
+ title,
36
+ events,
37
+ palette,
38
+ corner,
39
+ class: className = ''
40
+ }: GraphTimelineProps = $props();
41
+
42
+ function eventRole(state: TimelineState): ToneRole {
43
+ if (state === 'now') {
44
+ return toneRole(palette, 'primary');
45
+ }
46
+
47
+ if (state === 'next') {
48
+ return toneRole(palette, 'secondary');
49
+ }
50
+
51
+ return 'foreground';
52
+ }
53
+
54
+ function dateRole(state: TimelineState): ToneRole {
55
+ return state === 'next' ? toneRole(palette, 'secondary') : 'foreground';
56
+ }
57
+ </script>
58
+
59
+ <Graph {title} {corner} class={className}>
60
+ <GraphBody>
61
+ <ol class="timeline" role="list">
62
+ {#each events as event, index (`${event.date}-${event.label}`)}
63
+ {@const state = event.state ?? 'done'}
64
+ {@const main = eventRole(state)}
65
+ {@const date = dateRole(state)}
66
+ <li class="event" use:reveal={{ delay: stagger(index, 50), amount: 0.4 }}>
67
+ <div class="line">
68
+ <span
69
+ class="mark"
70
+ aria-hidden="true"
71
+ class:c-accent={main === 'accent'}
72
+ class:c-accent2={main === 'accent2'}
73
+ class:c-muted={main === 'muted'}
74
+ class:c-fg={main === 'foreground'}
75
+ >
76
+ {MARK[state]}
77
+ </span>
78
+ <span
79
+ class="when"
80
+ class:c-accent={date === 'accent'}
81
+ class:c-accent2={date === 'accent2'}
82
+ class:c-muted={date === 'muted'}
83
+ class:c-fg={date === 'foreground'}
84
+ >
85
+ {event.date}
86
+ </span>
87
+ <span
88
+ class="label"
89
+ class:c-accent={main === 'accent'}
90
+ class:c-accent2={main === 'accent2'}
91
+ class:c-muted={main === 'muted'}
92
+ class:c-fg={main === 'foreground'}
93
+ >
94
+ {event.label}
95
+ </span>
96
+ </div>
97
+ {#if index < events.length - 1}
98
+ <div class="link" aria-hidden="true">
99
+ <span class="linkmark">│</span>
100
+ </div>
101
+ {/if}
102
+ </li>
103
+ {/each}
104
+ </ol>
105
+ </GraphBody>
106
+ </Graph>
107
+
108
+ <style>
109
+ .timeline {
110
+ display: flex;
111
+ flex-direction: column;
112
+ margin: 0;
113
+ padding: 0;
114
+ list-style: none;
115
+ }
116
+
117
+ .event {
118
+ display: flex;
119
+ flex-direction: column;
120
+ }
121
+
122
+ .line {
123
+ display: grid;
124
+ grid-template-columns: 1.25rem 7rem minmax(0, 1fr);
125
+ align-items: baseline;
126
+ column-gap: 1rem;
127
+ }
128
+
129
+ .mark {
130
+ text-align: center;
131
+ line-height: 1;
132
+ user-select: none;
133
+ }
134
+
135
+ .link {
136
+ display: grid;
137
+ grid-template-columns: 1.25rem 7rem minmax(0, 1fr);
138
+ column-gap: 1rem;
139
+ padding: 0.25rem 0;
140
+ user-select: none;
141
+ }
142
+
143
+ .linkmark {
144
+ grid-column: 1;
145
+ text-align: center;
146
+ color: var(--graph-frame, oklch(0.6 0 0 / 0.5));
147
+ }
148
+
149
+ .c-accent {
150
+ color: var(--graph-accent, oklch(0.78 0.17 155));
151
+ }
152
+
153
+ .c-accent2 {
154
+ color: var(--graph-accent-2, oklch(0.78 0.12 70));
155
+ }
156
+
157
+ .c-muted {
158
+ color: var(--graph-muted, oklch(0.62 0 0));
159
+ }
160
+
161
+ .c-fg {
162
+ color: var(--graph-foreground, oklch(0.93 0 0));
163
+ }
164
+ </style>
@@ -0,0 +1,18 @@
1
+ import type { GraphPalette } from '../frame/tone';
2
+ /** Progress state of a timeline event. */
3
+ export type TimelineState = 'done' | 'now' | 'next';
4
+ export interface TimelineEvent {
5
+ date: string;
6
+ label: string;
7
+ state?: TimelineState;
8
+ }
9
+ export interface GraphTimelineProps {
10
+ title: string;
11
+ events: TimelineEvent[];
12
+ palette?: GraphPalette;
13
+ corner?: string;
14
+ class?: string;
15
+ }
16
+ declare const GraphTimeline: import("svelte").Component<GraphTimelineProps, {}, "">;
17
+ type GraphTimeline = ReturnType<typeof GraphTimeline>;
18
+ export default GraphTimeline;
@@ -0,0 +1,117 @@
1
+ <script module lang="ts">
2
+ import type { GraphPalette } from '../frame/tone';
3
+
4
+ /** Elapsed time, how long ago, or the local clock. */
5
+ export type TimerKind = 'elapsed' | 'ago' | 'clock';
6
+
7
+ export interface GraphTimerProps {
8
+ title: string;
9
+ kind?: TimerKind;
10
+ at?: Date | number | string;
11
+ caption?: string;
12
+ palette?: GraphPalette;
13
+ corner?: string;
14
+ class?: string;
15
+ }
16
+ </script>
17
+
18
+ <script lang="ts">
19
+ import Graph from '../frame/Graph.svelte';
20
+ import GraphBody from '../frame/GraphBody.svelte';
21
+ import { formatAgo, formatClock, formatHms, graphNow, parseInstant } from '../frame/clock';
22
+ import { reveal } from '../frame/motion';
23
+
24
+ let {
25
+ title,
26
+ kind = 'elapsed',
27
+ at,
28
+ caption,
29
+ palette,
30
+ corner,
31
+ class: className = ''
32
+ }: GraphTimerProps = $props();
33
+
34
+ const time = graphNow();
35
+ const origin = $derived(at == null ? Number.NaN : parseInstant(at));
36
+
37
+ const view = $derived.by(() => {
38
+ const placeholder = { value: kind === 'ago' ? '0s ago' : '00:00:00', spoken: 'timer' };
39
+
40
+ if ($time == null) {
41
+ return placeholder;
42
+ }
43
+
44
+ if (kind === 'clock') {
45
+ const value = formatClock($time);
46
+ return { value, spoken: `local time ${value}` };
47
+ }
48
+
49
+ if (!Number.isFinite(origin)) {
50
+ return placeholder;
51
+ }
52
+
53
+ const elapsed = Math.max(0, $time - origin);
54
+
55
+ if (kind === 'ago') {
56
+ const value = formatAgo(elapsed);
57
+ return { value, spoken: value };
58
+ }
59
+
60
+ const value = formatHms(elapsed);
61
+ return { value, spoken: `elapsed ${value}` };
62
+ });
63
+ </script>
64
+
65
+ <Graph {title} {corner} class={className}>
66
+ <GraphBody>
67
+ <div class="timer" use:reveal={{ amount: 0.5 }}>
68
+ <p class="value c-accent">{view.value}</p>
69
+ {#if caption}
70
+ <p class="muted">{caption}</p>
71
+ {/if}
72
+ </div>
73
+ <span class="sr-only">{view.spoken}</span>
74
+ </GraphBody>
75
+ </Graph>
76
+
77
+ <style>
78
+ .timer {
79
+ display: flex;
80
+ flex-direction: column;
81
+ gap: 0.5rem;
82
+ }
83
+
84
+ .value {
85
+ margin: 0;
86
+ font-size: 1.875rem;
87
+ line-height: 1.2;
88
+ letter-spacing: -0.025em;
89
+ }
90
+
91
+ @media (min-width: 640px) {
92
+ .value {
93
+ font-size: 2.25rem;
94
+ }
95
+ }
96
+
97
+ .muted {
98
+ margin: 0;
99
+ color: var(--graph-muted, oklch(0.62 0 0));
100
+ }
101
+
102
+ .c-accent {
103
+ color: var(--graph-accent, oklch(0.78 0.17 155));
104
+ }
105
+
106
+ .sr-only {
107
+ position: absolute;
108
+ width: 1px;
109
+ height: 1px;
110
+ padding: 0;
111
+ margin: -1px;
112
+ overflow: hidden;
113
+ clip-path: inset(50%);
114
+ white-space: nowrap;
115
+ border-width: 0;
116
+ }
117
+ </style>
@@ -0,0 +1,15 @@
1
+ import type { GraphPalette } from '../frame/tone';
2
+ /** Elapsed time, how long ago, or the local clock. */
3
+ export type TimerKind = 'elapsed' | 'ago' | 'clock';
4
+ export interface GraphTimerProps {
5
+ title: string;
6
+ kind?: TimerKind;
7
+ at?: Date | number | string;
8
+ caption?: string;
9
+ palette?: GraphPalette;
10
+ corner?: string;
11
+ class?: string;
12
+ }
13
+ declare const GraphTimer: import("svelte").Component<GraphTimerProps, {}, "">;
14
+ type GraphTimer = ReturnType<typeof GraphTimer>;
15
+ export default GraphTimer;
@@ -0,0 +1,147 @@
1
+ <script module lang="ts">
2
+ /** Indented file/org tree with ├─/└─ branches. */
3
+ export interface TreeNode {
4
+ label: string;
5
+ meta?: string;
6
+ accent?: boolean;
7
+ children?: TreeNode[];
8
+ }
9
+
10
+ export interface GraphTreeProps {
11
+ title: string;
12
+ nodes: TreeNode[];
13
+ corner?: string;
14
+ class?: string;
15
+ }
16
+ </script>
17
+
18
+ <script lang="ts">
19
+ import Graph from '../frame/Graph.svelte';
20
+ import GraphBody from '../frame/GraphBody.svelte';
21
+ import { reveal, stagger } from '../frame/motion';
22
+
23
+ let { title, nodes, corner, class: className = '' }: GraphTreeProps = $props();
24
+
25
+ interface FlatRow {
26
+ key: string;
27
+ branch: string;
28
+ label: string;
29
+ meta?: string;
30
+ accent?: boolean;
31
+ }
32
+
33
+ function flatten(
34
+ nodes: TreeNode[],
35
+ prefix = '',
36
+ trail = 'root',
37
+ isRoot = true
38
+ ): FlatRow[] {
39
+ const singleRoot = isRoot && nodes.length === 1;
40
+
41
+ return nodes.flatMap((node, index) => {
42
+ const last = index === nodes.length - 1;
43
+ const branch = singleRoot ? '' : prefix + (last ? '└─ ' : '├─ ');
44
+ const key = `${trail}/${node.label}-${index}`;
45
+ const childPrefix = singleRoot ? '' : prefix + (last ? ' ' : '│ ');
46
+ const row: FlatRow = {
47
+ key,
48
+ branch,
49
+ label: node.label,
50
+ meta: node.meta,
51
+ accent: node.accent
52
+ };
53
+ const kids = node.children ? flatten(node.children, childPrefix, key, false) : [];
54
+ return [row, ...kids];
55
+ });
56
+ }
57
+
58
+ const rows = $derived(flatten(nodes));
59
+ const hasAccent = $derived(rows.some((row) => row.accent));
60
+ </script>
61
+
62
+ <Graph {title} {corner} class={className}>
63
+ <GraphBody>
64
+ <div class="scroll">
65
+ <ul class="tree" role="list">
66
+ {#each rows as row, i (row.key)}
67
+ <li
68
+ class="row"
69
+ class:dim={hasAccent && !row.accent}
70
+ use:reveal={{ delay: stagger(i, 40), amount: 0.4 }}
71
+ >
72
+ <span class="entry">
73
+ <span class="branch" aria-hidden="true">{row.branch}</span>
74
+ <span class="label" class:c-accent={row.accent}>{row.label}</span>
75
+ </span>
76
+ {#if row.meta}
77
+ <span class="meta">{row.meta}</span>
78
+ {:else}
79
+ <span></span>
80
+ {/if}
81
+ </li>
82
+ {/each}
83
+ </ul>
84
+ </div>
85
+ <span class="sr-only">Tree with {rows.length} nodes</span>
86
+ </GraphBody>
87
+ </Graph>
88
+
89
+ <style>
90
+ .scroll {
91
+ overflow-x: auto;
92
+ }
93
+
94
+ .tree {
95
+ display: flex;
96
+ min-width: max-content;
97
+ flex-direction: column;
98
+ gap: 0.25rem;
99
+ margin: 0;
100
+ padding: 0;
101
+ list-style: none;
102
+ }
103
+
104
+ .row {
105
+ display: grid;
106
+ grid-template-columns: minmax(0, 1fr) auto;
107
+ align-items: baseline;
108
+ column-gap: 1.5rem;
109
+ }
110
+
111
+ .entry {
112
+ white-space: nowrap;
113
+ }
114
+
115
+ .branch {
116
+ color: var(--graph-frame, oklch(0.6 0 0 / 0.5));
117
+ user-select: none;
118
+ }
119
+
120
+ .label {
121
+ color: var(--graph-foreground, oklch(0.93 0 0));
122
+ }
123
+
124
+ .c-accent {
125
+ color: var(--graph-accent, oklch(0.78 0.17 155));
126
+ }
127
+
128
+ .meta {
129
+ color: var(--graph-muted, oklch(0.62 0 0));
130
+ }
131
+
132
+ .dim {
133
+ opacity: 0.4;
134
+ }
135
+
136
+ .sr-only {
137
+ position: absolute;
138
+ width: 1px;
139
+ height: 1px;
140
+ padding: 0;
141
+ margin: -1px;
142
+ overflow: hidden;
143
+ clip-path: inset(50%);
144
+ white-space: nowrap;
145
+ border-width: 0;
146
+ }
147
+ </style>
@@ -0,0 +1,16 @@
1
+ /** Indented file/org tree with ├─/└─ branches. */
2
+ export interface TreeNode {
3
+ label: string;
4
+ meta?: string;
5
+ accent?: boolean;
6
+ children?: TreeNode[];
7
+ }
8
+ export interface GraphTreeProps {
9
+ title: string;
10
+ nodes: TreeNode[];
11
+ corner?: string;
12
+ class?: string;
13
+ }
14
+ declare const GraphTree: import("svelte").Component<GraphTreeProps, {}, "">;
15
+ type GraphTree = ReturnType<typeof GraphTree>;
16
+ export default GraphTree;
@@ -0,0 +1,210 @@
1
+ <script module lang="ts">
2
+ import type { Glyphs } from '../frame/glyphs';
3
+ import type { GraphPalette } from '../frame/tone';
4
+
5
+ /** Rows of day-status glyphs: ok / degraded / down. */
6
+ export type UptimeStatus = 'ok' | 'degraded' | 'down' | 'empty';
7
+
8
+ export interface GraphUptimeProps {
9
+ title: string;
10
+ days: UptimeStatus[];
11
+ from?: string;
12
+ to?: string;
13
+ columns?: number;
14
+ glyphs?: Glyphs;
15
+ palette?: GraphPalette;
16
+ corner?: string;
17
+ class?: string;
18
+ }
19
+ </script>
20
+
21
+ <script lang="ts">
22
+ import Graph from '../frame/Graph.svelte';
23
+ import GraphBody from '../frame/GraphBody.svelte';
24
+ import { resolveGlyphs } from '../frame/glyphs';
25
+ import { isMonoPalette } from '../frame/tone';
26
+ import { reveal, stagger } from '../frame/motion';
27
+
28
+ let {
29
+ title,
30
+ days,
31
+ from,
32
+ to,
33
+ columns = 30,
34
+ glyphs,
35
+ palette,
36
+ corner,
37
+ class: className = ''
38
+ }: GraphUptimeProps = $props();
39
+
40
+ const mono = $derived(isMonoPalette(palette));
41
+
42
+ const view = $derived.by(() => {
43
+ const set = resolveGlyphs(glyphs);
44
+ const last = set.length - 1;
45
+ const known = days.filter((day) => day !== 'empty');
46
+ const ok = known.filter((day) => day === 'ok').length;
47
+ const percent = known.length === 0 ? 0 : Math.round((ok / known.length) * 100);
48
+ const cols = Math.max(1, columns);
49
+ const rows: UptimeStatus[][] = [];
50
+ for (let index = 0; index < days.length; index += cols) {
51
+ rows.push(days.slice(index, index + cols));
52
+ }
53
+ const mark: Record<UptimeStatus, string> = {
54
+ ok: set[last] ?? '█',
55
+ degraded: set[Math.min(2, last)] ?? '▒',
56
+ down: set[0] ?? '·',
57
+ empty: '-'
58
+ };
59
+ return { percent, rows, mark, knownCount: known.length };
60
+ });
61
+ </script>
62
+
63
+ <Graph {title} {corner} class={className}>
64
+ <GraphBody>
65
+ <div class="upt">
66
+ <div class="stack">
67
+ <div class="grid" aria-hidden="true">
68
+ {#each view.rows as row, rowIndex}
69
+ <div class="week" use:reveal={{ delay: stagger(rowIndex, 40), amount: 0.4 }}>
70
+ {#each row as day}
71
+ <span
72
+ class="cell"
73
+ class:c-accent={day === 'ok'}
74
+ class:c-accent2={day === 'degraded' && !mono}
75
+ class:c-muted={day === 'degraded' && mono}
76
+ class:c-frame={day === 'down' || day === 'empty'}
77
+ >
78
+ {view.mark[day]}
79
+ </span>
80
+ {/each}
81
+ </div>
82
+ {/each}
83
+ </div>
84
+ <div class="meta">
85
+ {#if from || to}
86
+ <p class="dates">
87
+ {#if from}<span>{from}</span>{/if}
88
+ {#if to}<span>{to}</span>{/if}
89
+ </p>
90
+ {/if}
91
+ <p class="pct c-accent">{view.percent}%</p>
92
+ </div>
93
+ </div>
94
+ <p class="legend">
95
+ <span>
96
+ <span class="lg c-accent" aria-hidden="true">{view.mark.ok}</span> up
97
+ </span>
98
+ <span>
99
+ <span class="lg" class:c-accent2={!mono} class:c-muted={mono} aria-hidden="true">
100
+ {view.mark.degraded}
101
+ </span>
102
+ slow
103
+ </span>
104
+ <span>
105
+ <span class="lg c-frame" aria-hidden="true">{view.mark.down}</span> down
106
+ </span>
107
+ </p>
108
+ <span class="sr-only">
109
+ {view.percent} percent uptime over {view.knownCount} days{#if from && to}, {from}
110
+ to {to}{/if}
111
+ </span>
112
+ </div>
113
+ </GraphBody>
114
+ </Graph>
115
+
116
+ <style>
117
+ .upt {
118
+ display: flex;
119
+ flex-direction: column;
120
+ align-items: center;
121
+ gap: 1rem;
122
+ }
123
+
124
+ .stack {
125
+ display: flex;
126
+ width: fit-content;
127
+ max-width: 100%;
128
+ flex-direction: column;
129
+ gap: 1rem;
130
+ }
131
+
132
+ .grid {
133
+ display: flex;
134
+ flex-direction: column;
135
+ gap: 0.25rem;
136
+ user-select: none;
137
+ }
138
+
139
+ .week {
140
+ display: flex;
141
+ justify-content: flex-start;
142
+ gap: 0.125rem;
143
+ }
144
+
145
+ .cell {
146
+ min-width: 1ch;
147
+ text-align: center;
148
+ }
149
+
150
+ .meta {
151
+ display: flex;
152
+ flex-wrap: wrap;
153
+ align-items: baseline;
154
+ justify-content: space-between;
155
+ gap: 0.75rem;
156
+ }
157
+
158
+ .dates {
159
+ display: flex;
160
+ margin: 0;
161
+ gap: 0.75rem;
162
+ color: var(--graph-muted, oklch(0.62 0 0));
163
+ }
164
+
165
+ .pct {
166
+ margin: 0 0 0 auto;
167
+ text-align: right;
168
+ }
169
+
170
+ .legend {
171
+ display: flex;
172
+ flex-wrap: wrap;
173
+ justify-content: center;
174
+ margin: 0;
175
+ color: var(--graph-muted, oklch(0.62 0 0));
176
+ gap: 0.25rem 1rem;
177
+ }
178
+
179
+ .lg {
180
+ user-select: none;
181
+ }
182
+
183
+ .c-accent {
184
+ color: var(--graph-accent, oklch(0.78 0.17 155));
185
+ }
186
+
187
+ .c-accent2 {
188
+ color: var(--graph-accent-2, oklch(0.78 0.12 70));
189
+ }
190
+
191
+ .c-muted {
192
+ color: var(--graph-muted, oklch(0.62 0 0));
193
+ }
194
+
195
+ .c-frame {
196
+ color: var(--graph-frame, oklch(0.6 0 0 / 0.5));
197
+ }
198
+
199
+ .sr-only {
200
+ position: absolute;
201
+ width: 1px;
202
+ height: 1px;
203
+ padding: 0;
204
+ margin: -1px;
205
+ overflow: hidden;
206
+ clip-path: inset(50%);
207
+ white-space: nowrap;
208
+ border-width: 0;
209
+ }
210
+ </style>
@@ -0,0 +1,18 @@
1
+ import type { Glyphs } from '../frame/glyphs';
2
+ import type { GraphPalette } from '../frame/tone';
3
+ /** Rows of day-status glyphs: ok / degraded / down. */
4
+ export type UptimeStatus = 'ok' | 'degraded' | 'down' | 'empty';
5
+ export interface GraphUptimeProps {
6
+ title: string;
7
+ days: UptimeStatus[];
8
+ from?: string;
9
+ to?: string;
10
+ columns?: number;
11
+ glyphs?: Glyphs;
12
+ palette?: GraphPalette;
13
+ corner?: string;
14
+ class?: string;
15
+ }
16
+ declare const GraphUptime: import("svelte").Component<GraphUptimeProps, {}, "">;
17
+ type GraphUptime = ReturnType<typeof GraphUptime>;
18
+ export default GraphUptime;