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,414 @@
1
+ <script lang="ts">
2
+ import AsciiDiagram from './AsciiDiagram.svelte';
3
+ import { alignBoxLines } from './parser';
4
+
5
+ const PRESETS = [
6
+ {
7
+ name: 'Nested Radii',
8
+ code: `+ - - - - - - [ NESTED RADII ] - - - - - - +
9
+ | |
10
+ | ╭ - - - - - - - - - - - - - - - - - - ╮ |
11
+ | | outer 16px | |
12
+ | | ╭ - - - - - - - - - - - - ╮ | |
13
+ | |◀ - ▶| inner 12px | | |
14
+ | | ╰ - - - - - - - - - - - - ╯ | |
15
+ | | inset 4px | |
16
+ | ╰ - - - - - - - - - - - - - - - - - - ╯ |
17
+ | |
18
+ | inner = outer - inset |
19
+ | 12px = 16px - 4px |
20
+ + - - - - - - - - - - - - - - - - - - - - - - +`
21
+ },
22
+ {
23
+ name: 'Prompt Loop',
24
+ code: `+ - - - - - - [ THE PROMPT LOOP ] - - - - - - +
25
+ | |
26
+ | ~> Ask for the thing you want |
27
+ | │ |
28
+ | v |
29
+ | AI builds it ◀ - - - - + |
30
+ | │ │ |
31
+ | v │ |
32
+ | It's not quite right │ |
33
+ | │ │ |
34
+ | v │ |
35
+ | ~> Make me a few variants │ |
36
+ | │ │ |
37
+ | v │ |
38
+ | v1 · v2 · v3 · v4 │ |
39
+ | │ │ |
40
+ | v │ |
41
+ | None of them are it │ |
42
+ | │ │ |
43
+ | + - - - - - - - - -+ |
44
+ | Repeat forever |
45
+ | |
46
+ + - - - - - - - - - - - - - - - - - - - - - - +`
47
+ },
48
+ {
49
+ name: 'System Architecture',
50
+ code: `┌───────────────────┐ ┌───────────────────┐
51
+ │ Client │──────────────>│ Edge Gateway │
52
+ │ SvelteKit + SVX │<──────────────│ Cloudflare / V8 │
53
+ └─────────┬─────────┘ └─────────┬─────────┘
54
+ │ │
55
+ v v
56
+ ┌───────────────────┐ ┌───────────────────┐
57
+ │ Monospace Cache │ │ AI LLM Engine │
58
+ │ Fast In-Memory │ │ Streaming Runes │
59
+ └───────────────────┘ └───────────────────┘`
60
+ },
61
+ {
62
+ name: 'AI Amplifier',
63
+ code: `+ - - - - - - - - - [ AI IS AN AMPLIFIER ] - - - - - - - - - +
64
+ | |
65
+ | ▃▅█▅▃ - - - - ▶ AI - - - - ▶ ▂▃▅▆█████▆▅▃▂ |
66
+ | your taste amplified |
67
+ | |
68
+ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +`
69
+ },
70
+ {
71
+ name: 'Token Cost Ledger',
72
+ code: `+ - - - - - - - - - [ COST LEDGER ] - - - - - - - - - +
73
+ | |
74
+ | Operation Tokens Time |
75
+ | - - - - - - - - - - - - - - - - - - - - - - |
76
+ | AST Parse 120 16m |
77
+ | MDSveX Compile 164 16m |
78
+ | Rune Optimization 112 18m |
79
+ | - - - - - - - - - - - - - - - - - - - - - - |
80
+ | Total 396 ~50m |
81
+ | |
82
+ + - - - - - - - - - - - - - - - - - - - - - - - - - - +`
83
+ }
84
+ ];
85
+
86
+ const GLYPH_SECTIONS = [
87
+ { label: 'Rounded', chars: ['╭', '╮', '╯', '╰', '─', '│'] },
88
+ { label: 'Light Box', chars: ['┌', '┐', '└', '┘', '├', '┤', '┬', '┴', '┼', '─', '│'] },
89
+ { label: 'Heavy Box', chars: ['┏', '┓', '┗', '┛', '┣', '┫', '┳', '┻', '╋', '━', '┃'] },
90
+ { label: 'Double Box', chars: ['╔', '╗', '╚', '╝', '╠', '╣', '╦', '╩', '╬', '═', '║'] },
91
+ { label: 'Arrows', chars: ['~>', '->', '◀', '▶', '▼', '▲', '◀ - ▶', '→', '←', '↑', '↓'] },
92
+ { label: 'Meters', chars: [' ', '▂', '▃', '▄', '▅', '▆', '▇', '█', '■', '●', '◆'] }
93
+ ];
94
+
95
+ let rawInput = $state(PRESETS[0].code);
96
+ let copiedFormat = $state<'text' | 'svelte' | 'svx' | null>(null);
97
+ let textarea: HTMLTextAreaElement | undefined = $state();
98
+
99
+ const lineCount = $derived(rawInput.split('\n').length);
100
+
101
+ function insertChar(char: string) {
102
+ const el = textarea;
103
+
104
+ if (!el) {
105
+ rawInput += char;
106
+ return;
107
+ }
108
+
109
+ const start = el.selectionStart;
110
+ const end = el.selectionEnd;
111
+ rawInput = rawInput.substring(0, start) + char + rawInput.substring(end);
112
+
113
+ window.setTimeout(() => {
114
+ el.focus();
115
+ el.setSelectionRange(start + char.length, start + char.length);
116
+ }, 10);
117
+ }
118
+
119
+ function handleAlign() {
120
+ rawInput = alignBoxLines(rawInput);
121
+ }
122
+
123
+ function loadPreset(preset: (typeof PRESETS)[number]) {
124
+ rawInput = preset.code;
125
+ }
126
+
127
+ async function copyAs(format: 'text' | 'svelte' | 'svx') {
128
+ let code = '';
129
+
130
+ if (format === 'text') {
131
+ code = rawInput;
132
+ } else if (format === 'svelte') {
133
+ code = `<script lang="ts">\n import { AsciiDiagram } from 'markgraphy';\n<\/script>\n\n<AsciiDiagram>\n {\`${rawInput}\`}\n</AsciiDiagram>`;
134
+ } else if (format === 'svx') {
135
+ code = `<script>\n import { AsciiDiagram } from 'markgraphy';\n<\/script>\n\n<AsciiDiagram>\n\n\`\`\`diagram\n${rawInput}\n\`\`\`\n\n</AsciiDiagram>`;
136
+ }
137
+
138
+ try {
139
+ await navigator.clipboard.writeText(code);
140
+ copiedFormat = format;
141
+ window.setTimeout(() => {
142
+ copiedFormat = null;
143
+ }, 2000);
144
+ } catch {
145
+ // Clipboard unavailable (permissions or non-secure context).
146
+ }
147
+ }
148
+ </script>
149
+
150
+ <div class="editor">
151
+ <div class="toolbar">
152
+ <div class="group">
153
+ <span class="label">Preset</span>
154
+ <div class="options">
155
+ {#each PRESETS as p (p.name)}
156
+ <button
157
+ class="chip"
158
+ class:on={rawInput === p.code}
159
+ type="button"
160
+ onclick={() => loadPreset(p)}
161
+ >
162
+ {p.name}
163
+ </button>
164
+ {/each}
165
+ </div>
166
+ </div>
167
+ </div>
168
+
169
+ <div class="palette">
170
+ <div class="palette-header">
171
+ <span class="label">Glyphs</span>
172
+ <button class="chip" type="button" onclick={handleAlign}>⚡ auto-align width</button>
173
+ </div>
174
+ <div class="glyph-groups">
175
+ {#each GLYPH_SECTIONS as section (section.label)}
176
+ <div class="glyph-group">
177
+ <span class="group-label">{section.label}</span>
178
+ <div class="chars">
179
+ {#each section.chars as ch (ch)}
180
+ <button class="char" type="button" onclick={() => insertChar(ch)}>{ch}</button>
181
+ {/each}
182
+ </div>
183
+ </div>
184
+ {/each}
185
+ </div>
186
+ </div>
187
+
188
+ <div class="workspace">
189
+ <div class="pane">
190
+ <div class="pane-header">
191
+ <span class="pane-title">Input</span>
192
+ <span class="meta">{rawInput.length} chars · {lineCount} lines</span>
193
+ </div>
194
+ <textarea
195
+ bind:this={textarea}
196
+ bind:value={rawInput}
197
+ class="input"
198
+ placeholder="Type or paste an ASCII / Unicode diagram…"
199
+ spellcheck="false"
200
+ ></textarea>
201
+ </div>
202
+
203
+ <div class="pane">
204
+ <div class="pane-header">
205
+ <span class="pane-title">Preview</span>
206
+ <div class="exports">
207
+ <button
208
+ class="chip"
209
+ class:on={copiedFormat === 'text'}
210
+ type="button"
211
+ onclick={() => copyAs('text')}
212
+ >
213
+ {copiedFormat === 'text' ? '✓ copied' : 'copy text'}
214
+ </button>
215
+ <button
216
+ class="chip"
217
+ class:on={copiedFormat === 'svelte'}
218
+ type="button"
219
+ onclick={() => copyAs('svelte')}
220
+ >
221
+ {copiedFormat === 'svelte' ? '✓ copied' : 'copy svelte'}
222
+ </button>
223
+ <button
224
+ class="chip"
225
+ class:on={copiedFormat === 'svx'}
226
+ type="button"
227
+ onclick={() => copyAs('svx')}
228
+ >
229
+ {copiedFormat === 'svx' ? '✓ copied' : 'copy .svx'}
230
+ </button>
231
+ </div>
232
+ </div>
233
+ <div class="preview">
234
+ <AsciiDiagram content={rawInput} showCopy={false} />
235
+ </div>
236
+ </div>
237
+ </div>
238
+ </div>
239
+
240
+ <style>
241
+ .editor {
242
+ display: flex;
243
+ flex-direction: column;
244
+ gap: 1rem;
245
+ width: 100%;
246
+ min-width: 0;
247
+ font-size: 0.875rem;
248
+ }
249
+
250
+ .toolbar,
251
+ .palette {
252
+ display: flex;
253
+ flex-direction: column;
254
+ gap: 0.6rem;
255
+ padding: 0.75rem 1rem;
256
+ border: 1px dashed var(--graph-frame, oklch(0.6 0 0 / 0.5));
257
+ }
258
+
259
+ .group {
260
+ display: flex;
261
+ align-items: center;
262
+ gap: 0.75rem;
263
+ flex-wrap: wrap;
264
+ }
265
+
266
+ .label {
267
+ font-size: 0.75rem;
268
+ letter-spacing: 0.08em;
269
+ text-transform: uppercase;
270
+ color: var(--graph-muted, oklch(0.62 0 0));
271
+ }
272
+
273
+ .options {
274
+ display: flex;
275
+ gap: 0.4rem;
276
+ flex-wrap: wrap;
277
+ }
278
+
279
+ .chip {
280
+ padding: 0.2rem 0.55rem;
281
+ font-size: 0.75rem;
282
+ color: var(--graph-muted, oklch(0.62 0 0));
283
+ background: none;
284
+ border: 1px dashed var(--graph-frame, oklch(0.6 0 0 / 0.5));
285
+ border-radius: 0;
286
+ cursor: pointer;
287
+ }
288
+
289
+ .chip:hover {
290
+ color: var(--graph-foreground, oklch(0.93 0 0));
291
+ border-color: var(--graph-muted, oklch(0.62 0 0));
292
+ }
293
+
294
+ .chip.on {
295
+ color: var(--graph-accent, oklch(0.78 0.17 155));
296
+ border-color: var(--graph-accent, oklch(0.78 0.17 155));
297
+ }
298
+
299
+ .palette-header {
300
+ display: flex;
301
+ align-items: center;
302
+ justify-content: space-between;
303
+ gap: 1rem;
304
+ }
305
+
306
+ .glyph-groups {
307
+ display: flex;
308
+ flex-wrap: wrap;
309
+ gap: 0.8rem;
310
+ }
311
+
312
+ .glyph-group {
313
+ display: flex;
314
+ align-items: center;
315
+ gap: 0.35rem;
316
+ }
317
+
318
+ .group-label {
319
+ font-size: 0.7rem;
320
+ color: var(--graph-muted, oklch(0.62 0 0));
321
+ }
322
+
323
+ .chars {
324
+ display: flex;
325
+ gap: 0.2rem;
326
+ flex-wrap: wrap;
327
+ }
328
+
329
+ .char {
330
+ min-width: 22px;
331
+ padding: 0.15rem 0.35rem;
332
+ font-size: 0.75rem;
333
+ color: var(--graph-foreground, oklch(0.93 0 0));
334
+ background: none;
335
+ border: 1px solid transparent;
336
+ border-radius: 0;
337
+ cursor: pointer;
338
+ }
339
+
340
+ .char:hover {
341
+ color: var(--graph-accent, oklch(0.78 0.17 155));
342
+ border-color: var(--graph-frame, oklch(0.6 0 0 / 0.5));
343
+ }
344
+
345
+ .workspace {
346
+ display: grid;
347
+ grid-template-columns: 1fr 1fr;
348
+ gap: 1.25rem;
349
+ min-width: 0;
350
+ }
351
+
352
+ @media (max-width: 900px) {
353
+ .workspace {
354
+ grid-template-columns: 1fr;
355
+ }
356
+ }
357
+
358
+ .pane {
359
+ display: flex;
360
+ flex-direction: column;
361
+ min-width: 0;
362
+ border: 1px dashed var(--graph-frame, oklch(0.6 0 0 / 0.5));
363
+ }
364
+
365
+ .pane-header {
366
+ display: flex;
367
+ align-items: center;
368
+ justify-content: space-between;
369
+ gap: 1rem;
370
+ padding: 0.5rem 0.75rem;
371
+ border-bottom: 1px dashed var(--graph-frame, oklch(0.6 0 0 / 0.5));
372
+ }
373
+
374
+ .pane-title {
375
+ font-size: 0.75rem;
376
+ font-weight: 600;
377
+ letter-spacing: 0.08em;
378
+ text-transform: uppercase;
379
+ color: var(--graph-muted, oklch(0.62 0 0));
380
+ }
381
+
382
+ .meta {
383
+ font-size: 0.7rem;
384
+ color: var(--graph-muted, oklch(0.62 0 0));
385
+ }
386
+
387
+ .exports {
388
+ display: flex;
389
+ gap: 0.35rem;
390
+ }
391
+
392
+ .input {
393
+ width: 100%;
394
+ height: 380px;
395
+ padding: 1rem;
396
+ font-size: 0.825rem;
397
+ line-height: 1.4;
398
+ color: var(--graph-foreground, oklch(0.93 0 0));
399
+ background: transparent;
400
+ border: none;
401
+ outline: none;
402
+ box-sizing: border-box;
403
+ white-space: pre;
404
+ overflow-wrap: normal;
405
+ overflow-x: auto;
406
+ resize: vertical;
407
+ tab-size: 2;
408
+ }
409
+
410
+ .preview {
411
+ padding: 0.75rem;
412
+ overflow-x: auto;
413
+ }
414
+ </style>
@@ -0,0 +1,3 @@
1
+ declare const DiagramEditor: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type DiagramEditor = ReturnType<typeof DiagramEditor>;
3
+ export default DiagramEditor;
@@ -0,0 +1,125 @@
1
+ <script module lang="ts">
2
+ export interface MetricRow {
3
+ label?: string;
4
+ calls?: number | string;
5
+ time?: string;
6
+ }
7
+
8
+ export interface MetricsTableDiagramProps {
9
+ /** Caption on the top edge, uppercased. Default "COST". */
10
+ title?: string;
11
+ rows?: MetricRow[];
12
+ totalCalls?: number | string;
13
+ totalTime?: string;
14
+ /** Show the total row. Default true. */
15
+ showTotal?: boolean;
16
+ class?: string;
17
+ }
18
+ </script>
19
+
20
+ <script lang="ts">
21
+ import { dashEdge, padEnd, padRow, padStart, splitLabeledEdge, type ArtSeg } from './ascii';
22
+
23
+ let {
24
+ title = 'COST',
25
+ rows = [
26
+ { label: 'AST parse', calls: 120, time: '16m' },
27
+ { label: 'MDsveX compile', calls: 164, time: '16m' },
28
+ { label: 'Rune optimization', calls: 112, time: '18m' }
29
+ ],
30
+ totalCalls = 396,
31
+ totalTime = '~50m',
32
+ showTotal = true,
33
+ class: className = ''
34
+ }: MetricsTableDiagramProps = $props();
35
+
36
+ const WIDTH = 45;
37
+ const SEP = `| ${'- '.repeat(20).trimEnd()} |`;
38
+
39
+ const art = $derived.by((): ArtSeg[][] => {
40
+ const [edgeBefore, edgeLabel, edgeAfter] = splitLabeledEdge(WIDTH, title);
41
+ const lines: ArtSeg[][] = [
42
+ [{ text: edgeBefore }, { text: edgeLabel, cls: 'title' }, { text: edgeAfter }],
43
+ [{ text: padRow(WIDTH) }],
44
+ [{ text: `| ${padEnd('Tool calls', 23)}${padEnd('Time', 18)}|` }],
45
+ [{ text: SEP }]
46
+ ];
47
+
48
+ for (const row of rows) {
49
+ lines.push([
50
+ { text: `| ${padEnd(row.label ?? '', 18)}` },
51
+ { text: padStart(String(row.calls ?? ''), 5), cls: 'num' },
52
+ { text: ' ' },
53
+ { text: padEnd(row.time ?? '', 6), cls: 'time' },
54
+ { text: ' |' }
55
+ ]);
56
+ }
57
+
58
+ if (showTotal) {
59
+ lines.push([{ text: SEP }]);
60
+ lines.push([
61
+ { text: `| ${padEnd('Total', 18)}` },
62
+ { text: padStart(String(totalCalls), 5), cls: 'total-num' },
63
+ { text: ' ' },
64
+ { text: padEnd(totalTime, 6), cls: 'total-time' },
65
+ { text: ' |' }
66
+ ]);
67
+ }
68
+
69
+ lines.push([{ text: padRow(WIDTH) }]);
70
+ lines.push([{ text: dashEdge(WIDTH) }]);
71
+
72
+ return lines;
73
+ });
74
+ </script>
75
+
76
+ <div class="ledger {className}">
77
+ <div class="viewport">
78
+ <pre class="art"><code>{#each art as line, i (i)}{#each line as seg, j (j)}{#if seg.cls}<span class={seg.cls}>{seg.text}</span>{:else}{seg.text}{/if}{/each}{#if i < art.length - 1}{'\n'}{/if}{/each}</code></pre>
79
+ </div>
80
+ </div>
81
+
82
+ <style>
83
+ .ledger {
84
+ display: inline-flex;
85
+ flex-direction: column;
86
+ min-width: 0;
87
+ font-size: 0.875rem;
88
+ }
89
+
90
+ .viewport {
91
+ overflow-x: auto;
92
+ }
93
+
94
+ .art {
95
+ margin: 0;
96
+ font-size: 0.85rem;
97
+ line-height: 1.4;
98
+ color: var(--graph-frame, oklch(0.6 0 0 / 0.5));
99
+ white-space: pre;
100
+ }
101
+
102
+ .title {
103
+ color: var(--graph-accent, oklch(0.78 0.17 155));
104
+ font-weight: 600;
105
+ }
106
+
107
+ .num {
108
+ color: var(--graph-foreground, oklch(0.93 0 0));
109
+ font-weight: 500;
110
+ }
111
+
112
+ .time {
113
+ color: var(--graph-muted, oklch(0.62 0 0));
114
+ }
115
+
116
+ .total-num {
117
+ color: var(--graph-foreground, oklch(0.93 0 0));
118
+ font-weight: 600;
119
+ }
120
+
121
+ .total-time {
122
+ color: var(--graph-accent, oklch(0.78 0.17 155));
123
+ font-weight: 600;
124
+ }
125
+ </style>
@@ -0,0 +1,18 @@
1
+ export interface MetricRow {
2
+ label?: string;
3
+ calls?: number | string;
4
+ time?: string;
5
+ }
6
+ export interface MetricsTableDiagramProps {
7
+ /** Caption on the top edge, uppercased. Default "COST". */
8
+ title?: string;
9
+ rows?: MetricRow[];
10
+ totalCalls?: number | string;
11
+ totalTime?: string;
12
+ /** Show the total row. Default true. */
13
+ showTotal?: boolean;
14
+ class?: string;
15
+ }
16
+ declare const MetricsTableDiagram: import("svelte").Component<MetricsTableDiagramProps, {}, "">;
17
+ type MetricsTableDiagram = ReturnType<typeof MetricsTableDiagram>;
18
+ export default MetricsTableDiagram;