konpeki 0.1.1 → 0.3.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 (53) hide show
  1. package/AGENTS.md +1 -1
  2. package/CONTRIBUTING.md +36 -0
  3. package/README.md +57 -21
  4. package/SECURITY.md +22 -0
  5. package/SETUP.md +112 -51
  6. package/composition/README.md +42 -52
  7. package/composition/compile.ts +2 -2
  8. package/composition/document.ts +2 -111
  9. package/composition/schema.json +12 -3
  10. package/composition/schema.ts +4 -2
  11. package/composition/types.ts +4 -21
  12. package/composition/validate.ts +3 -461
  13. package/composition/visualizations.ts +0 -16
  14. package/design/themes/README.md +25 -7
  15. package/design/themes/index.ts +15 -4
  16. package/docs/development.md +75 -11
  17. package/docs/workflow.md +60 -11
  18. package/index.html +17 -1
  19. package/package.json +10 -2
  20. package/plugin.json +22 -0
  21. package/public/og.png +0 -0
  22. package/runtime/konpeki.mjs +223 -473
  23. package/skills/konpeki/SKILL.md +186 -0
  24. package/skills/konpeki/assets/blank.json +23 -0
  25. package/skills/konpeki/scripts/ensure-runtime.mjs +69 -0
  26. package/skills/konpeki/scripts/prepare-document.mjs +40 -0
  27. package/slides/introducing-konpeki/PROMPT.md +21 -0
  28. package/slides/introducing-konpeki/README.md +52 -30
  29. package/slides/introducing-konpeki/SOURCE.md +16 -10
  30. package/slides/introducing-konpeki/author.ts +44 -42
  31. package/slides/introducing-konpeki/composition.json +1748 -1743
  32. package/src/app/App.tsx +179 -37
  33. package/src/components/BuildOrb.tsx +40 -0
  34. package/src/components/Canvas.tsx +18 -1
  35. package/src/components/InspectorPanel.tsx +130 -43
  36. package/src/components/LeftPanel.tsx +16 -3
  37. package/src/components/RevisionNotes.tsx +56 -0
  38. package/src/components/WorkspaceChrome.tsx +98 -11
  39. package/src/lib/examples/react-page-migration.json +1 -1
  40. package/src/lib/export-png.ts +4 -1
  41. package/src/lib/file-session.ts +14 -1
  42. package/src/lib/review.ts +26 -0
  43. package/src/lib/storage.ts +38 -10
  44. package/src/lib/use-file-session.ts +49 -13
  45. package/src/main.tsx +3 -0
  46. package/src/styles/base.css +16 -0
  47. package/src/styles/canvas.css +43 -12
  48. package/src/styles/chrome.css +174 -52
  49. package/src/styles/feedback.css +39 -4
  50. package/src/styles/left-panel.css +48 -7
  51. package/src/styles/right-panel.css +90 -47
  52. package/src/styles/shell.css +99 -53
  53. package/.agents/skills/authoring-visuals/SKILL.md +0 -82
@@ -8,29 +8,14 @@ import {
8
8
  type CompositionSlide,
9
9
  type ContentSlot,
10
10
  type Rect,
11
- type SemanticRelationship,
12
- type ThemeId,
13
- type AuthoringMode,
14
11
  } from "./types.ts";
15
12
  import { validateComposition } from "./validate.ts";
16
13
  import { appearanceOptions } from "./schema.ts";
17
14
  import { diagramDefinition } from "./visualizations.ts";
18
15
 
19
16
  export type Draft = CompositionDocument;
20
- type LegacyDraft = {
21
- title: string;
22
- audience: string;
23
- question: string;
24
- themeId: ThemeId;
25
- themeMode: "paper" | "night";
26
- authoringMode?: AuthoringMode;
27
- components: CompositionComponent[];
28
- readingOrder: string[];
29
- paintOrder: string[];
30
- relationships: SemanticRelationship[];
31
- };
32
17
  export type StoredDraftResult =
33
- { ok: true; draft: Draft; migrated: boolean } | { ok: false };
18
+ { ok: true; draft: Draft } | { ok: false };
34
19
  export type ParsedComposition =
35
20
  | { ok: true; document: CompositionDocument }
36
21
  | { ok: false; message: string };
@@ -574,78 +559,6 @@ export function duplicateComponent(draft: Draft, id: string, slideId?: string):
574
559
  };
