konpeki 0.2.0 → 0.3.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 (52) hide show
  1. package/AGENTS.md +1 -1
  2. package/CONTRIBUTING.md +36 -0
  3. package/README.md +81 -28
  4. package/SECURITY.md +22 -0
  5. package/SETUP.md +128 -51
  6. package/composition/README.md +16 -3
  7. package/composition/compile.ts +1 -1
  8. package/composition/schema.json +9 -0
  9. package/composition/schema.ts +3 -1
  10. package/composition/types.ts +3 -1
  11. package/design/themes/README.md +25 -7
  12. package/design/themes/index.ts +15 -4
  13. package/docs/development.md +79 -11
  14. package/docs/workflow.md +11 -4
  15. package/index.html +17 -1
  16. package/package.json +10 -2
  17. package/plugin.json +22 -0
  18. package/public/og.png +0 -0
  19. package/runtime/konpeki.mjs +41 -13
  20. package/skills/konpeki/SKILL.md +186 -0
  21. package/skills/konpeki/assets/blank.json +23 -0
  22. package/skills/konpeki/scripts/ensure-runtime.mjs +69 -0
  23. package/skills/konpeki/scripts/prepare-document.mjs +40 -0
  24. package/slides/README.md +35 -132
  25. package/slides/drawing-references.md +32 -0
  26. package/slides/github-cover/PROMPT.md +21 -0
  27. package/slides/github-cover/README.md +21 -0
  28. package/slides/github-cover/author.ts +67 -0
  29. package/slides/github-cover/composition.json +595 -0
  30. package/slides/introducing-konpeki/PROMPT.md +25 -14
  31. package/slides/introducing-konpeki/README.md +32 -42
  32. package/slides/introducing-konpeki/SOURCE.md +13 -14
  33. package/slides/introducing-konpeki/author.ts +44 -42
  34. package/slides/introducing-konpeki/composition.json +135 -135
  35. package/src/app/App.tsx +149 -56
  36. package/src/components/Canvas.tsx +9 -3
  37. package/src/components/InspectorPanel.tsx +104 -67
  38. package/src/components/RevisionNotes.tsx +6 -7
  39. package/src/components/RightPanel.tsx +42 -10
  40. package/src/components/VectorOverflowWarning.tsx +35 -8
  41. package/src/components/WorkspaceChrome.tsx +125 -10
  42. package/src/components/ui.tsx +95 -1
  43. package/src/lib/storage.ts +38 -10
  44. package/src/lib/use-file-session.ts +60 -38
  45. package/src/main.tsx +3 -0
  46. package/src/styles/base.css +7 -0
  47. package/src/styles/chrome.css +188 -25
  48. package/src/styles/feedback.css +101 -49
  49. package/src/styles/left-panel.css +27 -6
  50. package/src/styles/right-panel.css +114 -30
  51. package/src/styles/shell.css +96 -33
  52. package/.agents/skills/authoring-visuals/SKILL.md +0 -93
@@ -10,8 +10,73 @@
10
10
  margin-bottom: 16px;
11
11
  }
12
12
 
