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,18 @@
1
+ import type { GraphPalette } from '../frame/tone';
2
+ export type DiffSign = 'add' | 'remove' | 'keep';
3
+ export interface DiffRow {
4
+ label: string;
5
+ value: string;
6
+ sign?: DiffSign;
7
+ }
8
+ export interface GraphDiffProps {
9
+ title: string;
10
+ rows: DiffRow[];
11
+ footer?: DiffRow;
12
+ palette?: GraphPalette;
13
+ corner?: string;
14
+ class?: string;
15
+ }
16
+ declare const GraphDiff: import("svelte").Component<GraphDiffProps, {}, "">;
17
+ type GraphDiff = ReturnType<typeof GraphDiff>;
18
+ export default GraphDiff;
@@ -0,0 +1,137 @@
1
+ <script module lang="ts">
2
+ import type { GraphPalette } from '../frame/tone';
3
+
4
+ /** Tone of a flow node: default foreground, accent (live path), or muted. */
5
+ export type FlowTone = 'default' | 'accent' | 'muted';
6
+
7
+ export interface FlowNode {
8
+ label: string;
9
+ tone?: FlowTone;
10
+ stretch?: boolean;
11
+ }
12
+
13
+ export interface FlowRow {
14
+ nodes: FlowNode[];
15
+ }
16
+
17
+ export interface GraphFlowProps {
18
+ title: string;
19
+ rows: FlowRow[];
20
+ palette?: GraphPalette;
21
+ corner?: string;
22
+ class?: string;
23
+ }
24
+ </script>
25
+
26
+ <script lang="ts">
27
+ import Graph from '../frame/Graph.svelte';
28
+ import GraphBody from '../frame/GraphBody.svelte';
29
+ import GraphArrow from '../frame/GraphArrow.svelte';
30
+ import { reveal, stagger } from '../frame/motion';
31
+ import { toneRole, type ToneRole } from '../frame/tone';
32
+
33
+ let {
34
+ title,
35
+ rows,
36
+ palette,
37
+ corner,
38
+ class: className = ''
39
+ }: GraphFlowProps = $props();
40
+
41
+ function nodeRole(tone: FlowTone): ToneRole {
42
+ if (tone === 'accent') {
43
+ return toneRole(palette, 'primary');
44
+ }
45
+
46
+ if (tone === 'muted') {
47
+ return toneRole(palette, 'secondary');
48
+ }
49
+
50
+ return 'foreground';
51
+ }
52
+ </script>
53
+
54
+ <Graph {title} {corner} class={className}>
55
+ <GraphBody>
56
+ <div class="flow">
57
+ {#each rows as row, rowIndex (rowIndex)}
58
+ <div class="row" use:reveal={{ delay: stagger(rowIndex, 80), amount: 0.5 }}>
59
+ {#each row.nodes as node, nodeIndex (`${node.label}-${nodeIndex}`)}
60
+ {@const tone = node.tone ?? 'default'}
61
+ {@const role = nodeRole(tone)}
62
+ <div class="node" class:stretch={node.stretch}>
63
+ {#if nodeIndex > 0}
64
+ <GraphArrow accent={tone === 'accent'} stretch={node.stretch} />
65
+ {/if}
66
+ <span
67
+ class="label"
68
+ class:c-accent={role === 'accent'}
69
+ class:c-accent2={role === 'accent2'}
70
+ class:c-muted={role === 'muted'}
71
+ class:c-fg={role === 'foreground'}
72
+ >
73
+ {node.label}
74
+ </span>
75
+ </div>
76
+ {/each}
77
+ </div>
78
+ {/each}
79
+ </div>
80
+ </GraphBody>
81
+ </Graph>
82
+
83
+ <style>
84
+ .flow {
85
+ display: flex;
86
+ flex-direction: column;
87
+ gap: 1.75rem;
88
+ }
89
+
90
+ .row {
91
+ display: flex;
92
+ min-width: 0;
93
+ flex-wrap: wrap;
94
+ align-items: center;
95
+ column-gap: 0.75rem;
96
+ row-gap: 0.5rem;
97
+ }
98
+
99
+ @media (min-width: 640px) {
100
+ .row {
101
+ flex-wrap: nowrap;
102
+ }
103
+ }
104
+
105
+ .node {
106
+ display: flex;
107
+ min-width: 0;
108
+ align-items: center;
109
+ gap: 0.75rem;
110
+ }
111
+
112
+ .node.stretch {
113
+ min-width: 4rem;
114
+ flex: 1;
115
+ }
116
+
117
+ .label {
118
+ flex-shrink: 0;
119
+ white-space: nowrap;
120
+ }
121
+
122
+ .c-accent {
123
+ color: var(--graph-accent, oklch(0.78 0.17 155));
124
+ }
125
+
126
+ .c-accent2 {
127
+ color: var(--graph-accent-2, oklch(0.78 0.12 70));
128
+ }
129
+
130
+ .c-muted {
131
+ color: var(--graph-muted, oklch(0.62 0 0));
132
+ }
133
+
134
+ .c-fg {
135
+ color: var(--graph-foreground, oklch(0.93 0 0));
136
+ }
137
+ </style>
@@ -0,0 +1,21 @@
1
+ import type { GraphPalette } from '../frame/tone';
2
+ /** Tone of a flow node: default foreground, accent (live path), or muted. */
3
+ export type FlowTone = 'default' | 'accent' | 'muted';
4
+ export interface FlowNode {
5
+ label: string;
6
+ tone?: FlowTone;
7
+ stretch?: boolean;
8
+ }
9
+ export interface FlowRow {
10
+ nodes: FlowNode[];
11
+ }
12
+ export interface GraphFlowProps {
13
+ title: string;
14
+ rows: FlowRow[];
15
+ palette?: GraphPalette;
16
+ corner?: string;
17
+ class?: string;
18
+ }
19
+ declare const GraphFlow: import("svelte").Component<GraphFlowProps, {}, "">;
20
+ type GraphFlow = ReturnType<typeof GraphFlow>;
21
+ export default GraphFlow;
@@ -0,0 +1,190 @@
1
+ <script module lang="ts">
2
+ import type { Glyphs } from '../frame/glyphs';
3
+ import type { GraphPalette } from '../frame/tone';
4
+
5
+ /** One stage of the funnel. */
6
+ export interface FunnelStep {
7
+ label: string;
8
+ value: number;
9
+ display?: string;
10
+ }
11
+
12
+ export interface GraphFunnelProps {
13
+ title: string;
14
+ steps: FunnelStep[];
15
+ ticks?: number;
16
+ stage?: string;
17
+ glyphs?: Glyphs;
18
+ palette?: GraphPalette;
19
+ corner?: string;
20
+ class?: string;
21
+ }
22
+ </script>
23
+
24
+ <script lang="ts">
25
+ import Graph from '../frame/Graph.svelte';
26
+ import GraphBody from '../frame/GraphBody.svelte';
27
+ import GraphTrack from '../frame/GraphTrack.svelte';
28
+ import GraphTick from '../frame/GraphTick.svelte';
29
+ import { trackMarks } from '../frame/glyphs';
30
+ import { isDim, isMonoPalette, seriesRole, type ToneRole } from '../frame/tone';
31
+ import { reveal, stagger } from '../frame/motion';
32
+
33
+ let {
34
+ title,
35
+ steps,
36
+ ticks = 20,
37
+ stage,
38
+ glyphs,
39
+ palette,
40
+ corner,
41
+ class: className = ''
42
+ }: GraphFunnelProps = $props();
43
+
44
+ const mono = $derived(isMonoPalette(palette));
45
+ const max = $derived(Math.max(...steps.map((step) => step.value), 1));
46
+ const head = $derived(steps[0]?.value || 1);
47
+ const marks = $derived(trackMarks(glyphs));
48
+
49
+ const view = $derived.by(() =>
50
+ steps.map((step, index) => {
51
+ const width = Math.max(1, Math.round((step.value / max) * ticks));
52
+ const percent = Math.round((step.value / head) * 100);
53
+ const focused = Boolean(stage) && step.label === stage;
54
+ const receded = Boolean(stage) && !focused;
55
+ const role: ToneRole = mono ? 'accent' : seriesRole(palette, index);
56
+
57
+ const cells = Array.from({ length: ticks }, (_, cell) => {
58
+ const filled = cell < width;
59
+
60
+ return {
61
+ glyph: filled ? marks.fill : marks.empty,
62
+ role: filled ? role : ('empty' as const)
63
+ };
64
+ });
65
+
66
+ return {
67
+ label: step.label,
68
+ value: step.display ?? step.value.toLocaleString(),
69
+ percent: index === 0 ? '' : `${percent}%`,
70
+ dim: isDim(palette, !receded),
71
+ cells
72
+ };
73
+ })
74
+ );
75
+
76
+ const spoken = $derived(
77
+ steps
78
+ .map((step) => `${step.label} ${step.display ?? step.value.toLocaleString()}`)
79
+ .join(', ')
80
+ );
81
+ </script>
82
+
83
+ <Graph {title} {corner} class={className}>
84
+ <GraphBody>
85
+ <ol class="steps" role="list">
86
+ {#each view as step, i (step.label)}
87
+ <li
88
+ class="step"
89
+ class:dim={step.dim}
90
+ use:reveal={{ delay: stagger(i, 40), amount: 0.4 }}
91
+ >
92
+ <span class="label">{step.label}</span>
93
+ <GraphTrack>
94
+ {#each step.cells as cell}
95
+ <GraphTick>
96
+ <span
97
+ class="g"
98
+ class:c-accent={cell.role === 'accent'}
99
+ class:c-accent2={cell.role === 'accent2'}
100
+ class:c-accent3={cell.role === 'accent3'}
101
+ class:c-frame={cell.role === 'empty'}
102
+ >
103
+ {cell.glyph}
104
+ </span>
105
+ </GraphTick>
106
+ {/each}
107
+ </GraphTrack>
108
+ <span class="value">{step.value}</span>
109
+ <span class="pct muted">{step.percent}</span>
110
+ </li>
111
+ {/each}
112
+ </ol>
113
+ <span class="sr-only">{spoken}</span>
114
+ </GraphBody>
115
+ </Graph>
116
+
117
+ <style>
118
+ .steps {
119
+ margin: 0;
120
+ padding: 0;
121
+ list-style: none;
122
+ display: flex;
123
+ flex-direction: column;
124
+ gap: 0.75rem;
125
+ }
126
+
127
+ .step {
128
+ display: grid;
129
+ grid-template-columns: 7rem minmax(0, 1fr) 8ch 4ch;
130
+ column-gap: 1rem;
131
+ align-items: center;
132
+ }
133
+
134
+ .label {
135
+ min-width: 0;
136
+ overflow: hidden;
137
+ text-overflow: ellipsis;
138
+ white-space: nowrap;
139
+ color: var(--graph-foreground, oklch(0.93 0 0));
140
+ }
141
+
142
+ .g {
143
+ display: block;
144
+ }
145
+
146
+ .value {
147
+ text-align: right;
148
+ color: var(--graph-foreground, oklch(0.93 0 0));
149
+ }
150
+
151
+ .pct {
152
+ text-align: right;
153
+ }
154
+
155
+ .muted {
156
+ color: var(--graph-muted, oklch(0.62 0 0));
157
+ }
158
+
159
+ .c-accent {
160
+ color: var(--graph-accent, oklch(0.78 0.17 155));
161
+ }
162
+
163
+ .c-accent2 {
164
+ color: var(--graph-accent-2, oklch(0.78 0.12 70));
165
+ }
166
+
167
+ .c-accent3 {
168
+ color: var(--graph-accent-3, oklch(0.75 0.1 200));
169
+ }
170
+
171
+ .c-frame {
172
+ color: var(--graph-frame, oklch(0.6 0 0 / 0.5));
173
+ }
174
+
175
+ .dim {
176
+ opacity: 0.4;
177
+ }
178
+
179
+ .sr-only {
180
+ position: absolute;
181
+ width: 1px;
182
+ height: 1px;
183
+ padding: 0;
184
+ margin: -1px;
185
+ overflow: hidden;
186
+ clip-path: inset(50%);
187
+ white-space: nowrap;
188
+ border-width: 0;
189
+ }
190
+ </style>
@@ -0,0 +1,21 @@
1
+ import type { Glyphs } from '../frame/glyphs';
2
+ import type { GraphPalette } from '../frame/tone';
3
+ /** One stage of the funnel. */
4
+ export interface FunnelStep {
5
+ label: string;
6
+ value: number;
7
+ display?: string;
8
+ }
9
+ export interface GraphFunnelProps {
10
+ title: string;
11
+ steps: FunnelStep[];
12
+ ticks?: number;
13
+ stage?: string;
14
+ glyphs?: Glyphs;
15
+ palette?: GraphPalette;
16
+ corner?: string;
17
+ class?: string;
18
+ }
19
+ declare const GraphFunnel: import("svelte").Component<GraphFunnelProps, {}, "">;
20
+ type GraphFunnel = ReturnType<typeof GraphFunnel>;
21
+ export default GraphFunnel;
@@ -0,0 +1,258 @@
1
+ <script module lang="ts">
2
+ import type { Glyphs } from '../frame/glyphs';
3
+ import type { GraphPalette } from '../frame/tone';
4
+
5
+ /** Tasks on a shared character track: spans positioned via --start/--span. */
6
+ export interface GanttItem {
7
+ label: string;
8
+ start: number;
9
+ end: number;
10
+ accent?: boolean;
11
+ complete?: number;
12
+ }
13
+
14
+ export interface GraphGanttProps {
15
+ title: string;
16
+ items: GanttItem[];
17
+ ticks?: string[];
18
+ columns?: number;
19
+ stage?: string;
20
+ progress?: number;
21
+ glyphs?: Glyphs;
22
+ palette?: GraphPalette;
23
+ corner?: string;
24
+ class?: string;
25
+ }
26
+ </script>
27
+
28
+ <script lang="ts">
29
+ import Graph from '../frame/Graph.svelte';
30
+ import GraphBody from '../frame/GraphBody.svelte';
31
+ import { clamp01, trackMarks } from '../frame/glyphs';
32
+ import { isDim, toneRole } from '../frame/tone';
33
+ import type { ToneRole } from '../frame/tone';
34
+ import { reveal, stagger } from '../frame/motion';
35
+
36
+ let {
37
+ title,
38
+ items,
39
+ ticks,
40
+ columns = 24,
41
+ stage,
42
+ progress,
43
+ glyphs,
44
+ palette,
45
+ corner,
46
+ class: className = ''
47
+ }: GraphGanttProps = $props();
48
+
49
+ const marks = $derived(trackMarks(glyphs));
50
+ const playhead = $derived(
51
+ progress == null ? null : Math.round(clamp01(progress) * (columns - 1))
52
+ );
53
+ const cols = $derived(Array.from({ length: columns }, (_, index) => index));
54
+
55
+ const view = $derived(
56
+ items.map((entry) => {
57
+ const start = Math.round(clamp01(entry.start) * columns);
58
+ const end = Math.max(start + 1, Math.round(clamp01(entry.end) * columns));
59
+ const span = end - start;
60
+ const done = Math.round(clamp01(entry.complete ?? 1) * span);
61
+ const focused = stage ? entry.label === stage : Boolean(entry.accent);
62
+ const dim = Boolean(stage) && !focused;
63
+ const spoken = `${entry.label} from ${Math.round(entry.start * 100)}% to ${Math.round(
64
+ entry.end * 100
65
+ )}%${entry.complete != null ? `, ${Math.round(entry.complete * 100)}% complete` : ''}`;
66
+ const bar = Array.from({ length: span }, (_, index) => {
67
+ const filled = index < done;
68
+ return {
69
+ glyph: filled ? marks.fill : marks.rest,
70
+ role: (
71
+ filled
72
+ ? focused
73
+ ? toneRole(palette, 'primary')
74
+ : 'foreground'
75
+ : toneRole(palette, 'secondary')
76
+ ) as ToneRole
77
+ };
78
+ });
79
+ return { entry, start, span, done, focused, dim, spoken, bar };
80
+ })
81
+ );
82
+ </script>
83
+
84
+ <Graph {title} {corner} class={className}>
85
+ <GraphBody>
86
+ <div class="gantt">
87
+ {#if playhead != null}
88
+ <div class="rowcols">
89
+ <span class="spacer"></span>
90
+ <span class="track" aria-hidden="true" style:--cols={columns}>
91
+ <span class="marker c-accent" style:--pos={playhead}>▾</span>
92
+ </span>
93
+ </div>
94
+ {/if}
95
+ <ul class="items" role="list">
96
+ {#each view as item, i (item.entry.label)}
97
+ <li
98
+ class="row"
99
+ class:dim={isDim(palette, !item.dim)}
100
+ aria-label={item.spoken}
101
+ use:reveal={{ delay: stagger(i, 50), amount: 0.4 }}
102
+ >
103
+ <span class="label" class:c-accent={item.focused} class:c-fg={!item.focused}>
104
+ {item.entry.label}
105
+ </span>
106
+ <span class="track" aria-hidden="true" style:--cols={columns}>
107
+ {#each cols as c (c)}
108
+ <span class="cell">
109
+ {c >= item.start && c < item.start + item.span ? '' : marks.empty}
110
+ </span>
111
+ {/each}
112
+ <span class="bar" style:--start={item.start + 1} style:--span={item.span}>
113
+ {#each item.bar as cell, index (index)}
114
+ <span
115
+ class="bcell"
116
+ class:c-accent={cell.role === 'accent'}
117
+ class:c-fg={cell.role === 'foreground'}
118
+ class:c-muted={cell.role === 'muted'}
119
+ class:c-accent2={cell.role === 'accent2'}
120
+ >
121
+ {cell.glyph}
122
+ </span>
123
+ {/each}
124
+ </span>
125
+ </span>
126
+ </li>
127
+ {/each}
128
+ </ul>
129
+ {#if ticks && ticks.length > 0}
130
+ <div class="rowcols">
131
+ <span class="spacer"></span>
132
+ <div class="ticks">
133
+ {#each ticks as tick (tick)}
134
+ <span>{tick}</span>
135
+ {/each}
136
+ </div>
137
+ </div>
138
+ {/if}
139
+ <span class="sr-only">{items.length} tasks</span>
140
+ </div>
141
+ </GraphBody>
142
+ </Graph>
143
+
144
+ <style>
145
+ .gantt {
146
+ display: flex;
147
+ flex-direction: column;
148
+ gap: 1rem;
149
+ }
150
+
151
+ .rowcols {
152
+ display: grid;
153
+ grid-template-columns: 7rem minmax(0, 1fr);
154
+ align-items: center;
155
+ column-gap: 1rem;
156
+ }
157
+
158
+ .spacer {
159
+ min-width: 0;
160
+ }
161
+
162
+ .items {
163
+ margin: 0;
164
+ padding: 0;
165
+ display: flex;
166
+ flex-direction: column;
167
+ gap: 0.5rem;
168
+ list-style: none;
169
+ }
170
+
171
+ .row {
172
+ display: grid;
173
+ grid-template-columns: 7rem minmax(0, 1fr);
174
+ align-items: center;
175
+ column-gap: 1rem;
176
+ }
177
+
178
+ .row.dim {
179
+ opacity: 0.4;
180
+ }
181
+
182
+ .label {
183
+ overflow: hidden;
184
+ text-overflow: ellipsis;
185
+ white-space: nowrap;
186
+ }
187
+
188
+ .track {
189
+ position: relative;
190
+ display: flex;
191
+ width: 100%;
192
+ min-width: 0;
193
+ user-select: none;
194
+ }
195
+
196
+ .cell {
197
+ min-width: 1ch;
198
+ flex: 1 1 0%;
199
+ text-align: center;
200
+ color: var(--graph-frame, oklch(0.6 0 0 / 0.5));
201
+ }
202
+
203
+ .bar {
204
+ position: absolute;
205
+ top: 0;
206
+ bottom: 0;
207
+ left: calc((var(--start) - 1) * 100% / var(--cols));
208
+ width: calc(var(--span) * 100% / var(--cols));
209
+ display: flex;
210
+ }
211
+
212
+ .bcell {
213
+ min-width: 0;
214
+ flex: 1 1 0%;
215
+ text-align: center;
216
+ }
217
+
218
+ .marker {
219
+ position: absolute;
220
+ top: 0;
221
+ left: calc((var(--pos) + 0.5) * 100% / var(--cols));
222
+ transform: translateX(-50%);
223
+ }
224
+
225
+ .ticks {
226
+ display: flex;
227
+ justify-content: space-between;
228
+ color: var(--graph-muted, oklch(0.62 0 0));
229
+ }
230
+
231
+ .c-accent {
232
+ color: var(--graph-accent, oklch(0.78 0.17 155));
233
+ }
234
+
235
+ .c-accent2 {
236
+ color: var(--graph-accent-2, oklch(0.78 0.12 70));
237
+ }
238
+
239
+ .c-fg {
240
+ color: var(--graph-foreground, oklch(0.93 0 0));
241
+ }
242
+
243
+ .c-muted {
244
+ color: var(--graph-muted, oklch(0.62 0 0));
245
+ }
246
+
247
+ .sr-only {
248
+ position: absolute;
249
+ width: 1px;
250
+ height: 1px;
251
+ padding: 0;
252
+ margin: -1px;
253
+ overflow: hidden;
254
+ clip-path: inset(50%);
255
+ white-space: nowrap;
256
+ border-width: 0;
257
+ }
258
+ </style>
@@ -0,0 +1,25 @@
1
+ import type { Glyphs } from '../frame/glyphs';
2
+ import type { GraphPalette } from '../frame/tone';
3
+ /** Tasks on a shared character track: spans positioned via --start/--span. */
4
+ export interface GanttItem {
5
+ label: string;
6
+ start: number;
7
+ end: number;
8
+ accent?: boolean;
9
+ complete?: number;
10
+ }
11
+ export interface GraphGanttProps {
12
+ title: string;
13
+ items: GanttItem[];
14
+ ticks?: string[];
15
+ columns?: number;
16
+ stage?: string;
17
+ progress?: number;
18
+ glyphs?: Glyphs;
19
+ palette?: GraphPalette;
20
+ corner?: string;
21
+ class?: string;
22
+ }
23
+ declare const GraphGantt: import("svelte").Component<GraphGanttProps, {}, "">;
24
+ type GraphGantt = ReturnType<typeof GraphGantt>;
25
+ export default GraphGantt;