575
560
  return validMutation(draft, next);
576
561
  }
577
- function legacyToComposition(draft: LegacyDraft): unknown {
578
- const components = draft.components;
579
- const rawComponents = components as unknown as Array<
580
- {
581
- id: string;
582
- kind: string;
583
- slotIds: string[];
584
- appearance?: { role?: string };
585
- intent?: string;
586
- }
587
- >;
588
- const contentSlots = rawComponents.flatMap((component) =>
589
- component.slotIds.map((id) => {
590
- const kind = component.kind;
591
- const source =
592
- kind === "footnote" ||
593
- (kind === "text-block" && component.appearance?.role === "footnote");
594
- const role = source
595
- ? "source"
596
- : kind === "headline" ||
597
- (kind === "text-block" && component.appearance?.role === "title")
598
- ? "takeaway"
599
- : ["visual", "evidence", "chart"].includes(kind)
600
- ? "evidence"
601
- : kind === "image"
602
- ? "image"
603
- : kind === "table"
604
- ? "table"
605
- : ["diagram", "process"].includes(kind)
606
- ? "process-step"
607
- : kind === "text-block"
608
- ? "body"
609
- : "entity";
610
- const base = {
611
- id,
612
- label: componentLabels[component.kind as CompositionComponent["kind"]] ??
613
- kind.replaceAll("-", " "),
614
- required: true,
615
- instruction: component.intent?.trim() || `Describe ${kind.replaceAll("-", " ")} content.`,
616
- };
617
- return role === "source"
618
- ? {
619
- ...base,
620
- role,
621
- targets: rawComponents
622
- .filter((candidate) => candidate.id !== component.id)
623
- .map((candidate) => candidate.id),
624
- }
625
- : { ...base, role };
626
- }),
627
- );
628
- return {
629
- schema: "konpeki-composition/v3",
630
- title: draft.title,
631
- ...(draft.authoringMode ? { authoringMode: draft.authoringMode } : {}),
632
- theme: { id: draft.themeId, mode: draft.themeMode },
633
- slide: {
634
- id: "slide-1",
635
- canvas: canvasSize,
636
- innerPadding: canvasPadding,
637
- audience: draft.audience,
638
- question: draft.question,
639
- intendedViewingSize: "presentation",
640
- contentSlots,
641
- components,
642
- groups: [],
643
- readingOrder: draft.readingOrder.map((id) => ({ kind: "component", id })),
644
- paintOrder: draft.paintOrder,
645
- relationships: draft.relationships,
646
- },
647
- };
648
- }
649
562
  export function serializeDraft(draft: Draft) {
650
563
  return JSON.stringify({ version: 2, document: draft });
651
564
  }
@@ -664,31 +577,9 @@ export function parseStoredDraft(raw: string): StoredDraftResult {
664
577
  return {
665
578
  ok: true,
666
579
  draft: { ...result.document, title: document.title },
667
- migrated: result.document.schema !== document.schema,
668
580
  };
669
581
  }
670
- const legacy = (parsed?.version === 1 ? parsed.draft : parsed) as LegacyDraft;
671
- if (
672
- !legacy ||
673
- typeof legacy.title !== "string" ||
674
- typeof legacy.audience !== "string" ||
675
- typeof legacy.question !== "string" ||
676
- !Array.isArray(legacy.readingOrder) ||
677
- !legacy.readingOrder.every((id: unknown) => typeof id === "string")
678
- )
679
- return { ok: false };
680
- const document = legacyToComposition(legacy) as { title: string };
681
- const result = validateComposition({
682
- ...document,
683
- title: document.title.trim() || "Untitled composition",
684
- });
685
- if (!result.ok)
686
- return { ok: false };
687
- return {
688
- ok: true,
689
- draft: { ...result.document, title: document.title },
690
- migrated: true,
691
- };
582
+ return { ok: false };
692
583
  } catch {
693
584
  return { ok: false };
694
585
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://vcfgdev.github.io/konpeki/composition/v18/schema.json",
2
+ "$id": "https://vcfgdev.github.io/konpeki/composition/v1/schema.json",
3
3
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
4
  "additionalProperties": false,
5
5
  "properties": {
@@ -11,7 +11,7 @@
11
11
  "type": "string"
12
12
  },
13
13
  "schema": {
14
- "const": "konpeki-composition/v18"
14
+ "const": "konpeki-composition/v1"
15
15
  },
16
16
  "slides": {
17
17
  "items": {
@@ -2968,6 +2968,15 @@
2968
2968
  "night"
2969
2969
  ],
2970
2970
  "type": "string"
2971
+ },
2972
+ "typography": {
2973
+ "enum": [
2974
+ "plex-sans",
2975
+ "noto-sans",
2976
+ "plex-serif",
2977
+ "hanken-grotesk"
2978
+ ],
2979
+ "type": "string"
2971
2980
  }
2972
2981
  },
