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,181 @@
1
+ <script module lang="ts">
2
+ import type { Glyphs } from '../frame/glyphs';
3
+ import type { GraphPalette } from '../frame/tone';
4
+
5
+ /** One labeled grid of cells; a value of `1` is filled, anything else is empty. */
6
+ export interface CellGrid {
7
+ label: string;
8
+ cells: number[][];
9
+ }
10
+
11
+ export interface GraphCellsProps {
12
+ title: string;
13
+ items: CellGrid[];
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 { trackMarks } from '../frame/glyphs';
25
+ import { isMonoPalette, seriesRole } from '../frame/tone';
26
+ import { reveal, stagger } from '../frame/motion';
27
+
28
+ let {
29
+ title,
30
+ items,
31
+ glyphs,
32
+ palette,
33
+ corner,
34
+ class: className = ''
35
+ }: GraphCellsProps = $props();
36
+
37
+ const marks = $derived(trackMarks(glyphs, { empty: '·', rest: '░', fill: '█' }));
38
+
39
+ const summary = $derived.by(() => {
40
+ let filled = 0;
41
+ let total = 0;
42
+ for (const item of items) {
43
+ for (const row of item.cells) {
44
+ for (const cell of row) {
45
+ total += 1;
46
+ if (cell === 1) {
47
+ filled += 1;
48
+ }
49
+ }
50
+ }
51
+ }
52
+ return `${filled} of ${total} cells filled`;
53
+ });
54
+ </script>
55
+
56
+ <Graph {title} {corner} class={className}>
57
+ <GraphBody>
58
+ <div class="wrap">
59
+ <div class="flow">
60
+ {#each items as item, itemIndex (item.label)}
61
+ {@const labelRole = isMonoPalette(palette) ? 'muted' : seriesRole(palette, itemIndex)}
62
+ <div class="group">
63
+ <div class="grid" aria-hidden="true">
64
+ {#each item.cells as row, rowIndex (rowIndex)}
65
+ <div class="row" use:reveal={{ delay: stagger(itemIndex * 8 + rowIndex, 40) }}>
66
+ {#each row as cell, cellIndex (cellIndex)}
67
+ {@const filled = cell === 1}
68
+ {@const role = filled
69
+ ? isMonoPalette(palette)
70
+ ? 'accent'
71
+ : seriesRole(palette, itemIndex)
72
+ : 'frame'}
73
+ <span
74
+ class="cell"
75
+ class:c-accent={role === 'accent'}
76
+ class:c-accent2={role === 'accent2'}
77
+ class:c-accent3={role === 'accent3'}
78
+ class:c-fg={role === 'foreground'}
79
+ class:c-frame={role === 'frame'}>{filled ? marks.fill : marks.empty}</span>
80
+ {/each}
81
+ </div>
82
+ {/each}
83
+ </div>
84
+ <p
85
+ class="label"
86
+ class:c-muted={labelRole === 'muted'}
87
+ class:c-accent={labelRole === 'accent'}
88
+ class:c-accent2={labelRole === 'accent2'}
89
+ class:c-accent3={labelRole === 'accent3'}>{item.label}</p>
90
+ </div>
91
+ {/each}
92
+ </div>
93
+ </div>
94
+ <span class="sr-only">{summary}</span>
95
+ </GraphBody>
96
+ </Graph>
97
+
98
+ <style>
99
+ .wrap {
100
+ container-type: inline-size;
101
+ }
102
+
103
+ .flow {
104
+ display: flex;
105
+ flex-direction: column;
106
+ align-items: center;
107
+ gap: 2.5rem;
108
+ }
109
+
110
+ @container (min-width: 28rem) {
111
+ .flow {
112
+ flex-direction: row;
113
+ justify-content: center;
114
+ gap: 3rem;
115
+ }
116
+ }
117
+
118
+ .group {
119
+ display: flex;
120
+ flex-direction: column;
121
+ align-items: center;
122
+ gap: 1rem;
123
+ }
124
+
125
+ .grid {
126
+ display: flex;
127
+ flex-direction: column;
128
+ gap: 0.25rem;
129
+ }
130
+
131
+ .row {
132
+ display: flex;
133
+ gap: 0.25rem;
134
+ }
135
+
136
+ .cell {
137
+ width: 1ch;
138
+ text-align: center;
139
+ user-select: none;
140
+ }
141
+
142
+ .label {
143
+ margin: 0;
144
+ }
145
+
146
+ .c-accent {
147
+ color: var(--graph-accent, oklch(0.78 0.17 155));
148
+ }
149
+
150
+ .c-accent2 {
151
+ color: var(--graph-accent-2, oklch(0.78 0.12 70));
152
+ }
153
+
154
+ .c-accent3 {
155
+ color: var(--graph-accent-3, oklch(0.75 0.1 200));
156
+ }
157
+
158
+ .c-fg {
159
+ color: var(--graph-foreground, oklch(0.93 0 0));
160
+ }
161
+
162
+ .c-frame {
163
+ color: var(--graph-frame, oklch(0.6 0 0 / 0.5));
164
+ }
165
+
166
+ .c-muted {
167
+ color: var(--graph-muted, oklch(0.62 0 0));
168
+ }
169
+
170
+ .sr-only {
171
+ position: absolute;
172
+ width: 1px;
173
+ height: 1px;
174
+ padding: 0;
175
+ margin: -1px;
176
+ overflow: hidden;
177
+ clip-path: inset(50%);
178
+ white-space: nowrap;
179
+ border-width: 0;
180
+ }
181
+ </style>
@@ -0,0 +1,18 @@
1
+ import type { Glyphs } from '../frame/glyphs';
2
+ import type { GraphPalette } from '../frame/tone';
3
+ /** One labeled grid of cells; a value of `1` is filled, anything else is empty. */
4
+ export interface CellGrid {
5
+ label: string;
6
+ cells: number[][];
7
+ }
8
+ export interface GraphCellsProps {
9
+ title: string;
10
+ items: CellGrid[];
11
+ glyphs?: Glyphs;
12
+ palette?: GraphPalette;
13
+ corner?: string;
14
+ class?: string;
15
+ }
16
+ declare const GraphCells: import("svelte").Component<GraphCellsProps, {}, "">;
17
+ type GraphCells = ReturnType<typeof GraphCells>;
18
+ export default GraphCells;
@@ -0,0 +1,192 @@
1
+ <script module lang="ts">
2
+ import type { GraphPalette } from '../frame/tone';
3
+
4
+ export type CompareCell = string | boolean;
5
+
6
+ export interface CompareRow {
7
+ label: string;
8
+ values: CompareCell[];
9
+ }
10
+
11
+ export interface GraphCompareProps {
12
+ title: string;
13
+ columns: string[];
14
+ rows: CompareRow[];
15
+ accent?: string;
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 { isMonoPalette, seriesRole } from '../frame/tone';
27
+
28
+ let {
29
+ title,
30
+ columns,
31
+ rows,
32
+ accent,
33
+ palette,
34
+ corner,
35
+ class: className = ''
36
+ }: GraphCompareProps = $props();
37
+
38
+ const template = $derived(`minmax(7rem, 1fr) repeat(${columns.length}, minmax(4.5rem, 7rem))`);
39
+ const summary = $derived(`${rows.length} features compared across ${columns.length} columns`);
40
+
41
+ function cellText(value: CompareCell): string {
42
+ if (typeof value === 'boolean') {
43
+ return value ? '✓' : '–';
44
+ }
45
+
46
+ return value;
47
+ }
48
+ </script>
49
+
50
+ <Graph {title} {corner} class={className}>
51
+ <GraphBody>
52
+ <div class="scroll">
53
+ <div class="sheet">
54
+ <div class="head" style:--cols={template}>
55
+ <span></span>
56
+ {#each columns as column, index (column)}
57
+ {@const focused = !!accent && column === accent}
58
+ {@const role = isMonoPalette(palette)
59
+ ? focused
60
+ ? 'accent'
61
+ : 'muted'
62
+ : seriesRole(palette, index)}
63
+ <span
64
+ class="right"
65
+ class:c-accent={role === 'accent'}
66
+ class:c-accent2={role === 'accent2'}
67
+ class:c-accent3={role === 'accent3'}
68
+ class:c-muted={role === 'muted'}>{column}</span>
69
+ {/each}
70
+ </div>
71
+ <ul class="rows" role="list">
72
+ {#each rows as row, r (row.label)}
73
+ <li
74
+ class="line"
75
+ style:--cols={template}
76
+ use:reveal={{ delay: stagger(r, 40), amount: 0.4 }}
77
+ >
78
+ <span class="label">{row.label}</span>
79
+ {#each columns as column, index (index)}
80
+ {@const value = row.values[index]}
81
+ {@const mark = typeof value === 'boolean'}
82
+ {@const on = value === true}
83
+ {@const focused = !!accent && column === accent}
84
+ {@const dim = !!accent && !focused}
85
+ {@const mono = isMonoPalette(palette)}
86
+ {@const series = on && !mono ? seriesRole(palette, index) : null}
87
+ {@const faded = dim && !on && mono}
88
+ <span
89
+ class="right"
90
+ class:dim={faded}
91
+ class:c-accent={(on && mono && (focused || !accent)) || series === 'accent'}
92
+ class:c-accent2={series === 'accent2'}
93
+ class:c-accent3={series === 'accent3'}
94
+ class:c-fg={(on && mono && dim) || (!mark && focused)}
95
+ class:c-frame={mark && !on}
96
+ class:c-muted={!mark && dim}>{value == null ? '' : cellText(value)}</span>
97
+ {/each}
98
+ </li>
99
+ {/each}
100
+ </ul>
101
+ </div>
102
+ </div>
103
+ <span class="sr-only">{summary}</span>
104
+ </GraphBody>
105
+ </Graph>
106
+
107
+ <style>
108
+ .scroll {
109
+ overflow-x: auto;
110
+ }
111
+
112
+ .sheet {
113
+ display: flex;
114
+ flex-direction: column;
115
+ gap: 0.75rem;
116
+ min-width: 32rem;
117
+ }
118
+
119
+ .head,
120
+ .line {
121
+ display: grid;
122
+ grid-template-columns: var(--cols);
123
+ column-gap: 1rem;
124
+ }
125
+
126
+ .head {
127
+ align-items: end;
128
+ }
129
+
130
+ .line {
131
+ align-items: baseline;
132
+ }
133
+
134
+ .rows {
135
+ display: flex;
136
+ flex-direction: column;
137
+ gap: 0.5rem;
138
+ margin: 0;
139
+ padding: 0;
140
+ list-style: none;
141
+ }
142
+
143
+ .label {
144
+ overflow: hidden;
145
+ text-overflow: ellipsis;
146
+ white-space: nowrap;
147
+ }
148
+
149
+ .right {
150
+ text-align: right;
151
+ }
152
+
153
+ .dim {
154
+ opacity: 0.4;
155
+ }
156
+
157
+ .c-accent {
158
+ color: var(--graph-accent, oklch(0.78 0.17 155));
159
+ }
160
+
161
+ .c-accent2 {
162
+ color: var(--graph-accent-2, oklch(0.78 0.12 70));
163
+ }
164
+
165
+ .c-accent3 {
166
+ color: var(--graph-accent-3, oklch(0.75 0.1 200));
167
+ }
168
+
169
+ .c-fg {
170
+ color: var(--graph-foreground, oklch(0.93 0 0));
171
+ }
172
+
173
+ .c-frame {
174
+ color: var(--graph-frame, oklch(0.6 0 0 / 0.5));
175
+ }
176
+
177
+ .c-muted {
178
+ color: var(--graph-muted, oklch(0.62 0 0));
179
+ }
180
+
181
+ .sr-only {
182
+ position: absolute;
183
+ width: 1px;
184
+ height: 1px;
185
+ padding: 0;
186
+ margin: -1px;
187
+ overflow: hidden;
188
+ clip-path: inset(50%);
189
+ white-space: nowrap;
190
+ border-width: 0;
191
+ }
192
+ </style>
@@ -0,0 +1,18 @@
1
+ import type { GraphPalette } from '../frame/tone';
2
+ export type CompareCell = string | boolean;
3
+ export interface CompareRow {
4
+ label: string;
5
+ values: CompareCell[];
6
+ }
7
+ export interface GraphCompareProps {
8
+ title: string;
9
+ columns: string[];
10
+ rows: CompareRow[];
11
+ accent?: string;
12
+ palette?: GraphPalette;
13
+ corner?: string;
14
+ class?: string;
15
+ }
16
+ declare const GraphCompare: import("svelte").Component<GraphCompareProps, {}, "">;
17
+ type GraphCompare = ReturnType<typeof GraphCompare>;
18
+ export default GraphCompare;
@@ -0,0 +1,96 @@
1
+ <script module lang="ts">
2
+ import type { GraphPalette } from '../frame/tone';
3
+
4
+ /** Time left until a date. */
5
+ export interface GraphCountdownProps {
6
+ title: string;
7
+ to: Date | number | string;
8
+ done?: string;
9
+ caption?: string;
10
+ palette?: GraphPalette;
11
+ corner?: string;
12
+ class?: string;
13
+ }
14
+ </script>
15
+
16
+ <script lang="ts">
17
+ import Graph from '../frame/Graph.svelte';
18
+ import GraphBody from '../frame/GraphBody.svelte';
19
+ import { formatHms, graphNow, parseInstant } from '../frame/clock';
20
+ import { reveal } from '../frame/motion';
21
+
22
+ let {
23
+ title,
24
+ to,
25
+ done = 'done',
26
+ caption,
27
+ palette,
28
+ corner,
29
+ class: className = ''
30
+ }: GraphCountdownProps = $props();
31
+
32
+ const time = graphNow();
33
+ const target = $derived(parseInstant(to));
34
+
35
+ const view = $derived.by(() => {
36
+ const remaining = $time == null || !Number.isFinite(target) ? null : target - $time;
37
+ const finished = remaining != null && remaining <= 0;
38
+ const value = remaining == null ? '00:00:00' : finished ? done : formatHms(remaining);
39
+ return { value, finished };
40
+ });
41
+ </script>
42
+
43
+ <Graph {title} {corner} class={className}>
44
+ <GraphBody>
45
+ <div class="countdown" use:reveal={{ amount: 0.5 }}>
46
+ <p class="value" class:c-accent={!view.finished} class:muted={view.finished}>
47
+ {view.value}
48
+ </p>
49
+ {#if caption}
50
+ <p class="muted">{caption}</p>
51
+ {/if}
52
+ </div>
53
+ <span class="sr-only">{view.finished ? done : `remaining ${view.value}`}</span>
54
+ </GraphBody>
55
+ </Graph>
56
+
57
+ <style>
58
+ .countdown {
59
+ display: flex;
60
+ flex-direction: column;
61
+ gap: 0.5rem;
62
+ }
63
+
64
+ .value {
65
+ margin: 0;
66
+ font-size: 1.875rem;
67
+ line-height: 1.2;
68
+ letter-spacing: -0.025em;
69
+ }
70
+
71
+ @media (min-width: 640px) {
72
+ .value {
73
+ font-size: 2.25rem;
74
+ }
75
+ }
76
+
77
+ .muted {
78
+ color: var(--graph-muted, oklch(0.62 0 0));
79
+ }
80
+
81
+ .c-accent {
82
+ color: var(--graph-accent, oklch(0.78 0.17 155));
83
+ }
84
+
85
+ .sr-only {
86
+ position: absolute;
87
+ width: 1px;
88
+ height: 1px;
89
+ padding: 0;
90
+ margin: -1px;
91
+ overflow: hidden;
92
+ clip-path: inset(50%);
93
+ white-space: nowrap;
94
+ border-width: 0;
95
+ }
96
+ </style>
@@ -0,0 +1,14 @@
1
+ import type { GraphPalette } from '../frame/tone';
2
+ /** Time left until a date. */
3
+ export interface GraphCountdownProps {
4
+ title: string;
5
+ to: Date | number | string;
6
+ done?: string;
7
+ caption?: string;
8
+ palette?: GraphPalette;
9
+ corner?: string;
10
+ class?: string;
11
+ }
12
+ declare const GraphCountdown: import("svelte").Component<GraphCountdownProps, {}, "">;
13
+ type GraphCountdown = ReturnType<typeof GraphCountdown>;
14
+ export default GraphCountdown;
@@ -0,0 +1,181 @@
1
+ <script module lang="ts">
2
+ import type { GraphPalette, ToneRole } from '../frame/tone';
3
+
4
+ export type DiffSign = 'add' | 'remove' | 'keep';
5
+
6
+ export interface DiffRow {
7
+ label: string;
8
+ value: string;
9
+ sign?: DiffSign;
10
+ }
11
+
12
+ export interface GraphDiffProps {
13
+ title: string;
14
+ rows: DiffRow[];
15
+ footer?: DiffRow;
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 GraphRule from '../frame/GraphRule.svelte';
26
+ import { reveal, stagger } from '../frame/motion';
27
+ import { toneRole } from '../frame/tone';
28
+
29
+ let {
30
+ title,
31
+ rows,
32
+ footer,
33
+ palette,
34
+ corner,
35
+ class: className = ''
36
+ }: GraphDiffProps = $props();
37
+
38
+ const signGlyph: Record<DiffSign, string> = {
39
+ add: '+',
40
+ remove: '-',
41
+ keep: ' '
42
+ };
43
+
44
+ function toneOf(sign: DiffSign): ToneRole {
45
+ if (sign === 'add') {
46
+ return toneRole(palette, 'primary');
47
+ }
48
+
49
+ if (sign === 'remove') {
50
+ return toneRole(palette, 'secondary');
51
+ }
52
+
53
+ return 'foreground';
54
+ }
55
+
56
+ const summary = $derived.by(() => {
57
+ let add = 0;
58
+ let remove = 0;
59
+ let keep = 0;
60
+ for (const row of footer ? [...rows, footer] : rows) {
61
+ const sign = row.sign ?? 'keep';
62
+ if (sign === 'add') {
63
+ add += 1;
64
+ } else if (sign === 'remove') {
65
+ remove += 1;
66
+ } else {
67
+ keep += 1;
68
+ }
69
+ }
70
+ return `${add} added, ${remove} removed, ${keep} unchanged`;
71
+ });
72
+ </script>
73
+
74
+ {#snippet diffLine(row: DiffRow, delay: number)}
75
+ {@const sign = row.sign ?? 'keep'}
76
+ {@const tone = toneOf(sign)}
77
+ {@const mark = sign === 'keep' ? 'empty' : tone}
78
+ <div class="line" use:reveal={{ delay, amount: 0.4 }}>
79
+ <span
80
+ aria-hidden="true"
81
+ class="mark"
82
+ class:c-frame={mark === 'empty'}
83
+ class:c-accent={mark === 'accent'}
84
+ class:c-accent2={mark === 'accent2'}
85
+ class:c-muted={mark === 'muted'}>{signGlyph[sign]}</span>
86
+ <span
87
+ class="label"
88
+ class:c-accent={tone === 'accent'}
89
+ class:c-accent2={tone === 'accent2'}
90
+ class:c-muted={tone === 'muted'}
91
+ class:c-fg={tone === 'foreground'}>{row.label}</span>
92
+ <span
93
+ class="value"
94
+ class:c-accent={tone === 'accent'}
95
+ class:c-accent2={tone === 'accent2'}
96
+ class:c-muted={tone === 'muted'}
97
+ class:c-fg={tone === 'foreground'}>{row.value}</span>
98
+ </div>
99
+ {/snippet}
100
+
101
+ <Graph {title} {corner} class={className}>
102
+ <GraphBody>
103
+ <div class="stack">
104
+ <ul class="lines" role="list">
105
+ {#each rows as row, i (row.label)}
106
+ <li>{@render diffLine(row, stagger(i, 40))}</li>
107
+ {/each}
108
+ </ul>
109
+ {#if footer}
110
+ <GraphRule />
111
+ {@render diffLine(footer, 0)}
112
+ {/if}
113
+ </div>
114
+ <span class="sr-only">{summary}</span>
115
+ </GraphBody>
116
+ </Graph>
117
+
118
+ <style>
119
+ .stack {
120
+ display: flex;
121
+ flex-direction: column;
122
+ gap: 0.75rem;
123
+ }
124
+
125
+ .lines {
126
+ display: flex;
127
+ flex-direction: column;
128
+ gap: 0.5rem;
129
+ margin: 0;
130
+ padding: 0;
131
+ list-style: none;
132
+ }
133
+
134
+ .line {
135
+ display: grid;
136
+ grid-template-columns: 1.25rem minmax(0, 1fr) 8ch;
137
+ align-items: baseline;
138
+ column-gap: 0.75rem;
139
+ }
140
+
141
+ .mark {
142
+ text-align: center;
143
+ user-select: none;
144
+ }
145
+
146
+ .value {
147
+ text-align: right;
148
+ }
149
+
150
+ .c-accent {
151
+ color: var(--graph-accent, oklch(0.78 0.17 155));
152
+ }
153
+
154
+ .c-accent2 {
155
+ color: var(--graph-accent-2, oklch(0.78 0.12 70));
156
+ }
157
+
158
+ .c-fg {
159
+ color: var(--graph-foreground, oklch(0.93 0 0));
160
+ }
161
+
162
+ .c-frame {
163
+ color: var(--graph-frame, oklch(0.6 0 0 / 0.5));
164
+ }
165
+
166
+ .c-muted {
167
+ color: var(--graph-muted, oklch(0.62 0 0));
168
+ }
169
+
170
+ .sr-only {
171
+ position: absolute;
172
+ width: 1px;
173
+ height: 1px;
174
+ padding: 0;
175
+ margin: -1px;
176
+ overflow: hidden;
177
+ clip-path: inset(50%);
178
+ white-space: nowrap;
179
+ border-width: 0;
180
+ }
181
+ </style>