konpeki 0.3.0 → 0.4.0

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 (162) hide show
  1. package/AGENTS.md +21 -28
  2. package/AUTHORING.md +68 -229
  3. package/CONTRIBUTING.md +10 -23
  4. package/README.md +96 -87
  5. package/SETUP.md +50 -114
  6. package/docs/development.md +43 -248
  7. package/docs/workflow.md +6 -108
  8. package/html/README.md +140 -0
  9. package/html/browser.ts +103 -0
  10. package/html/document.ts +38 -0
  11. package/html/floor.ts +34 -0
  12. package/html/index.html +5 -0
  13. package/html/inspect.ts +313 -0
  14. package/html/preview.css +62 -0
  15. package/html/preview.tsx +463 -0
  16. package/html/review-hints.ts +63 -0
  17. package/html/server.ts +99 -0
  18. package/html/source.ts +104 -0
  19. package/html/starter.ts +6 -0
  20. package/html/theme-authoring.md +176 -0
  21. package/html/theme.md +61 -0
  22. package/index.html +9 -9
  23. package/package.json +21 -35
  24. package/plugin.json +1 -1
  25. package/public/og.png +0 -0
  26. package/runtime/browser-B-29TH1a.mjs +595 -0
  27. package/runtime/floor-Cmk7G3pU.mjs +41 -0
  28. package/runtime/konpeki.mjs +90 -1410
  29. package/runtime/server-BAqC_5WD.mjs +2 -0
  30. package/runtime/server-DfRpfcY9.mjs +205 -0
  31. package/runtime/source-B_Ui9tMp.mjs +141 -0
  32. package/runtime/source-CZQq9GUO.mjs +2 -0
  33. package/skills/konpeki/SKILL.md +88 -172
  34. package/skills/konpeki/assets/blank.html +17 -0
  35. package/skills/konpeki/floor.md +76 -0
  36. package/skills/konpeki/references/cover.md +27 -0
  37. package/skills/konpeki/references/long-document.md +40 -0
  38. package/skills/konpeki/references/one-pager.md +27 -0
  39. package/skills/konpeki/references/patterns.md +118 -0
  40. package/skills/konpeki/references/resume.md +28 -0
  41. package/skills/konpeki/references/slides.md +28 -0
  42. package/skills/konpeki/scripts/ensure-runtime.mjs +10 -31
  43. package/skills/konpeki/scripts/prepare-document.mjs +25 -14
  44. package/src/components/PageBoard.tsx +156 -0
  45. package/src/lib/alignment.ts +21 -0
  46. package/src/lib/page-board.ts +25 -0
  47. package/src/lib/review-position.ts +19 -0
  48. package/src/styles/base.css +4 -6
  49. package/src/styles/feedback.css +97 -61
  50. package/src/styles/shell.css +95 -323
  51. package/theme-base.css +90 -0
  52. package/theme.css +56 -0
  53. package/vite.config.ts +2 -5
  54. package/composition/README.md +0 -156
  55. package/composition/compile.ts +0 -227
  56. package/composition/document.ts +0 -600
  57. package/composition/schema.json +0 -3001
  58. package/composition/schema.ts +0 -437
  59. package/composition/theme-tokens.ts +0 -16
  60. package/composition/types.ts +0 -269
  61. package/composition/validate.ts +0 -226
  62. package/composition/vector.ts +0 -143
  63. package/composition/visualizations.ts +0 -319
  64. package/design/README.md +0 -17
  65. package/design/palettes/README.md +0 -14
  66. package/design/palettes/base.ts +0 -14
  67. package/design/palettes/candidates.ts +0 -19
  68. package/design/palettes/index.ts +0 -78
  69. package/design/review/color-theme.md +0 -44
  70. package/design/review/layout.md +0 -16
  71. package/design/review/text.md +0 -18
  72. package/design/review/typography.md +0 -15
  73. package/design/review/visuals.md +0 -31
  74. package/design/semantic-patterns.md +0 -43
  75. package/design/themes/README.md +0 -40
  76. package/design/themes/index.ts +0 -24
  77. package/design/visual-languages/technical-product.md +0 -17
  78. package/design/visual-review.md +0 -88
  79. package/lib/assets.d.ts +0 -8
  80. package/lib/charts.ts +0 -18
  81. package/lib/contrast.ts +0 -16
  82. package/lib/layouts.ts +0 -50
  83. package/lib/slide.tsx +0 -42
  84. package/lib/taste.ts +0 -17
  85. package/lib/text.tsx +0 -89
  86. package/lib/typeface.ts +0 -44
  87. package/scripts/migrate-react-page.ts +0 -120
  88. package/skills/konpeki/assets/blank.json +0 -23
  89. package/slides/README.md +0 -153
  90. package/slides/architecture/PROMPT.md +0 -31
  91. package/slides/architecture/index.tsx +0 -102
  92. package/slides/article-brief/PROMPT.md +0 -35
  93. package/slides/article-brief/index.tsx +0 -71
  94. package/slides/bar-chart/PROMPT.md +0 -39
  95. package/slides/bar-chart/index.tsx +0 -97
  96. package/slides/comparison/PROMPT.md +0 -29
  97. package/slides/comparison/index.tsx +0 -95
  98. package/slides/decision-memo/PROMPT.md +0 -34
  99. package/slides/decision-memo/index.tsx +0 -85
  100. package/slides/delivery-plan/PROMPT.md +0 -45
  101. package/slides/delivery-plan/index.tsx +0 -105
  102. package/slides/experiment/PROMPT.md +0 -44
  103. package/slides/experiment/index.tsx +0 -127
  104. package/slides/incident-workflow/PROMPT.md +0 -57
  105. package/slides/incident-workflow/index.tsx +0 -78
  106. package/slides/introducing-konpeki/PROMPT.md +0 -40
  107. package/slides/introducing-konpeki/README.md +0 -76
  108. package/slides/introducing-konpeki/SOURCE.md +0 -26
  109. package/slides/introducing-konpeki/author.ts +0 -165
  110. package/slides/introducing-konpeki/composition.json +0 -3270
  111. package/slides/line-chart/PROMPT.md +0 -40
  112. package/slides/line-chart/index.tsx +0 -72
  113. package/slides/migration/PROMPT.md +0 -38
  114. package/slides/migration/index.tsx +0 -89
  115. package/slides/og-images/PROMPT.md +0 -21
  116. package/slides/og-images/index.tsx +0 -76
  117. package/slides/product-introduction/PROMPT.md +0 -24
  118. package/slides/product-introduction/index.tsx +0 -105
  119. package/slides/research-brief/PROMPT.md +0 -40
  120. package/slides/research-brief/index.tsx +0 -104
  121. package/slides/results-explanation/PROMPT.md +0 -32
  122. package/slides/results-explanation/index.tsx +0 -96
  123. package/slides/retrospective/PROMPT.md +0 -43
  124. package/slides/retrospective/index.tsx +0 -105
  125. package/slides/sankey/PROMPT.md +0 -11
  126. package/slides/sankey/index.tsx +0 -93
  127. package/slides/teaching/PROMPT.md +0 -45
  128. package/slides/teaching/index.tsx +0 -124
  129. package/slides/vertical-bar-charts/PROMPT.md +0 -13
  130. package/slides/vertical-bar-charts/index.tsx +0 -97
  131. package/src/app/App.tsx +0 -820
  132. package/src/components/BuildOrb.tsx +0 -40
  133. package/src/components/Canvas.tsx +0 -1185
  134. package/src/components/DiagramTypeIcon.tsx +0 -78
  135. package/src/components/InspectorPanel.tsx +0 -773
  136. package/src/components/LeftPanel.tsx +0 -120
  137. package/src/components/PageSizePicker.tsx +0 -30
  138. package/src/components/Presentation.tsx +0 -105
  139. package/src/components/RevisionNotes.tsx +0 -56
  140. package/src/components/RightPanel.tsx +0 -201
  141. package/src/components/VectorOverflowWarning.tsx +0 -46
  142. package/src/components/WorkspaceChrome.tsx +0 -288
  143. package/src/components/ui.tsx +0 -53
  144. package/src/lib/examples/react-page-migration.json +0 -1295
  145. package/src/lib/examples.ts +0 -42
  146. package/src/lib/export-png.ts +0 -104
  147. package/src/lib/file-session.ts +0 -87
  148. package/src/lib/history.ts +0 -53
  149. package/src/lib/model.ts +0 -188
  150. package/src/lib/page-size.ts +0 -24
  151. package/src/lib/presentation.ts +0 -17
  152. package/src/lib/review.ts +0 -26
  153. package/src/lib/storage.ts +0 -71
  154. package/src/lib/theme.ts +0 -25
  155. package/src/lib/use-file-session.ts +0 -227
  156. package/src/main.tsx +0 -29
  157. package/src/styles/canvas.css +0 -299
  158. package/src/styles/chrome.css +0 -384
  159. package/src/styles/component-previews.css +0 -386
  160. package/src/styles/left-panel.css +0 -166
  161. package/src/styles/presentation.css +0 -72
  162. package/src/styles/right-panel.css +0 -1215
