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,288 +0,0 @@
1
- import { useEffect, useRef, type ReactNode, type RefObject } from "react";
2
- import type { CompositionComponent } from "../../composition/types.ts";
3
- import { componentLabels } from "../lib/model.ts";
4
- import mark from "../assets/konpeki-mark.png";
5
- import { BuildOrb } from "./BuildOrb.tsx";
6
-
7
- const dockItems: {
8
- kind: CompositionComponent["kind"];
9
- }[] = [
10
- { kind: "text-block" },
11
- { kind: "diagram" },
12
- { kind: "chart" },
13
- { kind: "image" },
14
- { kind: "table" },
15
- ];
16
-
17
- function DockIcon({
18
- kind,
19
- }: {
20
- kind: CompositionComponent["kind"] | "select";
21
- }) {
22
- return (
23
- <svg className="dock-glyph" viewBox="0 0 24 24" aria-hidden="true">
24
- {kind === "select" ? (
25
- <path d="M5 3.8 18 12l-6.2 1.2L8.6 19Z" />
26
- ) : kind === "text-block" ? (
27
- <path d="M5 6h14M5 10h14M5 14h10M5 18h12" />
28
- ) : kind === "chart" ? (
29
- <>
30
- <path d="M5 19V5M5 19h14" />
31
- <path d="M8 16v-4M12 16V8M16 16v-7" />
32
- </>
33
- ) : kind === "diagram" ? (
34
- <>
35
- <rect x="3" y="5" width="6" height="5" rx="1" />
36
- <rect x="15" y="16" width="6" height="5" rx="1" />
37
- <path d="M9 8h9v8m-2.5-2.5L18 16l2.5-2.5" />
38
- </>
39
- ) : kind === "image" ? (
40
- <>
41
- <rect x="4" y="5" width="16" height="14" rx="1" />
42
- <circle cx="15.5" cy="9" r="1.5" />
43
- <path d="m6 17 4.5-5 3 3 2-2 2.5 4" />
44
- </>
45
- ) : kind === "table" ? (
46
- <>
47
- <rect x="3" y="5" width="18" height="14" rx="1" />
48
- <path d="M3 10h18M9 5v14M15 5v14" />
49
- </>
50
- ) : (
51
- <path d="M5 7h14M5 12h10M5 17h14" />
52
- )}
53
- </svg>
54
- );
55
- }
56
-
57
- export function WorkspaceChrome({
58
- title,
59
- titleRef,
60
- titleError,
61
- selectedKind,
62
- onTitle,
63
- onEditEnd,
64
- onExportPNG,
65
- exporting,
66
- onPresent,
67
- fileStatus,
68
- building,
69
- buildState,
70
- onBuild,
71
- browserTools,
72
- onSelectTool,
73
- onComponentTool,
74
- leftCollapsed,
75
- onToggleLeftPanel,
76
- children,
77
- }: {
78
- children: ReactNode;
79
- leftCollapsed: boolean;
80
- onToggleLeftPanel: () => void;
81
- title: string;
82
- titleRef: RefObject<HTMLInputElement | null>;
83
- titleError: boolean;
84
- selectedKind?: CompositionComponent["kind"];
85
- onTitle: (title: string, mergeKey?: string) => void;
86
- onEditEnd: () => void;
87
- onExportPNG: () => void;
88
- exporting: boolean;
89
- onPresent: () => void;
90
- fileStatus?: "loading" | "saved" | "saving" | "conflict" | "error";
91
- building: boolean;
92
- buildState?: "ready" | "working";
93
- onBuild?: () => void;
94
- browserTools?: {
95
- example: boolean;
96
- saveMessage: string;
97
- onImportJSON: (file: File) => void;
98
- onDownloadJSON: () => void;
99
- onStartBlank: () => void;
100
- onReset: () => void;
101
- };
102
- onSelectTool: () => void;
103
- onComponentTool: (kind: CompositionComponent["kind"]) => void;
104
- }) {
105
- const browserMenu = useRef<HTMLDetailsElement>(null);
106
- const importInput = useRef<HTMLInputElement>(null);
107
- function closeBrowserMenu() {
108
- if (browserMenu.current) browserMenu.current.open = false;
109
- }
110
- useEffect(() => {
111
- if (leftCollapsed) closeBrowserMenu();
112
- }, [leftCollapsed]);
113
- return (
114
- <>
115
- <div className={`left-sidebar${leftCollapsed ? " collapsed" : ""}`}>
116
- <header className="document-island" aria-label="Document controls">
117
- <img src={mark} alt="Konpeki" />
118
- <label className="document-title" inert={leftCollapsed}>
119
- <span className="sr-only">Composition title</span>
120
- <input
121
- ref={titleRef}
122
- aria-invalid={titleError || undefined}
123
- aria-describedby={titleError ? "title-error" : undefined}
124
- name="composition-title"
125
- autoComplete="off"
126
- disabled={building}
127
- value={title}
128
- onChange={(event) => onTitle(event.target.value, "title")}
129
- onBlur={onEditEnd}
130
- />
131
- </label>
132
- {titleError && (
133
- <span className="document-title-error" id="title-error">
134
- Enter a title.
135
- </span>
136
- )}
137
- {fileStatus && fileStatus !== "saved" && (
138
- <span
139
- className={`file-status ${fileStatus}${leftCollapsed ? " sr-only" : ""}`}
140
- role="status"
141
- aria-live="polite"
142
- title={fileStatus === "conflict"
143
- ? "The file changed elsewhere while this browser has edits."
144
- : undefined}
145
- >
146
- {fileStatus === "loading" ? "Opening"
147
- : fileStatus === "saving" ? "Saving"
148
- : fileStatus === "conflict" ? "Conflict" : "Save error"}
149
- </span>
150
- )}
151
- <button type="button" className="panel-toggle"
152
- aria-label={leftCollapsed ? "Expand left panel" : "Collapse left panel"}
153
- aria-expanded={!leftCollapsed}
154
- onClick={onToggleLeftPanel}>
155
- <svg className="panel-collapse-icon" viewBox="0 0 24 24" aria-hidden="true">
156
- <rect x="3" y="4" width="18" height="16" rx="2" />
157
- <path d={leftCollapsed ? "M9 4v16M13 9l3 3-3 3" : "M9 4v16M16 9l-3 3 3 3"} />
158
- </svg>
159
- </button>
160
- </header>
161
-
162
- <div className="editor-content" inert={building} aria-busy={building}>
163
- {children}
164
- </div>
165
-
166
- <div className="action-island" aria-label="Document actions" inert={leftCollapsed}>
167
- <button
168
- type="button"
169
- className="icon-only"
170
- aria-label="Export PNG"
171
- title="Export active page as PNG"
172
- disabled={exporting || building}
173
- onClick={onExportPNG}
174
- >
175
- <svg viewBox="0 0 24 24" aria-hidden="true">
176
- <rect x="4" y="4" width="16" height="12" rx="2" />
177
- <path d="m7 14 3.5-4 3 3 2-2 2.5 3M12 16v5m-3-3 3 3 3-3" />
178
- </svg>
179
- </button>
180
- <button type="button" className="icon-only" aria-label="Present" title="Present" onClick={onPresent} disabled={building}>
181
- <svg viewBox="0 0 24 24" aria-hidden="true">
182
- <rect x="3" y="4" width="18" height="12" rx="2" />
183
- <path d="M12 16v5m-4 0h8M10 7l5 3-5 3Z" />
184
- </svg>
185
- </button>
186
- {browserTools && (
187
- <details className="browser-menu" ref={browserMenu}>
188
- <summary>Browser</summary>
189
- <div className="browser-menu-popover">
190
- <strong>Browser playground</strong>
191
- <p role="status">
192
- {browserTools.saveMessage}
193
- {" "}Nothing syncs automatically.
194
- </p>
195
- <div className="browser-menu-actions">
196
- <button type="button" onClick={() => importInput.current?.click()}>
197
- Import JSON
198
- </button>
199
- <input
200
- ref={importInput}
201
- hidden
202
- type="file"
203
- accept="application/json,.json"
204
- aria-label="Choose composition JSON"
205
- onChange={(event) => {
206
- const file = event.target.files?.[0];
207
- event.target.value = "";
208
- if (!file) return;
209
- closeBrowserMenu();
210
- browserTools.onImportJSON(file);
211
- }}
212
- />
213
- <button type="button" onClick={() => {
214
- closeBrowserMenu();
215
- browserTools.onDownloadJSON();
216
- }}>
217
- Download JSON
218
- </button>
219
- <button type="button" onClick={() => {
220
- closeBrowserMenu();
221
- browserTools.onStartBlank();
222
- }}>
223
- Start blank
224
- </button>
225
- <button type="button" onClick={() => {
226
- closeBrowserMenu();
227
- browserTools.onReset();
228
- }}>
229
- {browserTools.example ? "Reset example" : "Reset local draft"}
230
- </button>
231
- </div>
232
- <p className="browser-agent-handoff">
233
- To continue with a coding agent, download the editable JSON and
234
- follow the{" "}
235
- <a
236
- href="https://github.com/vcfgdev/konpeki/blob/main/SETUP.md"
237
- target="_blank"
238
- rel="noreferrer"
239
- >
240
- setup guidance
241
- </a>
242
- .
243
- </p>
244
- </div>
245
- </details>
246
- )}
247
- {onBuild && (
248
- <button
249
- type="button"
250
- className={`primary build-button ${building ? "building" : ""}`}
251
- disabled={fileStatus !== "saved" || building}
252
- aria-busy={building}
253
- onClick={onBuild}
254
- >
255
- <BuildOrb active={building} />
256
- <span className="build-label">{buildState === "ready" ? "Request ready" : buildState === "working" ? "Agent working" : "Build it"}</span>
257
- </button>
258
- )}
259
- </div>
260
- </div>
261
-
262
- <nav className="component-dock" aria-label="Canvas tools" inert={building}>
263
- <button
264
- type="button"
265
- className={!selectedKind ? "active" : ""}
266
- aria-pressed={!selectedKind}
267
- onClick={onSelectTool}
268
- >
269
- <DockIcon kind="select" />
270
- <span>Select</span>
271
- </button>
272
- {dockItems.map(({ kind }) => (
273
- <button
274
- key={kind}
275
- type="button"
276
- className={selectedKind === kind ? "active" : ""}
277
- aria-pressed={selectedKind === kind}
278
- title={`Add or select ${componentLabels[kind]}`}
279
- onClick={() => onComponentTool(kind)}
280
- >
281
- <DockIcon kind={kind} />
282
- <span>{componentLabels[kind]}</span>
283
- </button>
284
- ))}
285
- </nav>
286
- </>
287
- );
288
- }
@@ -1,53 +0,0 @@
1
- import { useId, type ReactNode } from "react";
2
- export function Field({
3
- label,
4
- children,
5
- }: {
6
- label: string;
7
- children: ReactNode;
8
- }) {
9
- return (
10
- <label className="field">
11
- <span>{label}</span>
12
- {children}
13
- </label>
14
- );
15
- }
16
- export function Select({
17
- label,
18
- value,
19
- options,
20
- optionLabels,
21
- onChange,
22
- }: {
23
- label: string;
24
- value: string;
25
- options: readonly string[];
26
- optionLabels?: Partial<Record<string, string>>;
27
- onChange: (value: string) => void;
28
- }) {
29
- const id = useId();
30
- return (
31
- <Field label={label}>
32
- <select
33
- id={id}
34
- name={label}
35
- autoComplete="off"
36
- value={value}
37
- onChange={(e) => onChange(e.target.value)}
38
- >
39
- {options.map((option) => (
40
- <option key={option} value={option}>
41
- {optionLabels?.[option] ?? humanize(option)}
42
- </option>
43
- ))}
44
- </select>
45
- </Field>
46
- );
47
- }
48
- export function humanize(value: string) {
49
- return value
50
- .replace(/([a-z])([A-Z])/g, "$1 $2")
51
- .replaceAll("-", " ")
52
- .replace(/^./, (c) => c.toUpperCase());
53
- }