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
@@ -1,5 +1,3 @@
1
- .document-island,
2
- .action-island,
3
1
  .component-dock {
4
2
  position: fixed;
5
3
  z-index: 40;
@@ -11,18 +9,21 @@
11
9
  }
12
10
 
13
11
  .document-island {
14
- top: 20px;
15
- left: 20px;
16
- width: 252px;
17
- height: 60px;
12
+ position: relative;
13
+ z-index: 2;
14
+ display: flex;
15
+ align-items: center;
16
+ flex: none;
17
+ width: 100%;
18
+ height: var(--panel-header-height);
18
19
  gap: 10px;
19
20
  padding: 8px 10px;
20
- border-radius: 14px;
21
+ border-bottom: 1px solid var(--ui-border);
22
+ transition: border-bottom-color var(--panel-duration) var(--panel-easing);
21
23
  }
22
24
 
23
- .workspace:has(.left-panel:not(.collapsed)) .document-island {
24
- border-radius: 12px 12px 0 0;
25
- box-shadow: none;
25
+ .left-collapsed .document-island {
26
+ border-bottom-color: transparent;
26
27
  }
27
28
 
28
29
  .document-island img {
@@ -32,10 +33,6 @@
32
33
  object-fit: contain;
33
34
  }
34
35
 
35
- .document-island .panel-collapse-icon {
36
- transform: rotate(-90deg);
37
- }
38
-
39
36
  .document-title {
40
37
  min-width: 0;
41
38
  flex: 1;
@@ -76,9 +73,19 @@
76
73
  flex: none;
77
74
  display: inline-flex;
78
75
  align-items: center;
76
+ width: 6px;
79
77
  gap: 5px;
80
78
  color: var(--ui-muted);
81
79
  font-size: 10px;
80
+ transition: opacity var(--panel-duration) var(--panel-easing),
81
+ width var(--panel-duration) var(--panel-easing),
82
+ margin-right var(--panel-duration) var(--panel-easing), visibility 0s;
83
+ }
84
+
85
+ .left-collapsed .file-status {
86
+ width: 0;
87
+ margin-right: -10px;
88
+ transition-delay: 0s, 0s, 0s, var(--panel-duration);
82
89
  }
83
90
 
84
91
  .file-status::before {
@@ -105,20 +112,15 @@
105
112
  }
106
113
 
107
114
  .action-island {
108
- bottom: 92px;
109
- left: 20px;
110
- width: 252px;
111
- min-width: 252px;
112
- height: 56px;
115
+ position: relative;
116
+ display: flex;
117
+ align-items: center;
118
+ flex: none;
119
+ width: calc(var(--panel-width) - 2px);
120
+ height: 54px;
113
121
  gap: 4px;
114
122
  padding: 7px;
115
123
  border-top: 1px solid var(--ui-border);
116
- border-radius: 0 0 12px 12px;
117
- box-shadow: none;
118
- }
119
-
120
- .left-collapsed .action-island {
121
- visibility: hidden;
122
124
  }
123
125
 
124
126
  .action-island button {
@@ -146,6 +148,163 @@
146
148
  justify-content: center;
147
149
  }
148
150
 
151
+ .browser-menu {
152
+ position: relative;
153
+ min-width: 0;
154
+ }
155
+
156
+ .browser-menu::details-content {
157
+ opacity: 0;
158
+ transition: opacity 120ms ease-in, content-visibility 120ms allow-discrete;
159
+ }
160
+
161
+ .browser-menu[open]::details-content {
162
+ opacity: 1;
163
+ transition: opacity 180ms ease-out, content-visibility 180ms allow-discrete;
164
+ }
165
+
166
+ .browser-menu > summary {
167
+ display: flex;
168
+ align-items: center;
169
+ justify-content: center;
170
+ height: 40px;
171
+ gap: 6px;
172
+ padding: 0 12px;
173
+ border-radius: 7px;
174
+ cursor: pointer;
175
+ font-size: 13px;
176
+ font-weight: 500;
177
+ list-style: none;
178
+ white-space: nowrap;
179
+ }
180
+
181
+ .browser-menu > summary::-webkit-details-marker {
182
+ display: none;
183
+ }
184
+
185
+ .browser-menu > summary svg {
186
+ width: 14px;
187
+ height: 14px;
188
+ fill: none;
189
+ stroke: currentColor;
190
+ stroke-width: 1.5;
191
+ stroke-linecap: round;
192
+ stroke-linejoin: round;
193
+ }
194
+
195
+ .browser-menu[open] > summary svg {
196
+ transform: rotate(180deg);
197
+ }
198
+
199
+ .browser-menu > summary:hover,
200
+ .browser-menu[open] > summary {
201
+ background: var(--ui-hover);
202
+ }
203
+
204
+ .browser-menu-popover {
205
+ position: absolute;
206
+ z-index: 3;
207
+ bottom: calc(100% + 14px);
208
+ left: -88px;
209
+ display: grid;
210
+ width: 320px;
211
+ max-width: calc(100vw - 56px);
212
+ max-height: calc(100dvh - var(--panel-top) - 164px);
213
+ overflow-y: auto;
214
+ overscroll-behavior: contain;
215
+ scrollbar-width: thin;
216
+ scrollbar-color: #d4d4d8 transparent;
217
+ gap: 16px;
218
+ padding: 16px;
219
+ border: 1px solid var(--ui-border);
220
+ border-radius: 12px;
221
+ background: var(--ui-surface);
222
+ box-shadow: var(--ui-shadow);
223
+ transform: translateY(6px) scale(0.98);
224
+ transform-origin: bottom center;
225
+ transition: transform 120ms ease-in;
226
+ }
227
+
228
+ .browser-menu[open] .browser-menu-popover {
229
+ transform: none;
230
+ transition: transform 180ms ease-out;
231
+ }
232
+
233
+ @starting-style {
234
+ .browser-menu[open]::details-content {
235
+ opacity: 0;
236
+ }
237
+
238
+ .browser-menu[open] .browser-menu-popover {
239
+ transform: translateY(6px) scale(0.98);
240
+ }
241
+ }
242
+
243
+ .browser-menu-intro,
244
+ .browser-agent-handoff {
245
+ display: grid;
246
+ gap: 6px;
247
+ }
248
+
249
+ .browser-menu-popover strong {
250
+ font-size: 13px;
251
+ font-weight: 600;
252
+ }
253
+
254
+ .browser-menu-intro > strong {
255
+ font-size: 14px;
256
+ }
257
+
258
+ .browser-menu-popover p {
259
+ color: var(--ui-muted);
260
+ font-size: 12px;
261
+ line-height: 1.5;
262
+ overflow-wrap: anywhere;
263
+ }
264
+
265
+ .browser-menu-actions {
266
+ display: grid;
267
+ grid-template-columns: repeat(2, minmax(0, 1fr));
268
+ gap: 6px;
269
+ }
270
+
271
+ .action-island .browser-menu-actions button {
272
+ justify-content: center;
273
+ min-width: 0;
274
+ min-height: 40px;
275
+ height: auto;
276
+ padding: 8px;
277
+ border-color: var(--ui-border);
278
+ background: var(--ui-surface);
279
+ font-size: 12px;
280
+ }
281
+
282
+ .action-island .browser-menu-actions button.secondary {
283
+ color: var(--ui-muted);
284
+ }
285
+
286
+ .action-island .browser-menu-actions button:hover {
287
+ background: var(--ui-hover);
288
+ color: var(--ui-text);
289
+ }
290
+
291
+ .browser-agent-handoff {
292
+ padding: 12px 12px 4px;
293
+ border-radius: 8px;
294
+ background: var(--ui-hover);
295
+ }
296
+
297
+ .browser-agent-handoff a {
298
+ display: flex;
299
+ align-items: center;
300
+ justify-self: start;
301
+ min-height: 40px;
302
+ color: var(--accent);
303
+ font-size: 12px;
304
+ font-weight: 500;
305
+ text-underline-offset: 3px;
306
+ }
307
+
149
308
  .action-island button.primary {
150
309
  background: white;
151
310
  color: var(--ui-text);
@@ -231,6 +390,10 @@
231
390
  }
232
391
 
233
392
  @media (prefers-reduced-motion: reduce) {
393
+ .browser-menu::details-content {
394
+ transition: none !important;
395
+ }
396
+
234
397
  .build-button.building .build-label,
235
398
  .build-orb.active circle,
236
399
  .build-orb.nebula circle,
@@ -1,42 +1,78 @@
1
- .toast {
1
+ .feedback-notice {
2
2
  position: fixed;
3
- top: 20px;
4
- bottom: auto;
5
3
  left: 50%;
6
- transform: translateX(-50%);
7
- transform-origin: center top;
8
- display: none;
9
- align-items: center;
10
- gap: 12px;
4
+ z-index: 50;
5
+ opacity: 0;
6
+ visibility: hidden;
7
+ pointer-events: none;
8
+ transform: translate(-50%, -3px);
9
+ transition: opacity 120ms ease-in, transform 120ms ease-in,
10
+ visibility 0s 120ms;
11
11
  background: var(--ui-surface);
12
12
  color: var(--ui-text);
13
- border: 1px solid var(--ui-border);
14
- box-shadow: 0 4px 16px #0000000a, 0 1px 3px #00000008;
15
- padding: 10px 14px;
13
+ border: 1px solid transparent;
16
14
  border-radius: 12px;
15
+ box-shadow: var(--ui-floating-shadow);
17
16
  font-size: 13px;
18
17
  line-height: 1.5;
18
+ }
19
+ .feedback-notice.visible {
20
+ opacity: 1;
21
+ visibility: visible;
22
+ pointer-events: auto;
23
+ transform: translate(-50%, 0);
24
+ transition: opacity 180ms ease-out, transform 180ms ease-out,
25
+ visibility 0s;
26
+ }
27
+ @starting-style {
28
+ .feedback-notice.visible {
29
+ opacity: 0;
30
+ transform: translate(-50%, -6px);
31
+ }
32
+ }
33
+ .toast {
34
+ top: 20px;
35
+ display: flex;
36
+ align-items: center;
37
+ gap: 12px;
38
+ padding: 10px 14px;
19
39
  width: max-content;
20
- max-width: min(520px, max(240px, calc(100vw - 744px)), calc(100vw - 40px));
21
- z-index: 50;
40
+ max-width: min(560px, calc(100vw - 40px));
22
41
  }
23
- .toast > span {
42
+ .toast > span,
43
+ .recovery > span,
44
+ .parameter-error {
24
45
  min-width: 0;
25
46
  overflow-wrap: anywhere;
47
+ text-wrap: pretty;
26
48
  }
27
- .toast.visible {
28
- display: flex;
29
- animation: toast-enter 180ms ease-out both;
49
+ .toast > button {
50
+ flex: none;
51
+ min-height: 36px;
52
+ font-size: 12px;
53
+ border: 0;
30
54
  }
31
- .toast.visible.closing {
32
- pointer-events: none;
33
- animation: toast-exit 180ms ease-in both;
55
+ .toast > button,
56
+ .recovery-actions button {
57
+ border-radius: 6px;
58
+ background: transparent;
59
+ }
60
+ .toast > button:hover:not(:disabled),
61
+ .recovery-actions button:hover:not(:disabled) {
62
+ background: var(--ui-hover);
63
+ }
64
+ .toast-dismiss {
65
+ width: 36px;
66
+ padding: 0;
67
+ border: 0;
68
+ background: transparent;
69
+ font-size: 20px !important;
70
+ color: inherit;
34
71
  }
35
72
  .toast.error {
36
- border-color: #e4b5b5;
37
73
  background: #fff7f7;
38
74
  color: #8d1717;
39
- box-shadow: 0 0 0 1px #b13d3d14, 0 4px 16px #5f11110d;
75
+ box-shadow: 0 0 0 1px #b13d3d33, 0 4px 16px #5f11110d;
40
76
  }
41
77
  .toast.error::before {
42
78
  display: grid;
@@ -50,35 +86,51 @@
50
86
  content: "!";
51
87
  font-weight: 600;
52
88
  }
53
- @keyframes toast-enter {
54
- from {
55
- opacity: 0;
56
- transform: translate(-50%, -6px);
57
- }
58
- to {
59
- opacity: 1;
60
- transform: translate(-50%, 0);
61
- }
62
- }
63
- @keyframes toast-exit {
64
- from {
65
- opacity: 1;
66
- transform: translate(-50%, 0);
67
- }
68
- to {
69
- opacity: 0;
70
- transform: translate(-50%, -6px);
71
- }
72
- }
73
89
  .recovery {
74
- display: flex;
75
- justify-content: center;
76
- align-items: center;
77
- gap: 20px;
78
- background: #fff;
79
- border-bottom: 1px solid #ccc;
90
+ bottom: 100px;
91
+ display: grid;
92
+ gap: 12px;
93
+ width: max-content;
94
+ max-width: min(420px, calc(100vw - 40px));
80
95
  padding: 12px;
81
- font-size: 13px;
96
+ }
97
+ .recovery-actions {
98
+ display: flex;
99
+ flex-wrap: wrap;
100
+ justify-content: flex-end;
101
+ gap: 8px;
102
+ }
103
+ .recovery-actions button {
104
+ min-height: 36px;
105
+ font-size: 12px;
106
+ border: 1px solid var(--ui-border);
107
+ }
108
+ .recovery-actions button:hover:not(:disabled) {
109
+ border-color: var(--ui-control);
110
+ }
111
+ input[aria-invalid="true"] {
112
+ border-color: #b13d3d;
113
+ box-shadow: none;
114
+ }
115
+ input[aria-invalid="true"]:focus-visible {
116
+ outline: 2px solid #b13d3d;
117
+ outline-offset: -1px;
118
+ }
119
+ .parameter-error {
120
+ position: fixed;
121
+ z-index: 60;
122
+ width: 260px;
123
+ padding: 10px 12px;
124
+ border: 1px solid #e4b5b5;
125
+ border-radius: 8px;
126
+ background: #fff7f7;
127
+ color: #8d1717;
128
+ box-shadow: 0 4px 16px #0000000a;
129
+ font-size: 12px;
130
+ line-height: 1.5;
131
+ }
132
+ @media (max-width: 900px) {
133
+ .toast { top: calc(var(--panel-top) + 68px); }
82
134
  }
83
135
  @media (prefers-reduced-motion: reduce) {
84
136
  *,
@@ -37,7 +37,6 @@
37
37
  .revision-note-target > span { color: var(--ui-muted); }
38
38
  .revision-note-list p { font-size: 12px; line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; }
39
39
  .revision-note-remove { display: inline-flex; align-items: center; min-height: 40px; border: 0; padding: 6px 0; background: none; color: var(--ui-muted); font-size: 11px; }
40
- .revision-note-error { color: #a02020; font-size: 12px; }
41
40
 
42
41
  .slide-list {
43
42
  flex: 1;
@@ -53,10 +52,14 @@
53
52
  position: relative;
54
53
  }
55
54
 
55
+ .slide-thumbnail-item + .slide-thumbnail-item {
56
+ margin-top: 8px;
57
+ }
58
+
56
59
  .slide-thumbnail {
57
60
  display: grid;
58
61
  width: 100%;
59
- gap: 9px;
62
+ gap: 0;
60
63
  padding: 8px;
61
64
  border-color: transparent;
62
65
  font-size: 12px;
@@ -78,13 +81,17 @@
78
81
  }
79
82
 
80
83
  .slide-thumbnail > span:last-child {
81
- padding-right: 30px;
84
+ display: flex;
85
+ align-items: center;
86
+ min-height: 40px;
87
+ padding-right: 48px;
88
+ overflow-wrap: anywhere;
82
89
  }
83
90
 
84
91
  .remove-slide {
85
92
  position: absolute;
86
- right: 2px;
87
- bottom: 0;
93
+ right: 9px;
94
+ bottom: 9px;
88
95
  width: 40px;
89
96
  height: 40px;
90
97
  padding: 0;
@@ -94,12 +101,26 @@
94
101
  color: var(--ui-muted);
95
102
  }
96
103
 
104
+ .remove-slide::before {
105
+ position: absolute;
106
+ inset: 5px;
107
+ border-radius: 5px;
108
+ background: transparent;
109
+ pointer-events: none;
110
+ transition: background-color 120ms ease-out;
111
+ content: "";
112
+ }
113
+
97
114
  .remove-slide:hover:not(:disabled) {
98
115
  border-color: transparent;
99
- background: #ffe9e9;
116
+ background: transparent;
100
117
  color: #9d2020;
101
118
  }
102
119
 
120
+ .remove-slide:hover:not(:disabled)::before {
121
+ background: #ffe9e9;
122
+ }
123
+
103
124
  .add-slide {
104
125
  display: flex;
105
126
  align-items: center;