@@ -1,437 +0,0 @@
1
- import {
2
- authoringModes,
3
- componentKinds,
4
- compositionSchema,
5
- themeIds,
6
- themeModes,
7
- typographyIds,
8
- vectorElementKinds,
9
- } from "./types.ts";
10
- import { chartTemplates, diagramTypes } from "./visualizations.ts";
11
- import { tokensForAttribute } from "./theme-tokens.ts";
12
-
13
- const literalVectorAttribute = { oneOf: [{ type: "string", maxLength: 10000, pattern: "^(?!theme:)" }, { type: "number" }] };
14
-
15
- // Shared constrained vocabulary for schema validation and canvas controls.
16
- const alignment = ["start", "center", "end"];
17
- const titleStyle = ["plain", "prominent"];
18
- const border = ["none", "outline", "filled"];
19
- const colorScheme = [
20
- "monochrome",
21
- "accent-with-muted-context",
22
- "categorical",
23
- "sequential",
24
- "status",
25
- ];
26
- const emphasis = ["none", "primary", "latest-series", "exception"];
27
- const density = ["sparse", "standard"];
28
- export const tableStyles = [
29
- "header-rule",
30
- "top-header-bottom",
31
- "row-rules",
32
- "full-grid",
33
- ] as const;
34
- export type TableStyle = (typeof tableStyles)[number];
35
-
36
- export function tableAppearanceForStyle(style: TableStyle) {
37
- if (style === "top-header-bottom")
38
- return {
39
- header: "both" as const,
40
- grid: "none" as const,
41
- border: "none" as const,
42
- };
43
- if (style === "row-rules")
44
- return {
45
- header: "row" as const,
46
- grid: "rows" as const,
47
- border: "none" as const,
48
- };
49
- if (style === "full-grid")
50
- return {
51
- header: "row" as const,
52
- grid: "all" as const,
53
- border: "none" as const,
54
- };
55
- return {
56
- header: "row" as const,
57
- grid: "none" as const,
58
- border: "none" as const,
59
- };
60
- }
61
-
62
- export function tableStyleForAppearance(appearance?: {
63
- header?: string;
64
- grid?: string;
65
- border?: string;
66
- }): TableStyle {
67
- if (appearance?.grid === "all" || appearance?.header === "column")
68
- return "full-grid";
69
- if (appearance?.grid === "rows") return "row-rules";
70
- if (appearance?.header === "both" || appearance?.border === "outline")
71
- return "top-header-bottom";
72
- return "header-rule";
73
- }
74
-
75
- export const appearanceOptions: Record<
76
- (typeof componentKinds)[number],
77
- Record<string, readonly string[]>
78
- > = {
79
- "text-block": {
80
- role: ["title", "subtitle", "body", "caption", "footnote"],
81
- alignment,
82
- border,
83
- layout: [
84
- "single",
85
- "two-column",
86
- "three-column",
87
- "two-plus-two",
88
- "four-column",
89
- "one-plus-three",
90
- "three-plus-one",
91
- ],
92
- orientation: ["horizontal", "vertical"],
93
- purpose: ["narrative", "comparison", "emphasis"],
94
- treatment: ["plain", "subtle", "strong"],
95
- logicalOrder: [
96
- "none",
97
- "parallel",
98
- "progressive",
99
- "cyclical",
100
- "general-to-specific",
101
- "hierarchical",
102
- ],
103
- titleStyle,
104
- rule: ["none", "top", "bottom"],
105
- },
106
- chart: {
107
- template: chartTemplates,
108
- selection: ["auto", "explicit"],
109
- border,
110
- colorScheme,
111
- orientation: ["horizontal", "vertical"],
112
- emphasis,
113
- density,
114
- legend: ["none", "top", "right", "bottom"],
115
- },
116
- diagram: {
117
- type: diagramTypes,
118
- selection: ["auto", "explicit"],
119
- border,
120
- colorScheme,
121
- emphasis,
122
- density,
123
- },
124
- image: { border, fit: ["cover", "contain"] },
125
- table: {
126
- header: ["row", "none", "column", "both"],
127
- grid: ["none", "rows", "all"],
128
- border,
129
- colorScheme,
130
- density,
131
- },
132
- };
133
- const text = { type: "string", minLength: 1, pattern: "\\S" };
134
- const string = { type: "string" };
135
- const enumeration = (values: readonly string[]) => ({
136
- type: "string",
137
- enum: values,
138
- });
139
- const object = (
140
- properties: Record<string, unknown>,
141
- required = Object.keys(properties),
142
- ) => ({ type: "object", properties, required, additionalProperties: false });
143
- const array = (items: unknown, minItems = 0) => ({
144
- type: "array",
145
- items,
146
- minItems,
147
- });
148
- const ids = { ...array(text, 1), uniqueItems: true };
149
- const endpoint = object({ nodeId: text, slotId: text }, ["nodeId"]);
150
- const rect = object({
151
- x: { type: "number", minimum: 0, maximum: 4096 },
152
- y: { type: "number", minimum: 0, maximum: 4096 },
153
- width: { type: "number", exclusiveMinimum: 0, maximum: 4096 },
154
- height: { type: "number", exclusiveMinimum: 0, maximum: 4096 },
155
- });
156
- const visualBase = {
157
- viewBox: object({
158
- x: { type: "number" },
159
- y: { type: "number" },
160
- width: { type: "number", exclusiveMinimum: 0, maximum: 100000 },
161
- height: { type: "number", exclusiveMinimum: 0, maximum: 100000 },
162
- }),
163
- description: { ...text, maxLength: 1000 },
164
- fit: enumeration(["contain", "cover", "stretch"]),
165
- };
166
- const customVisual = {
167
- oneOf: [
168
- object(
169
- {
170
- format: { const: "vector" },
171
- elements: {
172
- ...array(
173
- object(
174
- {
175
- id: text,
176
- kind: enumeration(vectorElementKinds),
177
- parentId: text,
178
- attributes: {
179
- type: "object",
180
- maxProperties: 40,
181
- properties: Object.fromEntries(["fill", "stroke", "color", "font-family"].map((name) => [name, {
182
- anyOf: [literalVectorAttribute, { enum: tokensForAttribute(name).map((token) => `theme:${token}`) }],
183
- }])),
184
- additionalProperties: literalVectorAttribute,
185
- },
186
- text: { type: "string", maxLength: 10000 },
187
- },
188
- ["id", "kind", "attributes"],
189
- ),
190
- 0,
191
- ),
192
- maxItems: 2000,
193
- },
194
- ...visualBase,
195
- },
196
- ["format", "elements", "viewBox", "description"],
197
- ),
198
- object(
199
- {
200
- format: { const: "svg" },
201
- source: {
202
- type: "string",
203
- minLength: 1,
204
- maxLength: 500000,
205
- pattern: "^\\s*<svg(?:\\s|>)",
206
- },
207
- ...visualBase,
208
- },
209
- ["format", "source", "viewBox", "description"],
210
- ),
211
- ],
212
- };
213
- const topology = object({
214
- kind: { const: "explicit" },
215
- nodes: {
216
- ...array(object({
217
- id: text,
218
- slotId: text,
219
- visible: { type: "boolean" },
220
- preferredRect: rect,
221
- primitive: {
222
- oneOf: [
223
- object({
224
- kind: { const: "shape" },
225
- shape: enumeration(["rectangle", "rounded-rectangle", "circle", "line"]),
226
- color: enumeration(["ink", "muted", "accent"]),
227
- fill: enumeration(["none", "solid", "wash"]),
228
- }, ["kind", "shape"]),
229
- object({
230
- kind: { const: "icon" },
231
- name: text,
232
- style: enumeration(["outline", "filled"]),
233
- color: enumeration(["ink", "muted", "accent"]),
234
- }, ["kind"]),
235
- ],
236
- },
237
- }, ["id", "slotId"]), 1),
238
- maxItems: 24,
239
- },
240
- edges: {
241
- ...array(
242
- object({ from: text, to: text, label: { ...text, maxLength: 120 } }, [
243
- "from",
244
- "to",
245
- ]),
246
- 0,
247
- ),
248
- maxItems: 48,
249
- },
250
- });
251
- const components = componentKinds.map((kind) => {
252
- const options = appearanceOptions[kind];
253
- const requiredAppearance = [
254
- ...(kind === "chart" ? ["template"] : []),
255
- ...(kind === "text-block" ? ["role"] : []),
256
- ...(kind === "diagram" ? ["type"] : []),
257
- ];
258
- const component = object(
259
- {
260
- id: text,
261
- kind: { const: kind },
262
- preferredRect: rect,
263
- slotIds: ids,
264
- intent: string,
265
- customVisual,
266
- ...(kind === "text-block" ? {
267
- content: { type: "string", maxLength: 50000 },
268
- textStyle: object({
269
- size: { type: "number", minimum: 8, maximum: 240 },
270
- weight: { enum: [400, 500, 600] },
271
- lineHeight: { type: "number", minimum: 1, maximum: 3 },
272
- color: enumeration(["ink", "muted", "accent"]),
273
- font: enumeration(["heading", "body"]),
274
- }, []),
275
- } : {}),
276
- appearance: object(
277
- Object.fromEntries(
278
- Object.entries(options).map(([key, values]) => [
279
- key,
280
- enumeration(values),
281
- ]),
282
- ),
283
- requiredAppearance,
284
- ),
285
- ...(kind === "diagram" || kind === "chart" ? { topology } : {}),
286
- },
287
- [
288
- "id",
289
- "kind",
290
- "preferredRect",
291
- "slotIds",
292
- ...(requiredAppearance.length ? ["appearance"] : []),
293
- ],
294
- );
295
- return kind === "chart"
296
- ? {
297
- ...component,
298
- allOf: [{
299
- if: { required: ["topology"] },
300
- then: {
301
- properties: {
302
- appearance: {
303
- properties: { template: { const: "sankey" } },
304
- },
305
- },
306
- },
307
- }],
308
- }
309
- : component;
310
- });
311
- export const schema = {
312
- $schema: "https://json-schema.org/draft/2020-12/schema",
313
- $id: "https://vcfgdev.github.io/konpeki/composition/v1/schema.json",
314
- title: compositionSchema,
315
- ...object(
316
- {
317
- schema: { const: compositionSchema },
318
- title: text,
319
- authoringMode: enumeration(authoringModes),
320
- theme: object({
321
- id: enumeration(themeIds),
322
- mode: enumeration(themeModes),
323
- typography: enumeration(typographyIds),
324
- }, ["id", "mode"]),
325
- slides: array(
326
- object(
327
- {
328
- id: text,
329
- name: text,
330
- canvas: object({
331
- width: { type: "integer", minimum: 256, maximum: 4096 },
332
- height: { type: "integer", minimum: 256, maximum: 4096 },
333
- }),
334
- innerPadding: object({
335
- top: { type: "number", minimum: 0 },
336
- right: { type: "number", minimum: 0 },
337
- bottom: { type: "number", minimum: 0 },
338
- left: { type: "number", minimum: 0 },
339
- }),
340
- pageNumber: object({
341
- style: enumeration(["none", "01", "01/02"]),
342
- color: enumeration(["ink", "muted", "accent"]),
343
- }),
344
- audience: text,
345
- question: text,
346
- intendedViewingSize: enumeration(["presentation", "social", "article", "custom"]),
347
- contentSlots: array(
348
- {
349
- oneOf: [
350
- object({
351
- id: text,
352
- label: text,
353
- required: { type: "boolean" },
354
- instruction: text,
355
- role: enumeration([
356
- "takeaway",
357
- "body",
358
- "evidence",
359
- "comparison-item",
360
- "process-step",
361
- "entity",
362
- "image",
363
- "table",
364
- ]),
365
- }),
366
- object({
367
- id: text,
368
- label: text,
369
- required: { type: "boolean" },
370
- instruction: text,
371
- role: enumeration(["qualification", "source"]),
372
- targets: ids,
373
- }),
374
- ],
375
- },
376
- 0,
377
- ),
378
- components: array({ oneOf: components }, 0),
379
- groups: array(
380
- object({ id: text, label: string, childIds: ids }, [
381
- "id",
382
- "childIds",
383
- ]),
384
- ),
385
- readingOrder: {
386
- ...array(
387
- object({ kind: enumeration(["component", "group"]), id: text }),
388
- 0,
389
- ),
390
- uniqueItems: true,
391
- },
392
- paintOrder: { ...array(text, 0), uniqueItems: true },
393
- relationships: array(
394
- object(
395
- {
396
- id: text,
397
- kind: enumeration([
398
- "flows-to",
399
- "qualifies",
400
- "compares-with",
401
- "depends-on",
402
- "connects-to",
403
- ]),
404
- direction: enumeration([
405
- "forward",
406
- "bidirectional",
407
- "undirected",
408
- ]),
409
- from: endpoint,
410
- to: endpoint,
411
- label: string,
412
- },
413
- ["id", "kind", "direction", "from", "to"],
414
- ),
415
- ),
416
- },
417
- [
418
- "id",
419
- "name",
420
- "canvas",
421
- "audience",
422
- "question",
423
- "intendedViewingSize",
424
- "contentSlots",
425
- "components",
426
- "groups",
427
- "readingOrder",
428
- "paintOrder",
429
- "relationships",
430
- ],
431
- ),
432
- 1,
433
- ),
434
- },
435
- ["schema", "title", "slides"],
436
- ),
437
- };
@@ -1,16 +0,0 @@
1
- /** Explicit opt-in bindings. Literal SVG attributes always remain fixed. */
2
- export const colorTokens = ["ink", "muted", "background", "surface", "divider", "accent", "on-accent", "wash"] as const;
3
- export const fontTokens = ["heading-font", "body-font"] as const;
4
- export type ThemeToken = typeof colorTokens[number] | typeof fontTokens[number];
5
- export function tokensForAttribute(name: string): readonly ThemeToken[] {
6
- return name === "font-family" ? fontTokens
7
- : ["fill", "stroke", "color"].includes(name) ? colorTokens : [];
8
- }
9
- export function validThemeBinding(name: string, value: string | number): boolean {
10
- return typeof value !== "string" || !value.startsWith("theme:") ||
11
- tokensForAttribute(name).some((token) => value === `theme:${token}`);
12
- }
13
- export function resolveVectorAttribute(name: string, value: string | number): string | number {
14
- return typeof value === "string" && value.startsWith("theme:") && validThemeBinding(name, value)
15
- ? `var(--vector-${value.slice(6)})` : value;
16
- }