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.
- package/AGENTS.md +21 -28
- package/AUTHORING.md +68 -229
- package/CONTRIBUTING.md +10 -23
- package/README.md +96 -87
- package/SETUP.md +50 -114
- package/docs/development.md +43 -248
- package/docs/workflow.md +6 -108
- package/html/README.md +140 -0
- package/html/browser.ts +103 -0
- package/html/document.ts +38 -0
- package/html/floor.ts +34 -0
- package/html/index.html +5 -0
- package/html/inspect.ts +313 -0
- package/html/preview.css +62 -0
- package/html/preview.tsx +463 -0
- package/html/review-hints.ts +63 -0
- package/html/server.ts +99 -0
- package/html/source.ts +104 -0
- package/html/starter.ts +6 -0
- package/html/theme-authoring.md +176 -0
- package/html/theme.md +61 -0
- package/index.html +9 -9
- package/package.json +21 -35
- package/plugin.json +1 -1
- package/public/og.png +0 -0
- package/runtime/browser-B-29TH1a.mjs +595 -0
- package/runtime/floor-Cmk7G3pU.mjs +41 -0
- package/runtime/konpeki.mjs +90 -1410
- package/runtime/server-BAqC_5WD.mjs +2 -0
- package/runtime/server-DfRpfcY9.mjs +205 -0
- package/runtime/source-B_Ui9tMp.mjs +141 -0
- package/runtime/source-CZQq9GUO.mjs +2 -0
- package/skills/konpeki/SKILL.md +88 -172
- package/skills/konpeki/assets/blank.html +17 -0
- package/skills/konpeki/floor.md +76 -0
- package/skills/konpeki/references/cover.md +27 -0
- package/skills/konpeki/references/long-document.md +40 -0
- package/skills/konpeki/references/one-pager.md +27 -0
- package/skills/konpeki/references/patterns.md +118 -0
- package/skills/konpeki/references/resume.md +28 -0
- package/skills/konpeki/references/slides.md +28 -0
- package/skills/konpeki/scripts/ensure-runtime.mjs +10 -31
- package/skills/konpeki/scripts/prepare-document.mjs +25 -14
- package/src/components/PageBoard.tsx +156 -0
- package/src/lib/alignment.ts +21 -0
- package/src/lib/page-board.ts +25 -0
- package/src/lib/review-position.ts +19 -0
- package/src/styles/base.css +4 -6
- package/src/styles/feedback.css +97 -61
- package/src/styles/shell.css +95 -323
- package/theme-base.css +90 -0
- package/theme.css +56 -0
- package/vite.config.ts +2 -5
- package/composition/README.md +0 -156
- package/composition/compile.ts +0 -227
- package/composition/document.ts +0 -600
- package/composition/schema.json +0 -3001
- package/composition/schema.ts +0 -437
- package/composition/theme-tokens.ts +0 -16
- package/composition/types.ts +0 -269
- package/composition/validate.ts +0 -226
- package/composition/vector.ts +0 -143
- package/composition/visualizations.ts +0 -319
- package/design/README.md +0 -17
- package/design/palettes/README.md +0 -14
- package/design/palettes/base.ts +0 -14
- package/design/palettes/candidates.ts +0 -19
- package/design/palettes/index.ts +0 -78
- package/design/review/color-theme.md +0 -44
- package/design/review/layout.md +0 -16
- package/design/review/text.md +0 -18
- package/design/review/typography.md +0 -15
- package/design/review/visuals.md +0 -31
- package/design/semantic-patterns.md +0 -43
- package/design/themes/README.md +0 -40
- package/design/themes/index.ts +0 -24
- package/design/visual-languages/technical-product.md +0 -17
- package/design/visual-review.md +0 -88
- package/lib/assets.d.ts +0 -8
- package/lib/charts.ts +0 -18
- package/lib/contrast.ts +0 -16
- package/lib/layouts.ts +0 -50
- package/lib/slide.tsx +0 -42
- package/lib/taste.ts +0 -17
- package/lib/text.tsx +0 -89
- package/lib/typeface.ts +0 -44
- package/scripts/migrate-react-page.ts +0 -120
- package/skills/konpeki/assets/blank.json +0 -23
- package/slides/README.md +0 -153
- package/slides/architecture/PROMPT.md +0 -31
- package/slides/architecture/index.tsx +0 -102
- package/slides/article-brief/PROMPT.md +0 -35
- package/slides/article-brief/index.tsx +0 -71
- package/slides/bar-chart/PROMPT.md +0 -39
- package/slides/bar-chart/index.tsx +0 -97
- package/slides/comparison/PROMPT.md +0 -29
- package/slides/comparison/index.tsx +0 -95
- package/slides/decision-memo/PROMPT.md +0 -34
- package/slides/decision-memo/index.tsx +0 -85
- package/slides/delivery-plan/PROMPT.md +0 -45
- package/slides/delivery-plan/index.tsx +0 -105
- package/slides/experiment/PROMPT.md +0 -44
- package/slides/experiment/index.tsx +0 -127
- package/slides/incident-workflow/PROMPT.md +0 -57
- package/slides/incident-workflow/index.tsx +0 -78
- package/slides/introducing-konpeki/PROMPT.md +0 -40
- package/slides/introducing-konpeki/README.md +0 -76
- package/slides/introducing-konpeki/SOURCE.md +0 -26
- package/slides/introducing-konpeki/author.ts +0 -165
- package/slides/introducing-konpeki/composition.json +0 -3270
- package/slides/line-chart/PROMPT.md +0 -40
- package/slides/line-chart/index.tsx +0 -72
- package/slides/migration/PROMPT.md +0 -38
- package/slides/migration/index.tsx +0 -89
- package/slides/og-images/PROMPT.md +0 -21
- package/slides/og-images/index.tsx +0 -76
- package/slides/product-introduction/PROMPT.md +0 -24
- package/slides/product-introduction/index.tsx +0 -105
- package/slides/research-brief/PROMPT.md +0 -40
- package/slides/research-brief/index.tsx +0 -104
- package/slides/results-explanation/PROMPT.md +0 -32
- package/slides/results-explanation/index.tsx +0 -96
- package/slides/retrospective/PROMPT.md +0 -43
- package/slides/retrospective/index.tsx +0 -105
- package/slides/sankey/PROMPT.md +0 -11
- package/slides/sankey/index.tsx +0 -93
- package/slides/teaching/PROMPT.md +0 -45
- package/slides/teaching/index.tsx +0 -124
- package/slides/vertical-bar-charts/PROMPT.md +0 -13
- package/slides/vertical-bar-charts/index.tsx +0 -97
- package/src/app/App.tsx +0 -820
- package/src/components/BuildOrb.tsx +0 -40
- package/src/components/Canvas.tsx +0 -1185
- package/src/components/DiagramTypeIcon.tsx +0 -78
- package/src/components/InspectorPanel.tsx +0 -773
- package/src/components/LeftPanel.tsx +0 -120
- package/src/components/PageSizePicker.tsx +0 -30
- package/src/components/Presentation.tsx +0 -105
- package/src/components/RevisionNotes.tsx +0 -56
- package/src/components/RightPanel.tsx +0 -201
- package/src/components/VectorOverflowWarning.tsx +0 -46
- package/src/components/WorkspaceChrome.tsx +0 -288
- package/src/components/ui.tsx +0 -53
- package/src/lib/examples/react-page-migration.json +0 -1295
- package/src/lib/examples.ts +0 -42
- package/src/lib/export-png.ts +0 -104
- package/src/lib/file-session.ts +0 -87
- package/src/lib/history.ts +0 -53
- package/src/lib/model.ts +0 -188
- package/src/lib/page-size.ts +0 -24
- package/src/lib/presentation.ts +0 -17
- package/src/lib/review.ts +0 -26
- package/src/lib/storage.ts +0 -71
- package/src/lib/theme.ts +0 -25
- package/src/lib/use-file-session.ts +0 -227
- package/src/main.tsx +0 -29
- package/src/styles/canvas.css +0 -299
- package/src/styles/chrome.css +0 -384
- package/src/styles/component-previews.css +0 -386
- package/src/styles/left-panel.css +0 -166
- package/src/styles/presentation.css +0 -72
- package/src/styles/right-panel.css +0 -1215
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type Guide = { axis: "x" | "y"; value: number };
|
|
2
|
+
|
|
3
|
+
export function closest(points: number[], targets: number[], threshold: number) {
|
|
4
|
+
let match: { delta: number; target: number } | undefined;
|
|
5
|
+
for (const point of points)
|
|
6
|
+
for (const target of targets) {
|
|
7
|
+
const delta = target - point;
|
|
8
|
+
if (Math.abs(delta) <= threshold && (!match || Math.abs(delta) < Math.abs(match.delta)))
|
|
9
|
+
match = { delta, target };
|
|
10
|
+
}
|
|
11
|
+
return match;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Visual references only. Never change the dragged coordinates. */
|
|
15
|
+
export function referenceGuides(rect: { x: number; y: number; width: number; height: number }, targets: { x: number[]; y: number[] }, threshold = 2): Guide[] {
|
|
16
|
+
return (["x", "y"] as const).flatMap(axis => {
|
|
17
|
+
const size = axis === "x" ? rect.width : rect.height;
|
|
18
|
+
const match = closest([rect[axis], rect[axis] + size / 2, rect[axis] + size], targets[axis], threshold);
|
|
19
|
+
return match ? [{ axis, value: match.target }] : [];
|
|
20
|
+
});
|
|
21
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Presentation geometry only; never stored in the authored document. */
|
|
2
|
+
export function layoutPages(sizes: readonly { width: number; height: number }[], availableWidth: number, availableHeight: number) {
|
|
3
|
+
const gap = 80, heading = 32;
|
|
4
|
+
let nextX = 0;
|
|
5
|
+
const pages = sizes.map(size => {
|
|
6
|
+
const scale = Math.min(availableWidth / size.width, Math.max(0, availableHeight - heading) / size.height);
|
|
7
|
+
const width = size.width * scale, height = size.height * scale;
|
|
8
|
+
const x = nextX;
|
|
9
|
+
nextX += width + gap;
|
|
10
|
+
return { x, y: heading, width, height };
|
|
11
|
+
});
|
|
12
|
+
const arrows = pages.slice(1).map((next, index) => {
|
|
13
|
+
const previous = pages[index];
|
|
14
|
+
const start = previous.x + previous.width + 16;
|
|
15
|
+
const end = next.x - 16;
|
|
16
|
+
const middle = (start + end) / 2;
|
|
17
|
+
return `M ${start} ${previous.y + previous.height / 2} H ${middle} V ${next.y + next.height / 2} H ${end}`;
|
|
18
|
+
});
|
|
19
|
+
return {
|
|
20
|
+
// The board centers this tightly bounded row when it fits the viewport.
|
|
21
|
+
width: pages.length ? nextX - gap : availableWidth,
|
|
22
|
+
height: pages.length ? heading + Math.max(...pages.map(page => page.height)) : 0,
|
|
23
|
+
pages, arrows,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
type Rect = { x: number; y: number; width: number; height: number };
|
|
2
|
+
|
|
3
|
+
/** Fixed viewport coordinates; the caller measures the already-zoomed target. */
|
|
4
|
+
export function reviewPosition(anchor: Rect, panel: Pick<Rect, "width" | "height">, viewport: Rect) {
|
|
5
|
+
const margin = 16, gap = 12;
|
|
6
|
+
const minX = viewport.x + margin, minY = viewport.y + margin;
|
|
7
|
+
const maxX = Math.max(minX, viewport.x + viewport.width - margin - panel.width);
|
|
8
|
+
const maxY = Math.max(minY, viewport.y + viewport.height - margin - panel.height);
|
|
9
|
+
const left = Math.max(minX, Math.min(anchor.x, maxX));
|
|
10
|
+
const top = Math.max(minY, Math.min(anchor.y, maxY));
|
|
11
|
+
const candidates = [
|
|
12
|
+
{ left, top: anchor.y + anchor.height + gap },
|
|
13
|
+
{ left, top: anchor.y - gap - panel.height },
|
|
14
|
+
{ left: anchor.x + anchor.width + gap, top },
|
|
15
|
+
{ left: anchor.x - gap - panel.width, top },
|
|
16
|
+
];
|
|
17
|
+
return candidates.find(p => p.left >= minX && p.left <= maxX && p.top >= minY && p.top <= maxY)
|
|
18
|
+
?? { left, top: Math.max(minY, Math.min(candidates[0].top, maxY)) };
|
|
19
|
+
}
|
package/src/styles/base.css
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
--ui-hover: #f2f2f2;
|
|
18
18
|
--ui-selected: #edf6fa;
|
|
19
19
|
--ui-shadow: 0 8px 28px #00000014, 0 1px 3px #00000012;
|
|
20
|
+
--ui-floating-shadow: 0 0 0 1px #0000000f, 0 2px 4px #00000006, 0 8px 24px #0000000a;
|
|
20
21
|
}
|
|
21
22
|
* {
|
|
22
23
|
box-sizing: border-box;
|
|
@@ -52,6 +53,9 @@ button:disabled {
|
|
|
52
53
|
cursor: default;
|
|
53
54
|
color: #767676;
|
|
54
55
|
}
|
|
56
|
+
.revision-note-count {
|
|
57
|
+
font-variant-numeric: tabular-nums;
|
|
58
|
+
}
|
|
55
59
|
:focus-visible {
|
|
56
60
|
outline: 2px solid var(--accent);
|
|
57
61
|
outline-offset: 3px;
|
|
@@ -98,12 +102,6 @@ h2 {
|
|
|
98
102
|
background: #383838;
|
|
99
103
|
border-color: #383838;
|
|
100
104
|
}
|
|
101
|
-
.panel-toggle:active:not(:disabled),
|
|
102
|
-
.action-island button:active:not(:disabled),
|
|
103
|
-
.component-dock button:active:not(:disabled),
|
|
104
|
-
.segmented-options button:active:not(:disabled),
|
|
105
|
-
.theme-options button:active:not(:disabled),
|
|
106
|
-
.appearance-options button:active:not(:disabled),
|
|
107
105
|
.revision-note-submit button:active:not(:disabled),
|
|
108
106
|
.revision-note-remove:active:not(:disabled) {
|
|
109
107
|
transform: scale(0.96);
|
package/src/styles/feedback.css
CHANGED
|
@@ -1,42 +1,79 @@
|
|
|
1
|
-
.
|
|
1
|
+
.feedback-notice {
|
|
2
2
|
position: fixed;
|
|
3
|
-
top: 20px;
|
|
4
|
-
bottom: auto;
|
|
5
3
|
left: 50%;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
|
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(
|
|
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
|
|
28
|
-
|
|
29
|
-
|
|
49
|
+
.toast > button {
|
|
50
|
+
flex: none;
|
|
51
|
+
min-height: 36px;
|
|
52
|
+
font-size: 12px;
|
|
53
|
+
border: 0;
|
|
30
54
|
}
|
|
31
|
-
.toast
|
|
32
|
-
|
|
33
|
-
|
|
55
|
+
.toast > button,
|
|
56
|
+
.recovery-actions button {
|
|
57
|
+
border-radius: 6px;
|
|
58
|
+
background: transparent;
|
|
34
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;
|
|
71
|
+
}
|
|
72
|
+
.toast-undo { margin-left: 12px; padding: 4px 8px; border: 0; background: transparent; color: var(--accent); font-weight: 500; }
|
|
35
73
|
.toast.error {
|
|
36
|
-
border-color: #e4b5b5;
|
|
37
74
|
background: #fff7f7;
|
|
38
75
|
color: #8d1717;
|
|
39
|
-
box-shadow: 0 0 0 1px #
|
|
76
|
+
box-shadow: 0 0 0 1px #b13d3d33, 0 4px 16px #5f11110d;
|
|
40
77
|
}
|
|
41
78
|
.toast.error::before {
|
|
42
79
|
display: grid;
|
|
@@ -50,52 +87,51 @@
|
|
|
50
87
|
content: "!";
|
|
51
88
|
font-weight: 600;
|
|
52
89
|
}
|
|
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
90
|
.recovery {
|
|
74
|
-
position: fixed;
|
|
75
91
|
bottom: 100px;
|
|
76
|
-
|
|
77
|
-
transform: translateX(-50%);
|
|
78
|
-
z-index: 50;
|
|
79
|
-
display: flex;
|
|
80
|
-
justify-content: center;
|
|
81
|
-
align-items: center;
|
|
92
|
+
display: grid;
|
|
82
93
|
gap: 12px;
|
|
83
94
|
width: max-content;
|
|
84
|
-
max-width: min(
|
|
85
|
-
background: var(--ui-surface);
|
|
86
|
-
border: 1px solid var(--ui-border);
|
|
87
|
-
border-radius: 12px;
|
|
88
|
-
box-shadow: var(--ui-shadow);
|
|
95
|
+
max-width: min(420px, calc(100vw - 40px));
|
|
89
96
|
padding: 12px;
|
|
90
|
-
font-size: 13px;
|
|
91
|
-
line-height: 1.5;
|
|
92
97
|
}
|
|
93
|
-
.recovery
|
|
94
|
-
|
|
95
|
-
|
|
98
|
+
.recovery-actions {
|
|
99
|
+
display: flex;
|
|
100
|
+
flex-wrap: wrap;
|
|
101
|
+
justify-content: flex-end;
|
|
102
|
+
gap: 8px;
|
|
96
103
|
}
|
|
97
|
-
.recovery
|
|
98
|
-
|
|
104
|
+
.recovery-actions button {
|
|
105
|
+
min-height: 36px;
|
|
106
|
+
font-size: 12px;
|
|
107
|
+
border: 1px solid var(--ui-border);
|
|
108
|
+
}
|
|
109
|
+
.recovery-actions button:hover:not(:disabled) {
|
|
110
|
+
border-color: var(--ui-control);
|
|
111
|
+
}
|
|
112
|
+
input[aria-invalid="true"] {
|
|
113
|
+
border-color: #b13d3d;
|
|
114
|
+
box-shadow: none;
|
|
115
|
+
}
|
|
116
|
+
input[aria-invalid="true"]:focus-visible {
|
|
117
|
+
outline: 2px solid #b13d3d;
|
|
118
|
+
outline-offset: -1px;
|
|
119
|
+
}
|
|
120
|
+
.parameter-error {
|
|
121
|
+
position: fixed;
|
|
122
|
+
z-index: 60;
|
|
123
|
+
width: 260px;
|
|
124
|
+
padding: 10px 12px;
|
|
125
|
+
border: 1px solid #e4b5b5;
|
|
126
|
+
border-radius: 8px;
|
|
127
|
+
background: #fff7f7;
|
|
128
|
+
color: #8d1717;
|
|
129
|
+
box-shadow: 0 4px 16px #0000000a;
|
|
130
|
+
font-size: 12px;
|
|
131
|
+
line-height: 1.5;
|
|
132
|
+
}
|
|
133
|
+
@media (max-width: 900px) {
|
|
134
|
+
.toast { top: 16px; }
|
|
99
135
|
}
|
|
100
136
|
@media (prefers-reduced-motion: reduce) {
|
|
101
137
|
*,
|