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,194 @@
1
+ <script module lang="ts">
2
+ import type { Glyphs } from '../frame/glyphs';
3
+ import type { GraphPalette, ToneRole } from '../frame/tone';
4
+
5
+ export interface BarSeries {
6
+ label: string;
7
+ values: number[];
8
+ size?: 'sm' | 'lg';
9
+ }
10
+
11
+ export interface GraphBarsProps {
12
+ title: string;
13
+ from: BarSeries;
14
+ to: BarSeries;
15
+ processor?: string;
16
+ glyphs?: Glyphs;
17
+ palette?: GraphPalette;
18
+ corner?: string;
19
+ class?: string;
20
+ }
21
+ </script>
22
+
23
+ <script lang="ts">
24
+ import Graph from '../frame/Graph.svelte';
25
+ import GraphBody from '../frame/GraphBody.svelte';
26
+ import GraphArrow from '../frame/GraphArrow.svelte';
27
+ import { trackMarks } from '../frame/glyphs';
28
+ import { toneRole } from '../frame/tone';
29
+ import { reveal, stagger } from '../frame/motion';
30
+
31
+ let {
32
+ title,
33
+ from,
34
+ to,
35
+ processor,
36
+ glyphs,
37
+ palette,
38
+ corner,
39
+ class: className = ''
40
+ }: GraphBarsProps = $props();
41
+
42
+ const marks = $derived(trackMarks(glyphs));
43
+ const fromHeight = $derived(from.size === 'lg' ? 8 : 5);
44
+ const toHeight = $derived(to.size === 'lg' ? 8 : 5);
45
+ const fromRole = $derived(toneRole(palette, 'secondary'));
46
+ const spoken = $derived(
47
+ `${from.label} to ${to.label}${processor ? ` via ${processor}` : ''}`
48
+ );
49
+ </script>
50
+
51
+ {#snippet miniBars(values: number[], height: number, base: number, tone: 'accent' | 'muted')}
52
+ {@const onRole: ToneRole =
53
+ tone === 'accent' ? toneRole(palette, 'primary') : toneRole(palette, 'secondary')}
54
+ <div class="bars" aria-hidden="true">
55
+ {#each values as value, i (i)}
56
+ {@const max = Math.max(...values, 1)}
57
+ {@const level = Math.round((value / max) * (height - 1))}
58
+ <span class="col" use:reveal={{ delay: base + stagger(i, 30) }}>
59
+ {#each Array.from({ length: height }) as _, row (row)}
60
+ {@const fromBottom = height - 1 - row}
61
+ {@const on = fromBottom <= level}
62
+ <span
63
+ class="cell"
64
+ class:off={!on}
65
+ class:c-accent={on && onRole === 'accent'}
66
+ class:c-accent2={on && onRole === 'accent2'}
67
+ class:c-muted={on && onRole === 'muted'}>{on ? marks.fill : ' '}</span>
68
+ {/each}
69
+ </span>
70
+ {/each}
71
+ </div>
72
+ {/snippet}
73
+
74
+ <Graph {title} {corner} class={className}>
75
+ <GraphBody>
76
+ <div class="flow">
77
+ <div class="group">
78
+ {@render miniBars(from.values, fromHeight, 40, 'muted')}
79
+ <p
80
+ class="label"
81
+ class:c-muted={fromRole === 'muted'}
82
+ class:c-accent2={fromRole === 'accent2'}>{from.label}</p>
83
+ </div>
84
+
85
+ <div class="mid">
86
+ <GraphArrow />
87
+ {#if processor}
88
+ <span>{processor}</span>
89
+ {/if}
90
+ <GraphArrow />
91
+ </div>
92
+
93
+ <div class="group">
94
+ {@render miniBars(to.values, toHeight, 160, 'accent')}
95
+ <p class="label c-fg">{to.label}</p>
96
+ </div>
97
+ </div>
98
+ <span class="sr-only">{spoken}</span>
99
+ </GraphBody>
100
+ </Graph>
101
+
102
+ <style>
103
+ .flow {
104
+ display: flex;
105
+ flex-direction: column;
106
+ align-items: center;
107
+ gap: 2rem;
108
+ }
109
+
110
+ @media (min-width: 640px) {
111
+ .flow {
112
+ flex-direction: row;
113
+ align-items: flex-end;
114
+ justify-content: center;
115
+ gap: 2rem;
116
+ }
117
+ }
118
+
119
+ .group {
120
+ display: flex;
121
+ flex-direction: column;
122
+ align-items: center;
123
+ gap: 0.75rem;
124
+ }
125
+
126
+ .bars {
127
+ display: flex;
128
+ align-items: flex-end;
129
+ gap: 0.25rem;
130
+ }
131
+
132
+ .col {
133
+ display: flex;
134
+ flex-direction: column;
135
+ justify-content: flex-end;
136
+ width: 1ch;
137
+ }
138
+
139
+ .cell {
140
+ height: 1em;
141
+ width: 100%;
142
+ text-align: center;
143
+ }
144
+
145
+ .off {
146
+ color: transparent;
147
+ }
148
+
149
+ .mid {
150
+ display: flex;
151
+ align-items: center;
152
+ justify-content: center;
153
+ gap: 0.75rem;
154
+ color: var(--graph-muted, oklch(0.62 0 0));
155
+ }
156
+
157
+ @media (max-width: 639.98px) {
158
+ .mid {
159
+ transform: rotate(90deg);
160
+ }
161
+ }
162
+
163
+ .label {
164
+ margin: 0;
165
+ }
166
+
167
+ .c-accent {
168
+ color: var(--graph-accent, oklch(0.78 0.17 155));
169
+ }
170
+
171
+ .c-accent2 {
172
+ color: var(--graph-accent-2, oklch(0.78 0.12 70));
173
+ }
174
+
175
+ .c-fg {
176
+ color: var(--graph-foreground, oklch(0.93 0 0));
177
+ }
178
+
179
+ .c-muted {
180
+ color: var(--graph-muted, oklch(0.62 0 0));
181
+ }
182
+
183
+ .sr-only {
184
+ position: absolute;
185
+ width: 1px;
186
+ height: 1px;
187
+ padding: 0;
188
+ margin: -1px;
189
+ overflow: hidden;
190
+ clip-path: inset(50%);
191
+ white-space: nowrap;
192
+ border-width: 0;
193
+ }
194
+ </style>
@@ -0,0 +1,20 @@
1
+ import type { Glyphs } from '../frame/glyphs';
2
+ import type { GraphPalette } from '../frame/tone';
3
+ export interface BarSeries {
4
+ label: string;
5
+ values: number[];
6
+ size?: 'sm' | 'lg';
7
+ }
8
+ export interface GraphBarsProps {
9
+ title: string;
10
+ from: BarSeries;
11
+ to: BarSeries;
12
+ processor?: string;
13
+ glyphs?: Glyphs;
14
+ palette?: GraphPalette;
15
+ corner?: string;
16
+ class?: string;
17
+ }
18
+ declare const GraphBars: import("svelte").Component<GraphBarsProps, {}, "">;
19
+ type GraphBars = ReturnType<typeof GraphBars>;
20
+ export default GraphBars;
@@ -0,0 +1,208 @@
1
+ <script module lang="ts">
2
+ import type { Glyphs } from '../frame/glyphs';
3
+ import type { GraphPalette } from '../frame/tone';
4
+
5
+ /** One bullet row: actual value against an optional target. */
6
+ export interface BulletItem {
7
+ label: string;
8
+ value: number;
9
+ target?: number;
10
+ max?: number;
11
+ display?: string;
12
+ }
13
+
14
+ export interface GraphBulletProps {
15
+ title: string;
16
+ items: BulletItem[];
17
+ ticks?: number;
18
+ glyphs?: Glyphs;
19
+ palette?: GraphPalette;
20
+ corner?: string;
21
+ class?: string;
22
+ }
23
+ </script>
24
+
25
+ <script lang="ts">
26
+ import Graph from '../frame/Graph.svelte';
27
+ import GraphBody from '../frame/GraphBody.svelte';
28
+ import GraphTrack from '../frame/GraphTrack.svelte';
29
+ import GraphTick from '../frame/GraphTick.svelte';
30
+ import { trackMarks } from '../frame/glyphs';
31
+ import { toneRole, type ToneRole } from '../frame/tone';
32
+ import { reveal, stagger } from '../frame/motion';
33
+
34
+ let {
35
+ title,
36
+ items,
37
+ ticks = 20,
38
+ glyphs,
39
+ palette,
40
+ corner,
41
+ class: className = ''
42
+ }: GraphBulletProps = $props();
43
+
44
+ function formatItem(item: BulletItem) {
45
+ if (item.display) {
46
+ return item.display;
47
+ }
48
+
49
+ const value = item.value.toLocaleString('en-US', {
50
+ maximumFractionDigits: Number.isInteger(item.value) ? 0 : 1
51
+ });
52
+
53
+ if (item.target == null) {
54
+ return value;
55
+ }
56
+
57
+ const target = item.target.toLocaleString('en-US', {
58
+ maximumFractionDigits: Number.isInteger(item.target) ? 0 : 1
59
+ });
60
+
61
+ return `${value} / ${target}`;
62
+ }
63
+
64
+ const marks = $derived(trackMarks(glyphs, { empty: '-', rest: '=', fill: '=' }));
65
+
66
+ const rows = $derived.by(() =>
67
+ items.map((entry) => {
68
+ const peak = entry.max ?? Math.max(entry.value, entry.target ?? 0, 1);
69
+ const filled = Math.min(
70
+ ticks,
71
+ Math.round((Math.max(entry.value, 0) / peak) * ticks)
72
+ );
73
+ const mark =
74
+ entry.target == null
75
+ ? null
76
+ : Math.min(
77
+ ticks - 1,
78
+ Math.max(0, Math.round((Math.max(entry.target, 0) / peak) * ticks))
79
+ );
80
+
81
+ const cells = Array.from({ length: ticks }, (_, index) => {
82
+ const isMark = mark != null && index === mark;
83
+ const isFill = index < filled;
84
+ const role: ToneRole = isMark
85
+ ? toneRole(palette, 'secondary')
86
+ : isFill
87
+ ? mark != null && index > mark
88
+ ? toneRole(palette, 'secondary')
89
+ : toneRole(palette, 'primary')
90
+ : 'empty';
91
+
92
+ return {
93
+ glyph: isMark ? '|' : isFill ? marks.fill : marks.empty,
94
+ role
95
+ };
96
+ });
97
+
98
+ return {
99
+ label: entry.label,
100
+ spoken: `${entry.label} ${formatItem(entry)}`,
101
+ text: formatItem(entry),
102
+ cells
103
+ };
104
+ })
105
+ );
106
+ </script>
107
+
108
+ <Graph {title} {corner} class={className}>
109
+ <GraphBody>
110
+ <ul class="rows" role="list">
111
+ {#each rows as row, i (row.label)}
112
+ <li
113
+ class="row"
114
+ aria-label={row.spoken}
115
+ use:reveal={{ delay: stagger(i, 40), amount: 0.4 }}
116
+ >
117
+ <span class="label">{row.label}</span>
118
+ <span class="zone">
119
+ <span class="c-frame" aria-hidden="true">[</span>
120
+ <GraphTrack>
121
+ {#each row.cells as cell}
122
+ <GraphTick>
123
+ <span
124
+ class="g"
125
+ class:c-accent={cell.role === 'accent'}
126
+ class:c-accent2={cell.role === 'accent2'}
127
+ class:c-accent3={cell.role === 'accent3'}
128
+ class:c-muted={cell.role === 'muted'}
129
+ class:c-frame={cell.role === 'empty'}
130
+ >
131
+ {cell.glyph}
132
+ </span>
133
+ </GraphTick>
134
+ {/each}
135
+ </GraphTrack>
136
+ <span class="c-frame" aria-hidden="true">]</span>
137
+ </span>
138
+ <span class="num muted">{row.text}</span>
139
+ </li>
140
+ {/each}
141
+ </ul>
142
+ </GraphBody>
143
+ </Graph>
144
+
145
+ <style>
146
+ .rows {
147
+ margin: 0;
148
+ padding: 0;
149
+ list-style: none;
150
+ width: 100%;
151
+ display: flex;
152
+ flex-direction: column;
153
+ gap: 0.5rem;
154
+ }
155
+
156
+ .row {
157
+ display: grid;
158
+ grid-template-columns: 7rem minmax(0, 1fr) 7rem;
159
+ column-gap: 1rem;
160
+ align-items: center;
161
+ }
162
+
163
+ .label {
164
+ min-width: 0;
165
+ overflow: hidden;
166
+ text-overflow: ellipsis;
167
+ white-space: nowrap;
168
+ color: var(--graph-foreground, oklch(0.93 0 0));
169
+ }
170
+
171
+ .zone {
172
+ display: flex;
173
+ align-items: center;
174
+ min-width: 0;
175
+ }
176
+
177
+ .g {
178
+ display: block;
179
+ }
180
+
181
+ .num {
182
+ text-align: right;
183
+ }
184
+
185
+ .muted {
186
+ color: var(--graph-muted, oklch(0.62 0 0));
187
+ }
188
+
189
+ .c-accent {
190
+ color: var(--graph-accent, oklch(0.78 0.17 155));
191
+ }
192
+
193
+ .c-accent2 {
194
+ color: var(--graph-accent-2, oklch(0.78 0.12 70));
195
+ }
196
+
197
+ .c-accent3 {
198
+ color: var(--graph-accent-3, oklch(0.75 0.1 200));
199
+ }
200
+
201
+ .c-muted {
202
+ color: var(--graph-muted, oklch(0.62 0 0));
203
+ }
204
+
205
+ .c-frame {
206
+ color: var(--graph-frame, oklch(0.6 0 0 / 0.5));
207
+ }
208
+ </style>
@@ -0,0 +1,22 @@
1
+ import type { Glyphs } from '../frame/glyphs';
2
+ import type { GraphPalette } from '../frame/tone';
3
+ /** One bullet row: actual value against an optional target. */
4
+ export interface BulletItem {
5
+ label: string;
6
+ value: number;
7
+ target?: number;
8
+ max?: number;
9
+ display?: string;
10
+ }
11
+ export interface GraphBulletProps {
12
+ title: string;
13
+ items: BulletItem[];
14
+ ticks?: number;
15
+ glyphs?: Glyphs;
16
+ palette?: GraphPalette;
17
+ corner?: string;
18
+ class?: string;
19
+ }
20
+ declare const GraphBullet: import("svelte").Component<GraphBulletProps, {}, "">;
21
+ type GraphBullet = ReturnType<typeof GraphBullet>;
22
+ export default GraphBullet;
@@ -0,0 +1,203 @@
1
+ <script module lang="ts">
2
+ import type { GraphPalette } from '../frame/tone';
3
+
4
+ /** One month grid: weekday header, marked-day accent, optional today. */
5
+ export interface CalendarMark {
6
+ day: number;
7
+ accent?: boolean;
8
+ }
9
+
10
+ export interface GraphCalendarProps {
11
+ title?: string;
12
+ year: number;
13
+ month: number;
14
+ weekStartsOn?: 0 | 1;
15
+ marks?: CalendarMark[] | number[];
16
+ today?: number;
17
+ palette?: GraphPalette;
18
+ corner?: string;
19
+ class?: string;
20
+ }
21
+ </script>
22
+
23
+ <script lang="ts">
24
+ import Graph from '../frame/Graph.svelte';
25
+ import GraphBody from '../frame/GraphBody.svelte';
26
+ import { isMonoPalette, toneRole } from '../frame/tone';
27
+ import { reveal, stagger } from '../frame/motion';
28
+
29
+ const WEEKDAYS_SUN = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
30
+ const WEEKDAYS_MON = ['M', 'T', 'W', 'T', 'F', 'S', 'S'];
31
+ const MONTHS = [
32
+ 'January',
33
+ 'February',
34
+ 'March',
35
+ 'April',
36
+ 'May',
37
+ 'June',
38
+ 'July',
39
+ 'August',
40
+ 'September',
41
+ 'October',
42
+ 'November',
43
+ 'December'
44
+ ];
45
+
46
+ let {
47
+ title,
48
+ year,
49
+ month,
50
+ weekStartsOn = 1,
51
+ marks,
52
+ today,
53
+ palette,
54
+ corner,
55
+ class: className = ''
56
+ }: GraphCalendarProps = $props();
57
+
58
+ function monthLength(year: number, monthIndex: number) {
59
+ return new Date(Date.UTC(year, monthIndex + 1, 0)).getUTCDate();
60
+ }
61
+
62
+ function leadingBlanks(year: number, monthIndex: number, weekStartsOn: 0 | 1) {
63
+ const weekday = new Date(Date.UTC(year, monthIndex, 1)).getUTCDay();
64
+ return (weekday - weekStartsOn + 7) % 7;
65
+ }
66
+
67
+ function markSet(list: GraphCalendarProps['marks']) {
68
+ const map = new Map<number, boolean>();
69
+
70
+ if (!list) {
71
+ return map;
72
+ }
73
+
74
+ for (const mark of list) {
75
+ if (typeof mark === 'number') {
76
+ map.set(mark, true);
77
+ continue;
78
+ }
79
+
80
+ map.set(mark.day, mark.accent ?? true);
81
+ }
82
+
83
+ return map;
84
+ }
85
+
86
+ const todayRole = $derived(toneRole(palette, isMonoPalette(palette) ? 'primary' : 'secondary'));
87
+
88
+ const view = $derived.by(() => {
89
+ const monthIndex = month - 1;
90
+ const days = monthLength(year, monthIndex);
91
+ const pad = leadingBlanks(year, monthIndex, weekStartsOn);
92
+ const highlighted = markSet(marks);
93
+ const headers = weekStartsOn === 1 ? WEEKDAYS_MON : WEEKDAYS_SUN;
94
+ const trailing = (7 - ((pad + days) % 7)) % 7;
95
+ const caption = title ?? `${MONTHS[monthIndex]} ${year}`;
96
+ const grid: (number | null)[] = [
97
+ ...Array.from({ length: pad }, () => null),
98
+ ...Array.from({ length: days }, (_, index) => index + 1),
99
+ ...Array.from({ length: trailing }, () => null)
100
+ ];
101
+ const weeks: (number | null)[][] = [];
102
+
103
+ for (let index = 0; index < grid.length; index += 7) {
104
+ weeks.push(grid.slice(index, index + 7));
105
+ }
106
+
107
+ return { monthIndex, headers, weeks, highlighted, caption };
108
+ });
109
+ </script>
110
+
111
+ <Graph title={view.caption} {corner} class={className}>
112
+ <GraphBody>
113
+ <div class="cal">
114
+ <div class="week head" aria-hidden="true">
115
+ {#each view.headers as header, index (`${header}-${index}`)}
116
+ <span class="day muted">{header}</span>
117
+ {/each}
118
+ </div>
119
+ <div class="weeks" aria-hidden="true">
120
+ {#each view.weeks as week, weekIndex (weekIndex)}
121
+ <div class="week" use:reveal={{ delay: stagger(weekIndex, 40), amount: 0.4 }}>
122
+ {#each week as day, dayIndex (`${weekIndex}-${dayIndex}`)}
123
+ {@const inMonth = day != null}
124
+ {@const accent = day != null && view.highlighted.get(day) === true}
125
+ {@const isToday = day != null && today === day}
126
+ <span
127
+ class="day"
128
+ class:ghost={!inMonth}
129
+ class:c-fg={inMonth && !accent && !isToday}
130
+ class:c-accent={accent || (isToday && !accent && todayRole === 'accent')}
131
+ class:c-accent2={isToday && !accent && todayRole === 'accent2'}
132
+ >
133
+ {inMonth ? (isToday ? `[${day}]` : day) : '\u00a0'}
134
+ </span>
135
+ {/each}
136
+ </div>
137
+ {/each}
138
+ </div>
139
+ <span class="sr-only">
140
+ {MONTHS[view.monthIndex]} {year}{today ? `, today ${today}` : ''}{view.highlighted.size > 0
141
+ ? `, marked ${[...view.highlighted.keys()].join(', ')}`
142
+ : ''}
143
+ </span>
144
+ </div>
145
+ </GraphBody>
146
+ </Graph>
147
+
148
+ <style>
149
+ .cal {
150
+ display: flex;
151
+ flex-direction: column;
152
+ gap: 0.75rem;
153
+ }
154
+
155
+ .weeks {
156
+ display: flex;
157
+ flex-direction: column;
158
+ gap: 0.25rem;
159
+ }
160
+
161
+ .week {
162
+ display: grid;
163
+ grid-template-columns: repeat(7, 1fr);
164
+ justify-items: center;
165
+ }
166
+
167
+ .day {
168
+ width: 4ch;
169
+ text-align: center;
170
+ }
171
+
172
+ .muted {
173
+ color: var(--graph-muted, oklch(0.62 0 0));
174
+ }
175
+
176
+ .ghost {
177
+ color: transparent;
178
+ }
179
+
180
+ .c-accent {
181
+ color: var(--graph-accent, oklch(0.78 0.17 155));
182
+ }
183
+
184
+ .c-accent2 {
185
+ color: var(--graph-accent-2, oklch(0.78 0.12 70));
186
+ }
187
+
188
+ .c-fg {
189
+ color: var(--graph-foreground, oklch(0.93 0 0));
190
+ }
191
+
192
+ .sr-only {
193
+ position: absolute;
194
+ width: 1px;
195
+ height: 1px;
196
+ padding: 0;
197
+ margin: -1px;
198
+ overflow: hidden;
199
+ clip-path: inset(50%);
200
+ white-space: nowrap;
201
+ border-width: 0;
202
+ }
203
+ </style>
@@ -0,0 +1,20 @@
1
+ import type { GraphPalette } from '../frame/tone';
2
+ /** One month grid: weekday header, marked-day accent, optional today. */
3
+ export interface CalendarMark {
4
+ day: number;
5
+ accent?: boolean;
6
+ }
7
+ export interface GraphCalendarProps {
8
+ title?: string;
9
+ year: number;
10
+ month: number;
11
+ weekStartsOn?: 0 | 1;
12
+ marks?: CalendarMark[] | number[];
13
+ today?: number;
14
+ palette?: GraphPalette;
15
+ corner?: string;
16
+ class?: string;
17
+ }
18
+ declare const GraphCalendar: import("svelte").Component<GraphCalendarProps, {}, "">;
19
+ type GraphCalendar = ReturnType<typeof GraphCalendar>;
20
+ export default GraphCalendar;