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,47 @@
1
+ import './motion.css';
2
+ export const EASE_OUT_CUBIC = 'cubic-bezier(0.215, 0.61, 0.355, 1)';
3
+ export const DIM_OPACITY = 0.4;
4
+ function prefersReducedMotion() {
5
+ return (typeof window !== 'undefined' &&
6
+ typeof window.matchMedia === 'function' &&
7
+ window.matchMedia('(prefers-reduced-motion: reduce)').matches);
8
+ }
9
+ /**
10
+ * Svelte action: fade-and-rise when the element enters the viewport.
11
+ * Stagger rows, weeks, or lists — never hundreds of individual cells.
12
+ *
13
+ * <div use:reveal={{ delay: stagger(i, 40) }}>
14
+ */
15
+ export function reveal(node, options = {}) {
16
+ const { delay = 0, amount = 0.25, y = 8, once = true } = options;
17
+ if (prefersReducedMotion() || typeof IntersectionObserver === 'undefined') {
18
+ return { destroy() { } };
19
+ }
20
+ node.classList.add('fg-motion');
21
+ node.style.setProperty('--fg-delay', `${delay}ms`);
22
+ if (y !== 8) {
23
+ node.style.setProperty('--fg-y', `${y}px`);
24
+ }
25
+ const observer = new IntersectionObserver((entries) => {
26
+ for (const entry of entries) {
27
+ if (entry.isIntersecting) {
28
+ node.classList.add('is-revealed');
29
+ if (once)
30
+ observer.disconnect();
31
+ }
32
+ else if (!once) {
33
+ node.classList.remove('is-revealed');
34
+ }
35
+ }
36
+ }, { threshold: amount });
37
+ observer.observe(node);
38
+ return {
39
+ destroy() {
40
+ observer.disconnect();
41
+ }
42
+ };
43
+ }
44
+ /** Stagger delay for index `i`, capped at 280ms. */
45
+ export function stagger(index, step = 40) {
46
+ return Math.min(index * step, 280);
47
+ }
@@ -0,0 +1,11 @@
1
+ export type GraphPalette = 'mono' | 'duo' | 'multi';
2
+ export type ToneRole = 'empty' | 'muted' | 'foreground' | 'accent' | 'accent2' | 'accent3';
3
+ export declare function isMonoPalette(palette?: GraphPalette): palette is "mono" | undefined;
4
+ /** Intensity level (0–4) → color role. Mirrors intensityClass from the reference. */
5
+ export declare function intensityRole(level: number, palette?: GraphPalette): ToneRole;
6
+ /** Series index → color role. Mirrors seriesClass from the reference. */
7
+ export declare function seriesRole(palette: GraphPalette | undefined, index: number): ToneRole;
8
+ /** Whether a series should recede (mono palette, not highlighted). */
9
+ export declare function isDim(palette: GraphPalette | undefined, highlighted: boolean): boolean;
10
+ /** Semantic role → color role. Mirrors toneClass from the reference. */
11
+ export declare function toneRole(palette: GraphPalette | undefined, role: 'primary' | 'secondary' | 'idle' | 'empty'): ToneRole;
@@ -0,0 +1,64 @@
1
+ /*
2
+ * Color-role logic, ported from markdown-graphs' series/intensity classes.
3
+ * Roles map to scoped classes inside each graph component:
4
+ * .c-accent / .c-accent2 / .c-accent3 / .c-muted / .c-faint / .c-frame / .c-fg
5
+ * backed by the --graph-* variables. Default is one accent.
6
+ */
7
+ export function isMonoPalette(palette) {
8
+ return palette == null || palette === 'mono';
9
+ }
10
+ /** Intensity level (0–4) → color role. Mirrors intensityClass from the reference. */
11
+ export function intensityRole(level, palette = 'mono') {
12
+ const index = Math.min(4, Math.max(0, Math.round(level)));
13
+ if (index <= 0) {
14
+ return 'empty';
15
+ }
16
+ if (palette === 'multi') {
17
+ if (index === 1) {
18
+ return 'accent2';
19
+ }
20
+ if (index <= 3) {
21
+ return 'accent3';
22
+ }
23
+ return 'accent';
24
+ }
25
+ if (palette === 'duo') {
26
+ if (index <= 2) {
27
+ return 'accent2';
28
+ }
29
+ return 'accent';
30
+ }
31
+ if (index <= 2) {
32
+ return 'muted';
33
+ }
34
+ if (index === 3) {
35
+ return 'foreground';
36
+ }
37
+ return 'accent';
38
+ }
39
+ const SERIES_ROLES = ['accent', 'accent2', 'accent3'];
40
+ /** Series index → color role. Mirrors seriesClass from the reference. */
41
+ export function seriesRole(palette, index) {
42
+ if (isMonoPalette(palette)) {
43
+ return index === 0 ? 'accent' : 'foreground';
44
+ }
45
+ const count = palette === 'duo' ? 2 : 3;
46
+ return SERIES_ROLES[index % count];
47
+ }
48
+ /** Whether a series should recede (mono palette, not highlighted). */
49
+ export function isDim(palette, highlighted) {
50
+ return isMonoPalette(palette) && !highlighted;
51
+ }
52
+ /** Semantic role → color role. Mirrors toneClass from the reference. */
53
+ export function toneRole(palette, role) {
54
+ if (role === 'empty') {
55
+ return 'empty';
56
+ }
57
+ if (role === 'idle') {
58
+ return 'muted';
59
+ }
60
+ if (role === 'primary') {
61
+ return 'accent';
62
+ }
63
+ return isMonoPalette(palette) ? 'muted' : 'accent2';
64
+ }
@@ -0,0 +1,387 @@
1
+ <script module lang="ts">
2
+ import type { Glyphs } from '../frame/glyphs';
3
+ import type { GraphPalette } from '../frame/tone';
4
+
5
+ /** GitHub-style contribution grid: weeks across the frame, days down. */
6
+ export interface ActivityDay {
7
+ date: string;
8
+ count: number;
9
+ }
10
+
11
+ export interface GraphActivityProps {
12
+ title: string;
13
+ days: ActivityDay[];
14
+ weekStartsOn?: 0 | 1;
15
+ max?: number;
16
+ legend?: boolean;
17
+ caption?: string | false;
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 { intensityGlyph, intensityLevel, resolveGlyphs } from '../frame/glyphs';
29
+ import { intensityRole } from '../frame/tone';
30
+ import type { ToneRole } from '../frame/tone';
31
+ import { reveal, stagger } from '../frame/motion';
32
+
33
+ const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
34
+ const DAY_MS = 86_400_000;
35
+
36
+ let {
37
+ title,
38
+ days,
39
+ weekStartsOn = 0,
40
+ max,
41
+ legend = true,
42
+ caption,
43
+ glyphs,
44
+ palette,
45
+ corner,
46
+ class: className = ''
47
+ }: GraphActivityProps = $props();
48
+
49
+ type Cell = { date: string; count: number; inRange: boolean };
50
+
51
+ function parseUTC(iso: string) {
52
+ const [year, month, day] = iso.split('-').map(Number);
53
+ return Date.UTC(year, month - 1, day);
54
+ }
55
+
56
+ function toISO(utc: number) {
57
+ return new Date(utc).toISOString().slice(0, 10);
58
+ }
59
+
60
+ function buildWeeks(list: ActivityDay[], start: 0 | 1) {
61
+ if (list.length === 0) {
62
+ return [] as Cell[][];
63
+ }
64
+
65
+ const counts = new Map<string, number>();
66
+ let min = Number.POSITIVE_INFINITY;
67
+ let maxTime = Number.NEGATIVE_INFINITY;
68
+
69
+ for (const day of list) {
70
+ const time = parseUTC(day.date);
71
+ counts.set(day.date, day.count);
72
+ if (time < min) min = time;
73
+ if (time > maxTime) maxTime = time;
74
+ }
75
+
76
+ const lead = (new Date(min).getUTCDay() - start + 7) % 7;
77
+ const trail = (start + 6 - new Date(maxTime).getUTCDay() + 7) % 7;
78
+ const first = min - lead * DAY_MS;
79
+ const last = maxTime + trail * DAY_MS;
80
+ const weeks: Cell[][] = [];
81
+ let week: Cell[] = [];
82
+
83
+ for (let time = first; time <= last; time += DAY_MS) {
84
+ const date = toISO(time);
85
+ const inRange = time >= min && time <= maxTime;
86
+ week.push({
87
+ date,
88
+ count: inRange ? (counts.get(date) ?? 0) : 0,
89
+ inRange
90
+ });
91
+ if (week.length === 7) {
92
+ weeks.push(week);
93
+ week = [];
94
+ }
95
+ }
96
+
97
+ return weeks;
98
+ }
99
+
100
+ function monthLabels(weeks: Cell[][]) {
101
+ return weeks.map((week) => {
102
+ const start = week.find((cell) => {
103
+ if (!cell.inRange) {
104
+ return false;
105
+ }
106
+
107
+ return new Date(parseUTC(cell.date)).getUTCDate() === 1;
108
+ });
109
+
110
+ if (!start) {
111
+ return '';
112
+ }
113
+
114
+ return MONTHS[new Date(parseUTC(start.date)).getUTCMonth()] ?? '';
115
+ });
116
+ }
117
+
118
+ function dayLabels(start: 0 | 1) {
119
+ return start === 1 ? ['M', '', 'W', '', 'F', '', ''] : ['', 'M', '', 'W', '', 'F', ''];
120
+ }
121
+
122
+ const set = $derived(resolveGlyphs(glyphs));
123
+ const weeks = $derived(buildWeeks(days, weekStartsOn));
124
+ const months = $derived(monthLabels(weeks));
125
+ const labels = $derived(dayLabels(weekStartsOn));
126
+ const peak = $derived(max ?? Math.max(0, ...days.map((day) => day.count), 0));
127
+ const total = $derived(days.reduce((sum, day) => sum + day.count, 0));
128
+ const summary = $derived(`${total.toLocaleString('en-US')} contributions`);
129
+ const quiet = $derived(set[0] ?? '·');
130
+
131
+ const scale = $derived(
132
+ set.map((glyph, index) => ({
133
+ glyph,
134
+ key: `${glyph}-${index}`,
135
+ role: intensityRole(Math.round((index / Math.max(set.length - 1, 1)) * 4), palette)
136
+ }))
137
+ );
138
+
139
+ const view = $derived(
140
+ weeks.map((week) => ({
141
+ key: week[0]?.date ?? '',
142
+ cells: week.map((cell) => {
143
+ const level = cell.inRange ? intensityLevel(cell.count, peak) : 0;
144
+ return {
145
+ date: cell.date,
146
+ glyph: cell.inRange ? intensityGlyph(level, set) : quiet,
147
+ role: (cell.inRange ? intensityRole(level, palette) : 'ghost') as ToneRole | 'ghost'
148
+ };
149
+ })
150
+ }))
151
+ );
152
+ </script>
153
+
154
+ <Graph {title} {corner} class={className}>
155
+ <GraphBody>
156
+ <div class="act">
157
+ <div class="wrap">
158
+ <div class="months">
159
+ <span class="gutter"></span>
160
+ {#each months as month, index (`m-${index}`)}
161
+ <span class="mslot">
162
+ {#if month}
163
+ <span class="mlabel muted">{month}</span>
164
+ {/if}
165
+ </span>
166
+ {/each}
167
+ </div>
168
+ <div class="body-row">
169
+ <div class="days">
170
+ {#each labels as label, index (`d-${index}`)}
171
+ <span class="dlabel muted">{label}</span>
172
+ {/each}
173
+ </div>
174
+ <div class="grid">
175
+ {#each view as week, weekIndex (week.key || weekIndex)}
176
+ <div
177
+ class="wcol"
178
+ use:reveal={{ delay: stagger(weekIndex, 10), amount: 0.2 }}
179
+ >
180
+ {#each week.cells as cell (cell.date)}
181
+ <span
182
+ class="dcell"
183
+ class:ghost={cell.role === 'ghost'}
184
+ class:c-frame={cell.role === 'empty'}
185
+ class:c-muted={cell.role === 'muted'}
186
+ class:c-fg={cell.role === 'foreground'}
187
+ class:c-accent={cell.role === 'accent'}
188
+ class:c-accent2={cell.role === 'accent2'}
189
+ class:c-accent3={cell.role === 'accent3'}
190
+ >
191
+ {cell.glyph}
192
+ </span>
193
+ {/each}
194
+ </div>
195
+ {/each}
196
+ </div>
197
+ </div>
198
+ </div>
199
+ {#if caption !== false || legend}
200
+ <div class="foot" class:end={caption === false}>
201
+ {#if caption !== false}
202
+ <p class="muted">{caption ?? summary}</p>
203
+ {/if}
204
+ {#if legend}
205
+ <p class="legend">
206
+ <span>Less</span>
207
+ <span class="scale" aria-hidden="true">
208
+ {#each scale as entry (entry.key)}
209
+ <span
210
+ class="sglyph"
211
+ class:c-frame={entry.role === 'empty'}
212
+ class:c-muted={entry.role === 'muted'}
213
+ class:c-fg={entry.role === 'foreground'}
214
+ class:c-accent={entry.role === 'accent'}
215
+ class:c-accent2={entry.role === 'accent2'}
216
+ class:c-accent3={entry.role === 'accent3'}
217
+ >
218
+ {entry.glyph}
219
+ </span>
220
+ {/each}
221
+ </span>
222
+ <span>More</span>
223
+ </p>
224
+ {/if}
225
+ </div>
226
+ {/if}
227
+ <span class="sr-only">
228
+ {total} contributions across {days.length} days{caption ? `. ${caption}` : ''}
229
+ </span>
230
+ </div>
231
+ </GraphBody>
232
+ </Graph>
233
+
234
+ <style>
235
+ .act {
236
+ display: flex;
237
+ flex-direction: column;
238
+ gap: 1rem;
239
+ }
240
+
241
+ .wrap {
242
+ display: flex;
243
+ width: 100%;
244
+ flex-direction: column;
245
+ gap: 0.25rem;
246
+ }
247
+
248
+ .months {
249
+ display: flex;
250
+ width: 100%;
251
+ height: 1.25em;
252
+ }
253
+
254
+ .gutter {
255
+ width: 2ch;
256
+ flex-shrink: 0;
257
+ }
258
+
259
+ .mslot {
260
+ position: relative;
261
+ min-width: 1ch;
262
+ flex: 1;
263
+ }
264
+
265
+ .mlabel {
266
+ position: absolute;
267
+ bottom: 0;
268
+ left: 0;
269
+ white-space: nowrap;
270
+ }
271
+
272
+ .body-row {
273
+ display: flex;
274
+ width: 100%;
275
+ }
276
+
277
+ .days {
278
+ display: flex;
279
+ width: 2ch;
280
+ flex-shrink: 0;
281
+ flex-direction: column;
282
+ }
283
+
284
+ .dlabel {
285
+ display: flex;
286
+ height: 1.15em;
287
+ align-items: center;
288
+ }
289
+
290
+ .grid {
291
+ display: flex;
292
+ min-width: 0;
293
+ flex: 1;
294
+ }
295
+
296
+ .wcol {
297
+ display: flex;
298
+ min-width: 1ch;
299
+ flex: 1;
300
+ flex-direction: column;
301
+ }
302
+
303
+ .dcell {
304
+ display: flex;
305
+ width: 100%;
306
+ height: 1.15em;
307
+ align-items: center;
308
+ justify-content: center;
309
+ line-height: 1;
310
+ user-select: none;
311
+ }
312
+
313
+ .foot {
314
+ display: flex;
315
+ flex-wrap: wrap;
316
+ align-items: center;
317
+ justify-content: space-between;
318
+ gap: 0.75rem;
319
+ }
320
+
321
+ .foot.end {
322
+ justify-content: flex-end;
323
+ }
324
+
325
+ .legend {
326
+ margin: 0;
327
+ display: flex;
328
+ align-items: center;
329
+ gap: 0.5rem;
330
+ color: var(--graph-muted, oklch(0.62 0 0));
331
+ }
332
+
333
+ .scale {
334
+ display: flex;
335
+ user-select: none;
336
+ }
337
+
338
+ .sglyph {
339
+ width: 1ch;
340
+ text-align: center;
341
+ }
342
+
343
+ .muted {
344
+ margin: 0;
345
+ color: var(--graph-muted, oklch(0.62 0 0));
346
+ }
347
+
348
+ .ghost {
349
+ color: transparent;
350
+ }
351
+
352
+ .c-accent {
353
+ color: var(--graph-accent, oklch(0.78 0.17 155));
354
+ }
355
+
356
+ .c-accent2 {
357
+ color: var(--graph-accent-2, oklch(0.78 0.12 70));
358
+ }
359
+
360
+ .c-accent3 {
361
+ color: var(--graph-accent-3, oklch(0.75 0.1 200));
362
+ }
363
+
364
+ .c-frame {
365
+ color: var(--graph-frame, oklch(0.6 0 0 / 0.5));
366
+ }
367
+
368
+ .c-fg {
369
+ color: var(--graph-foreground, oklch(0.93 0 0));
370
+ }
371
+
372
+ .c-muted {
373
+ color: var(--graph-muted, oklch(0.62 0 0));
374
+ }
375
+
376
+ .sr-only {
377
+ position: absolute;
378
+ width: 1px;
379
+ height: 1px;
380
+ padding: 0;
381
+ margin: -1px;
382
+ overflow: hidden;
383
+ clip-path: inset(50%);
384
+ white-space: nowrap;
385
+ border-width: 0;
386
+ }
387
+ </style>
@@ -0,0 +1,22 @@
1
+ import type { Glyphs } from '../frame/glyphs';
2
+ import type { GraphPalette } from '../frame/tone';
3
+ /** GitHub-style contribution grid: weeks across the frame, days down. */
4
+ export interface ActivityDay {
5
+ date: string;
6
+ count: number;
7
+ }
8
+ export interface GraphActivityProps {
9
+ title: string;
10
+ days: ActivityDay[];
11
+ weekStartsOn?: 0 | 1;
12
+ max?: number;
13
+ legend?: boolean;
14
+ caption?: string | false;
15
+ glyphs?: Glyphs;
16
+ palette?: GraphPalette;
17
+ corner?: string;
18
+ class?: string;
19
+ }
20
+ declare const GraphActivity: import("svelte").Component<GraphActivityProps, {}, "">;
21
+ type GraphActivity = ReturnType<typeof GraphActivity>;
22
+ export default GraphActivity;