2973
2982
  "required": [
@@ -2987,6 +2996,6 @@
2987
2996
  "title",
2988
2997
  "slides"
2989
2998
  ],
2990
- "title": "konpeki-composition/v18",
2999
+ "title": "konpeki-composition/v1",
2991
3000
  "type": "object"
2992
3001
  }
@@ -4,6 +4,7 @@ import {
4
4
  compositionSchema,
5
5
  themeIds,
6
6
  themeModes,
7
+ typographyIds,
7
8
  vectorElementKinds,
8
9
  } from "./types.ts";
9
10
  import { chartTemplates, diagramTypes } from "./visualizations.ts";
@@ -309,7 +310,7 @@ const components = componentKinds.map((kind) => {
309
310
  });
310
311
  export const schema = {
311
312
  $schema: "https://json-schema.org/draft/2020-12/schema",
312
- $id: "https://vcfgdev.github.io/konpeki/composition/v18/schema.json",
313
+ $id: "https://vcfgdev.github.io/konpeki/composition/v1/schema.json",
313
314
  title: compositionSchema,
314
315
  ...object(
315
316
  {
@@ -319,7 +320,8 @@ export const schema = {
319
320
  theme: object({
320
321
  id: enumeration(themeIds),
321
322
  mode: enumeration(themeModes),
322
- }),
323
+ typography: enumeration(typographyIds),
324
+ }, ["id", "mode"]),
323
325
  slides: array(
324
326
  object(
325
327
  {
@@ -1,26 +1,7 @@
1
1
  import type { ChartTemplate, DiagramType } from "./visualizations.ts";
2
2
  export type { ChartTemplate, DiagramType } from "./visualizations.ts";
3
3
 
4
- export const compositionSchema = "konpeki-composition/v18" as const;
5
- export const legacyCompositionSchemas = [
6
- "konpeki-composition/v1",
7
- "konpeki-composition/v2",
8
- "konpeki-composition/v3",
9
- "konpeki-composition/v4",
10
- "konpeki-composition/v5",
11
- "konpeki-composition/v6",
12
- "konpeki-composition/v7",
13
- "konpeki-composition/v8",
14
- "konpeki-composition/v9",
15
- "konpeki-composition/v10",
16
- "konpeki-composition/v11",
17
- "konpeki-composition/v12",
18
- "konpeki-composition/v13",
19
- "konpeki-composition/v14",
20
- "konpeki-composition/v15",
21
- "konpeki-composition/v16",
22
- "konpeki-composition/v17",
23
- ] as const;
4
+ export const compositionSchema = "konpeki-composition/v1" as const;
24
5
  export type CanvasSize = { width: number; height: number };
25
6
  export const canvasSize = { width: 1920, height: 1080 } as const;
26
7
  export const canvasPadding = {
@@ -44,6 +25,8 @@ export const themeIds = [
44
25
  export type ThemeId = (typeof themeIds)[number];
45
26
  export const themeModes = ["paper", "night"] as const;
46
27
  export type ThemeMode = (typeof themeModes)[number];
28
+ export const typographyIds = ["plex-sans", "noto-sans", "plex-serif", "hanken-grotesk"] as const;
29
+ export type TypographyId = (typeof typographyIds)[number];
47
30
  export type Rect = { x: number; y: number; width: number; height: number };
48
31
  export type Alignment = "start" | "center" | "end";
49
32
  export type TitleStyle = "plain" | "prominent";
@@ -281,6 +264,6 @@ export type CompositionDocument = {
281
264
  schema: typeof compositionSchema;
282
265
  title: string;
283
266
  authoringMode?: AuthoringMode;
284
- theme?: { id: ThemeId; mode: ThemeMode };
267
+ theme?: { id: ThemeId; mode: ThemeMode; typography?: TypographyId };
285
268
  slides: CompositionSlide[];
286
269
  };