@kekonic/diagrams-ui 1.0.0-rc.4
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.
- package/LICENSE +21 -0
- package/README.md +34 -0
- package/dist/KDiagramLive-CnGvR1jR.mjs +40 -0
- package/dist/KDiagramLive-CnGvR1jR.mjs.map +1 -0
- package/dist/KDiagramLive-Cx3hrc2_.d.mts +29 -0
- package/dist/index.d.mts +17 -0
- package/dist/index.mjs +23 -0
- package/dist/index.mjs.map +1 -0
- package/dist/playground.d.mts +57 -0
- package/dist/playground.mjs +226 -0
- package/dist/playground.mjs.map +1 -0
- package/dist/shiki/highlight.d.mts +10 -0
- package/dist/shiki/highlight.mjs +27 -0
- package/dist/shiki/highlight.mjs.map +1 -0
- package/dist/shiki/kdiagram.d.mts +223 -0
- package/dist/shiki/kdiagram.mjs +381 -0
- package/dist/shiki/kdiagram.mjs.map +1 -0
- package/package.json +82 -0
- package/src/chrome/tokens.css +109 -0
- package/src/diagram/KDiagramLive.tsx +59 -0
- package/src/diagram/KDiagramPlayground.tsx +288 -0
- package/src/diagram/live.css +13 -0
- package/src/diagram/playground.css +261 -0
- package/src/diagram/render-static.ts +28 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
.kd-play {
|
|
2
|
+
position: relative;
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
/* Prefer explicit height from the component; fall back for embeds without one. */
|
|
6
|
+
min-height: var(--kd-play-editor-min, 280px);
|
|
7
|
+
border: 1px solid var(--border);
|
|
8
|
+
background: var(--bg-panel);
|
|
9
|
+
color: var(--text);
|
|
10
|
+
overflow: hidden;
|
|
11
|
+
font-family: var(--font-ui, inherit);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.kd-play__sr-only {
|
|
15
|
+
position: absolute;
|
|
16
|
+
width: 1px;
|
|
17
|
+
height: 1px;
|
|
18
|
+
padding: 0;
|
|
19
|
+
margin: -1px;
|
|
20
|
+
overflow: hidden;
|
|
21
|
+
clip: rect(0, 0, 0, 0);
|
|
22
|
+
white-space: nowrap;
|
|
23
|
+
border: 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.kd-play__pane-bar {
|
|
27
|
+
display: flex;
|
|
28
|
+
flex: 0 0 auto;
|
|
29
|
+
align-items: center;
|
|
30
|
+
justify-content: space-between;
|
|
31
|
+
gap: 0.5rem;
|
|
32
|
+
padding: 0.3rem 0.55rem;
|
|
33
|
+
border-bottom: 1px solid var(--border-soft);
|
|
34
|
+
background: var(--bg-input);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.kd-play__label {
|
|
38
|
+
font-size: 0.68rem;
|
|
39
|
+
font-weight: 500;
|
|
40
|
+
letter-spacing: 0.04em;
|
|
41
|
+
text-transform: uppercase;
|
|
42
|
+
color: var(--text-faint);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.kd-play__actions {
|
|
46
|
+
display: flex;
|
|
47
|
+
flex-wrap: wrap;
|
|
48
|
+
justify-content: flex-end;
|
|
49
|
+
gap: 0.3rem;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.kd-play__btn {
|
|
53
|
+
appearance: none;
|
|
54
|
+
border: 1px solid var(--border);
|
|
55
|
+
background: var(--bg-input);
|
|
56
|
+
color: var(--text-muted);
|
|
57
|
+
font: inherit;
|
|
58
|
+
font-size: 0.72rem;
|
|
59
|
+
padding: 0.15rem 0.45rem;
|
|
60
|
+
cursor: pointer;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.kd-play__btn:hover {
|
|
64
|
+
color: var(--text);
|
|
65
|
+
background: color-mix(in oklch, var(--text) 6%, var(--bg-input));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.kd-play__btn:focus-visible {
|
|
69
|
+
color: var(--text);
|
|
70
|
+
box-shadow: inset 0 0 0 1px color-mix(in oklch, var(--accent) 55%, var(--border));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.kd-play__btn:disabled {
|
|
74
|
+
opacity: 0.45;
|
|
75
|
+
cursor: default;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.kd-play__body {
|
|
79
|
+
display: grid;
|
|
80
|
+
flex: 1 1 auto;
|
|
81
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
82
|
+
grid-template-rows: minmax(0, 1fr);
|
|
83
|
+
min-height: 0;
|
|
84
|
+
align-items: stretch;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.kd-play__body[data-layout="stacked"] {
|
|
88
|
+
grid-template-columns: 1fr;
|
|
89
|
+
grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* Gallery: diagram owns the stage; source is a compact strip underneath. */
|
|
93
|
+
.kd-play__body[data-layout="gallery"] {
|
|
94
|
+
grid-template-columns: 1fr;
|
|
95
|
+
grid-template-rows: minmax(0, 1fr) minmax(var(--kd-play-editor-min, 180px), 0.38fr);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.kd-play__body[data-layout="gallery"] .kd-play__diagram {
|
|
99
|
+
order: -1;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.kd-play__body[data-layout="gallery"] .kd-play__source {
|
|
103
|
+
border-right: 0;
|
|
104
|
+
border-top: 1px solid var(--border-soft);
|
|
105
|
+
border-bottom: 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/*
|
|
109
|
+
Kill Starlight sibling-gap (A + B { margin-top }) and pre/code chrome that
|
|
110
|
+
otherwise turn the highlight layer into a short bordered card + grey strip
|
|
111
|
+
above the diagram column.
|
|
112
|
+
*/
|
|
113
|
+
.kd-play__body > *,
|
|
114
|
+
.kd-play__source > *,
|
|
115
|
+
.kd-play__diagram > *,
|
|
116
|
+
.kd-play__editor > * {
|
|
117
|
+
margin-top: 0 !important;
|
|
118
|
+
margin-bottom: 0 !important;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.kd-play__source {
|
|
122
|
+
display: flex;
|
|
123
|
+
flex-direction: column;
|
|
124
|
+
min-width: 0;
|
|
125
|
+
min-height: 0;
|
|
126
|
+
border-right: 1px solid var(--border-soft);
|
|
127
|
+
background: var(--bg-input);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.kd-play__body[data-layout="stacked"] .kd-play__source {
|
|
131
|
+
border-right: 0;
|
|
132
|
+
border-bottom: 1px solid var(--border-soft);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.kd-play__editor {
|
|
136
|
+
position: relative;
|
|
137
|
+
flex: 1 1 auto;
|
|
138
|
+
min-height: 0;
|
|
139
|
+
overflow: hidden;
|
|
140
|
+
background: var(--bg-input);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.kd-play__highlight,
|
|
144
|
+
.kd-play__input {
|
|
145
|
+
margin: 0;
|
|
146
|
+
padding: 0.75rem 0.85rem;
|
|
147
|
+
border: 0;
|
|
148
|
+
font-family: var(--font-mono, ui-monospace, monospace);
|
|
149
|
+
font-size: 0.8rem;
|
|
150
|
+
line-height: 1.55;
|
|
151
|
+
tab-size: 2;
|
|
152
|
+
white-space: pre;
|
|
153
|
+
word-wrap: normal;
|
|
154
|
+
overflow-wrap: normal;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.kd-play__highlight {
|
|
158
|
+
position: absolute;
|
|
159
|
+
inset: 0;
|
|
160
|
+
overflow: auto;
|
|
161
|
+
pointer-events: none;
|
|
162
|
+
background: transparent;
|
|
163
|
+
color: var(--text-muted);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.kd-play__editor:not(:has(.kd-play__input)) .kd-play__highlight {
|
|
167
|
+
pointer-events: auto;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/* Neutralize host markdown / Expressive Code styles on the highlight surface. */
|
|
171
|
+
.kd-play__highlight :is(pre, code),
|
|
172
|
+
.kd-play__highlight .shiki {
|
|
173
|
+
all: unset;
|
|
174
|
+
display: block;
|
|
175
|
+
margin: 0 !important;
|
|
176
|
+
padding: 0 !important;
|
|
177
|
+
border: 0 !important;
|
|
178
|
+
background: transparent !important;
|
|
179
|
+
box-shadow: none !important;
|
|
180
|
+
font: inherit;
|
|
181
|
+
color: inherit;
|
|
182
|
+
white-space: pre;
|
|
183
|
+
tab-size: inherit;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.kd-play__highlight .shiki {
|
|
187
|
+
min-height: 100%;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/* Dual-theme tokens from highlightKDiagram (`defaultColor: false`). */
|
|
191
|
+
.kd-play__highlight .shiki span {
|
|
192
|
+
color: var(--shiki-dark);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
:root[data-theme="light"] .kd-play__highlight .shiki span,
|
|
196
|
+
[data-theme="light"] .kd-play__highlight .shiki span {
|
|
197
|
+
color: var(--shiki-light);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.kd-play__input {
|
|
201
|
+
position: absolute;
|
|
202
|
+
inset: 0;
|
|
203
|
+
width: 100%;
|
|
204
|
+
height: 100%;
|
|
205
|
+
resize: none;
|
|
206
|
+
overflow: auto;
|
|
207
|
+
background: transparent;
|
|
208
|
+
color: transparent;
|
|
209
|
+
caret-color: var(--text);
|
|
210
|
+
outline: none;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.kd-play__input::selection {
|
|
214
|
+
background: color-mix(in oklch, var(--accent) 28%, transparent);
|
|
215
|
+
color: transparent;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.kd-play__diagram {
|
|
219
|
+
position: relative;
|
|
220
|
+
z-index: 0;
|
|
221
|
+
display: flex;
|
|
222
|
+
flex-direction: column;
|
|
223
|
+
min-width: 0;
|
|
224
|
+
min-height: 0;
|
|
225
|
+
overflow: hidden;
|
|
226
|
+
isolation: isolate;
|
|
227
|
+
background: var(--bg);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/* Diagram pane = bare KDiagramLive (floating controls only — no double chrome). */
|
|
231
|
+
.kd-play__diagram .kd-live,
|
|
232
|
+
.kd-play__diagram k-diagram {
|
|
233
|
+
border: 0;
|
|
234
|
+
flex: 1 1 auto;
|
|
235
|
+
min-height: 0;
|
|
236
|
+
height: 100%;
|
|
237
|
+
/* Contain live overlays inside the diagram column of the split. */
|
|
238
|
+
isolation: isolate;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.kd-play__fallback {
|
|
242
|
+
display: flex;
|
|
243
|
+
flex: 1;
|
|
244
|
+
align-items: center;
|
|
245
|
+
justify-content: center;
|
|
246
|
+
min-height: 0;
|
|
247
|
+
color: var(--text-faint);
|
|
248
|
+
font-size: 0.8rem;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
@media (max-width: 720px) {
|
|
252
|
+
.kd-play__body[data-layout="split"] {
|
|
253
|
+
grid-template-columns: 1fr;
|
|
254
|
+
grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.kd-play__body[data-layout="split"] .kd-play__source {
|
|
258
|
+
border-right: 0;
|
|
259
|
+
border-bottom: 1px solid var(--border-soft);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { RenderOptions, RenderResult } from "@kekonic/diagrams";
|
|
2
|
+
|
|
3
|
+
export type StaticDiagramOptions = RenderOptions & {
|
|
4
|
+
/** Prefer snapshot CSS vars so SVGs look correct outside live theme CSS. */
|
|
5
|
+
snapshotTheme?: boolean;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Server-safe SVG render for docs/SSR. Uses the shared font measurer in Node.
|
|
10
|
+
*/
|
|
11
|
+
export async function renderKDiagramSvg(
|
|
12
|
+
source: string,
|
|
13
|
+
options: StaticDiagramOptions = {},
|
|
14
|
+
): Promise<{
|
|
15
|
+
svg: string;
|
|
16
|
+
diagnostics: RenderResult["diagnostics"];
|
|
17
|
+
}> {
|
|
18
|
+
const { KDiagram } = await import("@kekonic/diagrams");
|
|
19
|
+
const { snapshotTheme = true, theme = "dark", ...rest } = options;
|
|
20
|
+
const result = await KDiagram.renderToSvg(source, {
|
|
21
|
+
...rest,
|
|
22
|
+
theme,
|
|
23
|
+
snapshotTheme,
|
|
24
|
+
// Chromeless by default — opt into title/legend/etc. via options or the DSL.
|
|
25
|
+
presentation: rest.presentation,
|
|
26
|
+
});
|
|
27
|
+
return { svg: result.svg ?? "", diagnostics: result.diagnostics };
|
|
28
|
+
}
|