13
- .field-error {
14
- color: #a02020 !important;
13
+ .inspector-content:has(> .page-number-picker) legend {
14
+ margin-bottom: 7px;
15
+ }
16
+
17
+ .overflow-trigger {
18
+ display: flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ gap: 4px;
22
+ width: 48px;
23
+ height: 40px;
24
+ padding: 0;
25
+ color: #8a5409;
26
+ border: 0;
27
+ background: #fff5dd;
28
+ font-size: 12px;
29
+ }
30
+ .overflow-trigger:disabled {
31
+ visibility: hidden;
32
+ }
33
+ .overflow-trigger svg {
34
+ width: 18px;
35
+ height: 18px;
36
+ fill: none;
37
+ stroke: currentColor;
38
+ stroke-width: 1.5;
39
+ stroke-linecap: round;
40
+ stroke-linejoin: round;
41
+ }
42
+ .overflow-popover {
43
+ position: fixed;
44
+ inset: calc(var(--panel-top) + var(--panel-header-height) + 6px) 20px auto auto;
45
+ margin: 0;
46
+ width: min(328px, calc(100vw - 40px));
47
+ max-height: calc(100dvh - var(--panel-top) - 100px);
48
+ overflow: auto;
49
+ padding: 16px;
50
+ border: 1px solid var(--ui-border);
51
+ border-radius: 10px;
52
+ background: var(--ui-surface);
53
+ color: var(--ui-text);
54
+ box-shadow: 0 8px 32px #0000001a;
55
+ font-size: 13px;
56
+ line-height: 1.5;
57
+ }
58
+ .overflow-popover p {
59
+ margin: 8px 0 12px;
60
+ color: var(--ui-muted);
61
+ font-size: 12px;
62
+ }
63
+ .overflow-popover ul {
64
+ list-style: none;
65
+ padding: 0;
66
+ margin: 0;
67
+ }
68
+ .overflow-popover button {
69
+ display: grid;
70
+ gap: 4px;
71
+ width: 100%;
72
+ padding: 10px;
73
+ text-align: left;
74
+ white-space: normal;
75
+ overflow-wrap: anywhere;
76
+ font-size: 12px;
77
+ }
78
+ .overflow-popover li + li {
79
+ margin-top: 8px;
15
80
  }
16
81
 
17
82
  .custom-visual-summary p {
@@ -138,7 +203,7 @@
138
203
  gap: 3px;
139
204
  padding: 3px;
140
205
  background: #f4f4f5;
141
- border-radius: 7px;
206
+ border-radius: 8px;
142
207
  }
143
208
 
144
209
  .segmented-options button {
@@ -202,14 +267,6 @@
202
267
  white-space: nowrap;
203
268
  }
204
269
 
205
- .theme-options button[data-theme="precision"] > span:first-child {
206
- font-family: "Noto Sans", sans-serif;
207
- }
208
-
209
- .theme-options button[data-theme="editorial"] > span:first-child {
210
- font-family: Georgia, serif;
211
- }
212
-
213
270
  .theme-swatches {
214
271
  display: flex;
215
272
  gap: 3px;
@@ -249,9 +306,11 @@
249
306
  .layer-list {
250
307
  display: grid;
251
308
  gap: 4px;
309
+ padding-block: 3px;
252
310
  }
253
311
 
254
312
  .layer-row {
313
+ position: relative;
255
314
  display: grid;
256
315
  grid-template-columns: 16px minmax(0, 1fr) auto;
257
316
  align-items: center;
@@ -270,6 +329,26 @@
270
329
  opacity: 0.45;
271
330
  }
272
331
 
332
+ .layer-row[data-drop-edge]::after {
333
+ position: absolute;
334
+ z-index: 1;
335
+ left: -1px;
336
+ right: -1px;
337
+ height: 2px;
338
+ border-radius: 1px;
339
+ background: var(--accent);
340
+ pointer-events: none;
341
+ content: "";
342
+ }
343
+
344
+ .layer-row[data-drop-edge="before"]::after {
345
+ top: -4px;
346
+ }
347
+
348
+ .layer-row[data-drop-edge="after"]::after {
349
+ bottom: -4px;
350
+ }
351
+
273
352
  .layer-drag {
274
353
  color: var(--ui-muted);
275
354
  font-size: 13px;
@@ -356,6 +435,11 @@
356
435
  color: #565656;
357
436
  }
358
437
 
438
+ .field:has(> select[name="Font"]) > span {
439
+ color: var(--ui-text);
440
+ font-weight: 500;
441
+ }
442
+
359
443
  .field textarea {
360
444
  resize: none;
361
445
  overflow-y: auto;
@@ -799,6 +883,13 @@
799
883
  display: block;
800
884
  }
801
885
 
886
+ .appearance-preview[data-property="template"] svg {
887
+ position: absolute;
888
+ inset: 0;
889
+ width: 100%;
890
+ height: 100%;
891
+ }
892
+
802
893
  .appearance-preview[data-property="template"] i {
803
894
  position: absolute;
804
895
  z-index: 1;
@@ -880,24 +971,6 @@
880
971
  .appearance-preview[data-property="template"][data-value="treemap"] i:nth-child(3) { right: 8px; bottom: 3px; width: 5px; height: 7px; }
881
972
  .appearance-preview[data-property="template"][data-value="treemap"] i:nth-child(4) { right: 3px; bottom: 3px; width: 3px; height: 7px; background: var(--preview-secondary); }
882
973
 
883
- .appearance-preview[data-property="template"][data-value="scatter"] i:nth-child(1) { left: 5px; bottom: 5px; }
884
- .appearance-preview[data-property="template"][data-value="scatter"] i:nth-child(2) { left: 13px; bottom: 9px; }
885
- .appearance-preview[data-property="template"][data-value="scatter"] i:nth-child(3) { left: 22px; bottom: 12px; }
886
- .appearance-preview[data-property="template"][data-value="scatter"] i:nth-child(4) { right: 5px; top: 4px; width: 7px; height: 7px; background: var(--preview-accent); }
887
-
888
- .appearance-preview[data-property="template"][data-value="sankey"]::before,
889
- .appearance-preview[data-property="template"][data-value="sankey"]::after {
890
- position: absolute;
891
- left: 4px;
892
- width: 29px;
893
- border-top: 5px solid var(--preview-accent);
894
- border-radius: 50%;
895
- content: "";
896
- }
897
- .appearance-preview[data-property="template"][data-value="sankey"]::before { top: 7px; transform: rotate(8deg); }
898
- .appearance-preview[data-property="template"][data-value="sankey"]::after { bottom: 6px; border-color: var(--preview-muted); transform: rotate(-9deg); }
899
- .appearance-preview[data-property="template"][data-value="sankey"] i { display: none; }
900
-
901
974
  .appearance-preview[data-property="template"][data-value="linear"]::before,
902
975
  .appearance-preview[data-property="template"][data-value="request-flow"]::before {
903
976
  position: absolute;
@@ -1114,10 +1187,14 @@ legend {
1114
1187
  place-items: center;
1115
1188
  }
1116
1189
 
1117
- .diagram-type-category button:hover {
1190
+ .diagram-type-category button:hover:not(:disabled) {
1118
1191
  background: var(--ui-hover);
1119
1192
  }
1120
1193
 
1194
+ .diagram-type-category button:disabled {
1195
+ opacity: 0.48;
1196
+ }
1197
+
1121
1198
  .diagram-type-category button.selected {
1122
1199
  border-color: color-mix(in srgb, var(--accent) 45%, white);
1123
1200
  background: var(--ui-selected);
@@ -1152,6 +1229,13 @@ legend {
1152
1229
  stroke: none;
1153
1230
  }
1154
1231
 
1232
+ .chart-type-options .appearance-preview {
1233
+ margin: 4px 0;
1234
+ border: 0;
1235
+ background: transparent;
1236
+ transform: scale(1.333333);
1237
+ }
1238
+
1155
1239
  .visualization-description {
1156
1240
  display: block;
1157
1241
  margin-top: 8px;
@@ -1,3 +1,6 @@
1
+ :root {
2
+ --panel-top: 20px;
3
+ }
1
4
  .skip-link {
2
5
  position: fixed;
3
6
  top: -60px;
@@ -11,67 +14,102 @@
11
14
  top: 8px;
12
15
  }
13
16
  .workspace {
17
+ --panel-duration: 200ms;
18
+ --panel-easing: cubic-bezier(0.2, 0, 0, 1);
19
+ --panel-header-height: 58px;
14
20
  position: relative;
15
21
  height: 100dvh;
16
22
  min-height: 100dvh;
17
23
  overflow: hidden;
18
24
  background: var(--ui-bg);
19
25
  }
20
- .left-panel,
26
+ .left-sidebar,
21
27
  .right-panel {
22
28
  position: fixed;
23
- top: 92px;
24
- bottom: 92px;
29
+ top: var(--panel-top);
30
+ height: calc(100dvh - 92px - var(--panel-top));
31
+ width: var(--panel-width);
25
32
  z-index: 30;
33
+ display: flex;
34
+ flex-direction: column;
35
+ overflow: hidden;
26
36
  background: var(--ui-surface);
27
37
  min-height: 0;
28
- border: 1px solid var(--ui-border);
38
+ border: 1px solid transparent;
29
39
  border-radius: 12px;
30
- box-shadow: var(--ui-shadow);
40
+ box-shadow: var(--ui-floating-shadow);
41
+ transition: width var(--panel-duration) var(--panel-easing),
42
+ height var(--panel-duration) var(--panel-easing),
43
+ top var(--panel-duration) var(--panel-easing);
31
44
  }
32
- .left-panel {
33
- top: 80px;
34
- bottom: 148px;
45
+ .left-sidebar {
46
+ --panel-width: 252px;
35
47
  left: 20px;
36
- width: 252px;
37
- border-top: 0;
38
- border-bottom: 0;
39
- border-radius: 0;
40
- display: flex;
41
- flex-direction: column;
42
- overflow: hidden;
48
+ z-index: 40;
43
49
  }
44
- .right-panel {
50
+ .left-sidebar.collapsed {
45
51
  top: 20px;
52
+ width: 107px;
53
+ height: calc(var(--panel-header-height) + 2px);
54
+ }
55
+ .left-sidebar:not(.collapsed):has(.browser-menu[open]) {
56
+ overflow: visible;
57
+ }
58
+ .right-panel {
59
+ --panel-width: min(328px, calc(100vw - 40px));
46
60
  right: 20px;
47
- display: flex;
48
- flex-direction: column;
49
- width: min(328px, calc(100vw - 40px));
50
- overflow: hidden;
51
61
  }
52
62
  .right-panel.collapsed {
53
- bottom: auto;
63
+ top: 20px;
54
64
  width: 50px;
55
- height: 56px;
65
+ height: calc(var(--panel-header-height) + 2px);
56
66
  }
57
67
  .right-panel.collapsed > .panel-toolbar {
58
- height: 54px;
59
- justify-content: flex-end;
60
- padding: 0 8px;
61
- border-bottom: 0;
62
- }
63
- .right-panel.collapsed .panel-tabs,
64
- .right-panel.collapsed .right-panel-body {
65
- display: none;
68
+ gap: 0;
69
+ grid-template-columns: minmax(0, 1fr) 0 40px;
70
+ padding: 0 4px;
71
+ border-bottom-color: transparent;
66
72
  }
73
+ .left-panel,
67
74
  .right-panel-body {
75
+ width: calc(var(--panel-width) - 2px);
68
76
  display: flex;
69
77
  flex-direction: column;
70
78
  flex: 1;
71
79
  min-height: 0;
80
+ overflow: hidden;
81
+ }
82
+ .right-panel-body {
83
+ align-self: flex-end;
84
+ }
85
+ .right-panel > .panel-toolbar > .panel-tabs {
86
+ clip-path: inset(-4px 0);
87
+ }
88
+ .right-panel .panel-tabs button:focus-visible {
89
+ outline-offset: -3px;
90
+ }
91
+ .document-title,
92
+ .document-title-error,
93
+ .file-status,
94
+ .right-panel > .panel-toolbar > .panel-tabs,
95
+ .right-panel > .panel-toolbar > .overflow-control,
96
+ .left-panel,
97
+ .action-island,
98
+ .right-panel-body {
99
+ transition: opacity var(--panel-duration) var(--panel-easing),
100
+ visibility 0s;
72
101
  }
73
- .left-panel.collapsed {
102
+ .left-collapsed .document-title,
103
+ .left-collapsed .document-title-error,
104
+ .left-collapsed .file-status,
105
+ .right-panel.collapsed .panel-tabs,
106
+ .right-panel.collapsed .overflow-control,
107
+ .left-panel.collapsed,
108
+ .left-collapsed .action-island,
109
+ .right-panel.collapsed .right-panel-body {
110
+ opacity: 0;
74
111
  visibility: hidden;
112
+ transition-delay: 0s, var(--panel-duration);
75
113
  }
76
114
  .panel-toolbar {
77
115
  position: sticky;
@@ -91,8 +129,15 @@
91
129
  }
92
130
  .right-panel > .panel-toolbar {
93
131
  flex: none;
94
- height: 55px;
132
+ display: grid;
133
+ grid-template-columns: minmax(0, 1fr) 48px 40px;
134
+ height: var(--panel-header-height);
95
135
  padding: 0 8px 0 12px;
136
+ overflow: hidden;
137
+ transition: padding var(--panel-duration) var(--panel-easing),
138
+ gap var(--panel-duration) var(--panel-easing),
139
+ grid-template-columns var(--panel-duration) var(--panel-easing),
140
+ border-bottom-color var(--panel-duration) var(--panel-easing);
96
141
  }
97
142
  .panel-heading {
98
143
  flex: 1;
@@ -197,6 +242,8 @@
197
242
  align-items: center;
198
243
  justify-content: center;
199
244
  min-width: 0;
245
+ transition: padding-left var(--panel-duration) var(--panel-easing),
246
+ padding-right var(--panel-duration) var(--panel-easing);
200
247
  }
201
248
  .workspace.left-collapsed .stage {
202
249
  padding-left: 96px;
@@ -264,7 +311,7 @@
264
311
  align-items: center;
265
312
  justify-content: space-between;
266
313
  gap: 16px;
267
- min-height: 26px;
314
+ height: 40px;
268
315
  margin: 0 0 12px;
269
316
  }
270
317
  .edit-elements-action {
@@ -274,10 +321,14 @@
274
321
  font-size: 12px;
275
322
  }
276
323
  .stage-meta h2 {
324
+ min-width: 0;
325
+ overflow: hidden;
277
326
  font-size: 12px;
278
327
  font-weight: 500;
279
328
  color: var(--ui-muted);
280
329
  margin: 0;
330
+ text-overflow: ellipsis;
331
+ white-space: nowrap;
281
332
  cursor: text;
282
333
  }
283
334
  .stage-meta input {
@@ -299,3 +350,15 @@
299
350
  padding: 96px 16px 110px;
300
351
  }
301
352
  }
353
+
354
+ @media (max-width: 600px) {
355
+ :root {
356
+ --panel-top: 88px;
357
+ }
358
+ }
359
+
360
+ @media (prefers-reduced-motion: reduce) {
361
+ .workspace {
362
+ --panel-duration: 0ms;
363
+ }
364
+ }
@@ -1,93 +0,0 @@
1
- ---
2
- name: authoring-visuals
3
- description: Creates and revises editable Konpeki visuals from source material. Use for social graphics, article headers, visual explanations and presentations, including revisions to an existing composition.
4
- ---
5
-
6
- # Authoring visuals with Konpeki
7
-
8
- Deliver an editable composition and visually reviewed output. This skill needs
9
- the surrounding Konpeki runtime and resources; if they are unavailable, follow
10
- [SETUP.md](../../../SETUP.md) first. Paths here are relative to this file;
11
- run commands below from the user's workspace with Konpeki installed locally.
12
- For repository development, substitute `pnpm konpeki` for
13
- `npm exec --no -- konpeki`. Keep authored documents outside `node_modules`.
14
-
15
- ## 1. Interpret the brief
16
-
17
- Read [project rules](../../../AGENTS.md) and
18
- [authoring policy](../../../AUTHORING.md). Use the user's existing prompt as the
19
- brief; do not ask them to repeat it in the canvas. Establish the source facts,
20
- audience, takeaway and destination. Ask only when missing facts or conflicting
21
- requirements prevent a faithful result.
22
-
23
- Use `default` authoring mode unless requested otherwise. Explicit visual
24
- preferences override taste defaults, not factual fidelity or readability. Use
25
- the policy's [comparison workflow](../../../AUTHORING.md#explore-an-uncertain-direction)
26
- only when requested or accepted. A single page is a complete creation; choose
27
- dimensions for its destination rather than assuming a slide deck.
28
-
29
- ## 2. Author or revise the composition
30
-
31
- Read the [composition contract](../../../composition/README.md). For a new visual,
32
- create `slides/<name>/composition.json` unless the user supplies another path.
33
- Save the creative brief in `PROMPT.md` and substantial facts, citations and asset
34
- provenance in `SOURCE.md`. Separate assumptions from supplied facts. Preserve
35
- creative requests accurately, but omit private coordination and environment or
36
- agent metadata; label excerpts and redactions rather than calling them verbatim.
37
-
38
- For revisions, reread the current file first. Preserve unrelated content,
39
- component/vector IDs and human-edited geometry. Honor explicit chart or diagram
40
- choices. Recompose for a new aspect ratio instead of stretching or cropping.
41
-
42
- Prefer native text and semantic components. When standard drafts cannot express
43
- the visual, use editable vectors inside their owning component. Reuse
44
- [design resources](../../../design/README.md) and reference examples as needed.
45
- Trusted React may generate SVG for conversion, but imported JSX must not execute
46
- in the canvas or become a second document source.
47
-
48
- ## 3. Validate, render and repair
49
-
50
- ```sh
51
- npm exec --no -- konpeki validate slides/<name>/composition.json
52
- npm exec --no -- konpeki preview slides/<name>/composition.json
53
- ```
54
-
55
- Reuse an active file-backed preview for the same document when available. Open
56
- the exact session URL, or its host-approved remote preview equivalent. Inspect
57
- every affected page and requested theme at presentation and smaller review sizes
58
- after fonts load. Check factual fidelity, text bounds, contrast, reading order
59
- and relationships. Repair consequential issues and inspect fresh renders.
60
-
61
- Follow [verification guidance](../../../docs/development.md#verification) for
62
- code changes. Validation alone is not visual review. If a required check cannot
63
- run, state the limitation; do not claim it passed. Honor requested checkpoints;
64
- otherwise continue to finished output.
65
-
66
- ## 4. Deliver and continue revisions
67
-
68
- Return the composition path, usable preview, reviewed images or requested
69
- exports, source attribution and verification limitations. Verify exports
70
- separately; browser images do not prove editable PDF/PPTX or font fidelity.
71
- Include any generator source while keeping composition JSON authoritative.
72
-
73
- Keep revision requests in agent chat by default. When explicitly waiting for a
74
- canvas request, run `npm exec --no -- konpeki wait <composition.json>` alongside the preview.
75
- **Build it** submits a request; it does not launch an agent. On receiving it,
76
- reread the named file and compare its revision with the request. If it changed,
77
- reconcile against the latest document instead of applying a stale rewrite.
78
- Apply every attached note to its named page, component or vector-element ID;
79
- without notes, respect the selected scope. Preserve unrelated edits and stable
80
- IDs. A request is already marked working when `wait` returns; it is not deleted.
81
- Validate, render, inspect and repair the result, then run
82
- `npm exec --no -- konpeki finish <composition.json> <request-id> --message "Updated and checked"`.
83
- File changes alone do not resolve notes. If blocked, finish with
84
- `--status needs-clarification --message "..."` or `--status failed --message "..."`;
85
- unresolved notes remain for retry. Never mark a partially handled batch done.
86
- Use `konpeki request <composition.json>` to recover an interrupted request and
87
- verify it is still active before further writes. Cancellation does not stop your
88
- process: stop work if the request is no longer active. Do not edit the feedback
89
- sidecar directly. Return to `wait` only when the person requested a continuing loop.
90
-
91
- See [canvas workflow](../../../docs/workflow.md) for the full handoff contract.
92
- Never bypass revision checks or mutate hidden browser storage to replace the
93
- document. Do not publish without permission.