kasaframe 0.1.3 → 0.1.4
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/README.md +1 -1
- package/docs/AGENTS.md +1 -1
- package/package.json +1 -1
- package/packages/adapters/src/project.ts +4 -0
- package/packages/adapters/src/texture.ts +94 -0
- package/packages/cli/src/cells.ts +227 -0
- package/packages/cli/src/commands/make.ts +77 -9
- package/packages/cli/src/commands/new.ts +2 -2
- package/packages/cli/src/commands/theme.ts +141 -10
- package/packages/cli/src/lock.ts +8 -6
- package/packages/cli/src/pick.ts +110 -0
- package/packages/cli/src/vary.ts +124 -0
- package/packages/core/src/index.ts +1 -1
- package/packages/core/src/project.ts +15 -0
- package/packages/director/src/assemble.ts +6 -3
- package/packages/motion/src/moves/menu.ts +2 -1
- package/packages/patterns/src/kit.ts +3 -2
- package/packages/plan/src/asks.ts +25 -16
- package/packages/plan/src/index.ts +2 -2
- package/packages/plan/src/plan.ts +4 -2
- package/packages/plan/src/themes.ts +65 -9
- package/packages/plan/src/types.ts +3 -0
- package/packages/themes/kit/THEME-MAKE.md +1 -0
- package/packages/themes/kit/fonts.json +743 -0
- package/packages/themes/package.json +6 -1
- package/packages/themes/src/color.ts +152 -0
- package/packages/themes/src/fx.ts +4 -2
- package/packages/themes/src/index.ts +67 -3
- package/packages/themes/src/look.ts +223 -0
- package/packages/themes/src/name.ts +9 -0
- package/packages/themes/src/palette.ts +194 -0
- package/packages/themes/src/slotkit.ts +14 -1
- package/packages/themes/src/slots.ts +17 -2
- package/packages/themes/src/types.ts +84 -0
- package/packages/themes/src/vary.ts +290 -0
- package/themes/blueprint/THEME.md +64 -0
- package/themes/blueprint/effects.ts +570 -0
- package/themes/blueprint/sample/assets/og/logo.svg +12 -0
- package/themes/blueprint/sample/beats.json +1005 -0
- package/themes/blueprint/sample/index.html +11 -0
- package/themes/blueprint/sample/kf.json +59 -0
- package/themes/blueprint/sample/lib/facts.ts +29 -0
- package/themes/blueprint/sample/lib/sheet.ts +55 -0
- package/themes/blueprint/sample/main.ts +9 -0
- package/themes/blueprint/sample/scenes/end.ts +91 -0
- package/themes/blueprint/sample/scenes/gather.ts +75 -0
- package/themes/blueprint/sample/scenes/models.ts +117 -0
- package/themes/blueprint/sample/scenes/price.ts +94 -0
- package/themes/blueprint/sample/style.json +114 -0
- package/themes/blueprint/slots.ts +88 -0
- package/themes/blueprint/still.png +0 -0
- package/themes/blueprint/style.json +114 -0
- package/themes/blueprint/theme.json +137 -0
- package/themes/blueprint/variants/deep-rose-2.json +90 -0
- package/themes/blueprint/variants/deep-rose-suit.json +117 -0
- package/themes/blueprint/variants/deep-rose.json +117 -0
- package/themes/blueprint/variants/navy-coral-2.json +118 -0
- package/themes/blueprint/variants/navy-coral-suit.json +118 -0
- package/themes/blueprint/variants/navy-coral.json +128 -0
- package/themes/blueprint/variants/navy-orange-2.json +118 -0
- package/themes/blueprint/variants/navy-orange-3.json +91 -0
- package/themes/blueprint/variants/navy-orange-4.json +128 -0
- package/themes/blueprint/variants/navy-orange-mono.json +128 -0
- package/themes/blueprint/variants/navy-orange-plex.json +128 -0
- package/themes/blueprint/variants/navy-orange-suit.json +118 -0
- package/themes/blueprint/variants/navy-orange.json +118 -0
- package/themes/blueprint/variants/navy-rose-plex.json +127 -0
- package/themes/blueprint/variants/navy-rose.json +127 -0
- package/themes/cartography/THEME.md +61 -0
- package/themes/cartography/effects.ts +845 -0
- package/themes/cartography/sample/assets/og/logo.svg +12 -0
- package/themes/cartography/sample/beats.json +1005 -0
- package/themes/cartography/sample/index.html +11 -0
- package/themes/cartography/sample/kf.json +59 -0
- package/themes/cartography/sample/lib/facts.ts +29 -0
- package/themes/cartography/sample/lib/map.ts +39 -0
- package/themes/cartography/sample/main.ts +9 -0
- package/themes/cartography/sample/scenes/end.ts +56 -0
- package/themes/cartography/sample/scenes/gather.ts +46 -0
- package/themes/cartography/sample/scenes/models.ts +43 -0
- package/themes/cartography/sample/scenes/price.ts +73 -0
- package/themes/cartography/sample/style.json +103 -0
- package/themes/cartography/slots.ts +87 -0
- package/themes/cartography/still.png +0 -0
- package/themes/cartography/style.json +103 -0
- package/themes/cartography/theme.json +160 -0
- package/themes/cartography/variants/blush-amber.json +128 -0
- package/themes/cartography/variants/blush-indigo.json +128 -0
- package/themes/cartography/variants/blush-pink.json +136 -0
- package/themes/cartography/variants/chalk-plum.json +137 -0
- package/themes/cartography/variants/chalk-sky.json +100 -0
- package/themes/cartography/variants/cocoa-amber.json +128 -0
- package/themes/cartography/variants/deep-plum.json +125 -0
- package/themes/cartography/variants/dusk-coral.json +128 -0
- package/themes/cartography/variants/forest-lime.json +131 -0
- package/themes/cartography/variants/frost-teal.json +128 -0
- package/themes/cartography/variants/navy-green.json +131 -0
- package/themes/cartography/variants/navy-indigo.json +138 -0
- package/themes/cartography/variants/navy-sky.json +100 -0
- package/themes/cartography/variants/sage-green.json +127 -0
- package/themes/cartography/variants/wine-teal.json +128 -0
- package/themes/circuit-board/THEME.md +61 -0
- package/themes/circuit-board/effects.ts +576 -0
- package/themes/circuit-board/pcb.ts +103 -0
- package/themes/circuit-board/sample/assets/og/logo.svg +12 -0
- package/themes/circuit-board/sample/beats.json +1005 -0
- package/themes/circuit-board/sample/index.html +11 -0
- package/themes/circuit-board/sample/kf.json +59 -0
- package/themes/circuit-board/sample/lib/facts.ts +29 -0
- package/themes/circuit-board/sample/lib/kit.ts +45 -0
- package/themes/circuit-board/sample/main.ts +9 -0
- package/themes/circuit-board/sample/scenes/end.ts +102 -0
- package/themes/circuit-board/sample/scenes/gather.ts +76 -0
- package/themes/circuit-board/sample/scenes/models.ts +101 -0
- package/themes/circuit-board/sample/scenes/price.ts +109 -0
- package/themes/circuit-board/sample/style.json +104 -0
- package/themes/circuit-board/slots.ts +108 -0
- package/themes/circuit-board/still.png +0 -0
- package/themes/circuit-board/style.json +104 -0
- package/themes/circuit-board/theme.json +149 -0
- package/themes/circuit-board/variants/deep-gold-plex.json +133 -0
- package/themes/circuit-board/variants/deep-gold.json +123 -0
- package/themes/circuit-board/variants/dusk-gold-grain.json +138 -0
- package/themes/circuit-board/variants/dusk-gold-pretendard.json +118 -0
- package/themes/circuit-board/variants/dusk-gold.json +97 -0
- package/themes/circuit-board/variants/forest-gold-2.json +96 -0
- package/themes/circuit-board/variants/forest-gold-grain.json +129 -0
- package/themes/circuit-board/variants/forest-gold-mono.json +124 -0
- package/themes/circuit-board/variants/forest-gold.json +128 -0
- package/themes/circuit-board/variants/navy-gold-grain.json +124 -0
- package/themes/circuit-board/variants/navy-gold.json +101 -0
- package/themes/circuit-board/variants/wine-gold-grain.json +128 -0
- package/themes/circuit-board/variants/wine-gold-plex.json +133 -0
- package/themes/circuit-board/variants/wine-gold-pretendard.json +118 -0
- package/themes/circuit-board/variants/wine-gold.json +128 -0
- package/themes/clay-toy/THEME.md +73 -0
- package/themes/clay-toy/effects.ts +643 -0
- package/themes/clay-toy/glyphs.ts +32 -0
- package/themes/clay-toy/sample/assets/og/logo.svg +12 -0
- package/themes/clay-toy/sample/beats.json +1005 -0
- package/themes/clay-toy/sample/index.html +11 -0
- package/themes/clay-toy/sample/kf.json +59 -0
- package/themes/clay-toy/sample/lib/clay.ts +20 -0
- package/themes/clay-toy/sample/lib/facts.ts +29 -0
- package/themes/clay-toy/sample/main.ts +9 -0
- package/themes/clay-toy/sample/scenes/end.ts +81 -0
- package/themes/clay-toy/sample/scenes/gather.ts +53 -0
- package/themes/clay-toy/sample/scenes/models.ts +77 -0
- package/themes/clay-toy/sample/scenes/price.ts +91 -0
- package/themes/clay-toy/sample/style.json +101 -0
- package/themes/clay-toy/slots.ts +132 -0
- package/themes/clay-toy/still.png +0 -0
- package/themes/clay-toy/style.json +101 -0
- package/themes/clay-toy/theme.json +146 -0
- package/themes/clay-toy/variants/blush-coral-grain.json +126 -0
- package/themes/clay-toy/variants/blush-coral.json +123 -0
- package/themes/clay-toy/variants/chalk-indigo.json +97 -0
- package/themes/clay-toy/variants/chalk-jade.json +125 -0
- package/themes/clay-toy/variants/chalk-teal.json +120 -0
- package/themes/clay-toy/variants/frost-orange.json +125 -0
- package/themes/clay-toy/variants/frost-sky-grain.json +126 -0
- package/themes/clay-toy/variants/frost-sky.json +121 -0
- package/themes/clay-toy/variants/frost-teal.json +120 -0
- package/themes/clay-toy/variants/lilac-green.json +120 -0
- package/themes/clay-toy/variants/lilac-plum-round.json +120 -0
- package/themes/clay-toy/variants/lilac-plum.json +124 -0
- package/themes/clay-toy/variants/sage-indigo.json +125 -0
- package/themes/clay-toy/variants/sage-magenta.json +119 -0
- package/themes/clay-toy/variants/sand-amber.json +125 -0
- package/themes/conveyor-factory/THEME.md +71 -0
- package/themes/conveyor-factory/effects.ts +744 -0
- package/themes/conveyor-factory/sample/assets/og/logo.svg +12 -0
- package/themes/conveyor-factory/sample/beats.json +1005 -0
- package/themes/conveyor-factory/sample/index.html +11 -0
- package/themes/conveyor-factory/sample/kf.json +59 -0
- package/themes/conveyor-factory/sample/lib/factory.ts +48 -0
- package/themes/conveyor-factory/sample/lib/facts.ts +29 -0
- package/themes/conveyor-factory/sample/main.ts +9 -0
- package/themes/conveyor-factory/sample/scenes/end.ts +44 -0
- package/themes/conveyor-factory/sample/scenes/gather.ts +47 -0
- package/themes/conveyor-factory/sample/scenes/models.ts +91 -0
- package/themes/conveyor-factory/sample/scenes/price.ts +77 -0
- package/themes/conveyor-factory/sample/style.json +107 -0
- package/themes/conveyor-factory/slots.ts +121 -0
- package/themes/conveyor-factory/still.png +0 -0
- package/themes/conveyor-factory/style.json +107 -0
- package/themes/conveyor-factory/theme.json +142 -0
- package/themes/conveyor-factory/variants/cocoa-gold.json +125 -0
- package/themes/conveyor-factory/variants/dusk-gold.json +135 -0
- package/themes/conveyor-factory/variants/forest-gold.json +135 -0
- package/themes/conveyor-factory/variants/navy-amber.json +93 -0
- package/themes/conveyor-factory/variants/navy-gold.json +120 -0
- package/themes/conveyor-factory/variants/slate-amber-2.json +120 -0
- package/themes/conveyor-factory/variants/slate-amber-grain.json +125 -0
- package/themes/conveyor-factory/variants/slate-amber-suit.json +120 -0
- package/themes/conveyor-factory/variants/slate-amber.json +125 -0
- package/themes/conveyor-factory/variants/slate-gold-bold.json +120 -0
- package/themes/conveyor-factory/variants/slate-gold.json +120 -0
- package/themes/data-journal/THEME.md +74 -0
- package/themes/data-journal/effects.ts +570 -0
- package/themes/data-journal/sample/assets/og/logo.svg +12 -0
- package/themes/data-journal/sample/beats.json +1005 -0
- package/themes/data-journal/sample/index.html +11 -0
- package/themes/data-journal/sample/kf.json +59 -0
- package/themes/data-journal/sample/lib/facts.ts +29 -0
- package/themes/data-journal/sample/lib/page.ts +25 -0
- package/themes/data-journal/sample/main.ts +9 -0
- package/themes/data-journal/sample/scenes/end.ts +69 -0
- package/themes/data-journal/sample/scenes/gather.ts +58 -0
- package/themes/data-journal/sample/scenes/models.ts +51 -0
- package/themes/data-journal/sample/scenes/price.ts +73 -0
- package/themes/data-journal/sample/style.json +114 -0
- package/themes/data-journal/slots.ts +119 -0
- package/themes/data-journal/still.png +0 -0
- package/themes/data-journal/style.json +114 -0
- package/themes/data-journal/theme.json +140 -0
- package/themes/data-journal/variants/blush-green.json +129 -0
- package/themes/data-journal/variants/chalk-magenta.json +138 -0
- package/themes/data-journal/variants/cocoa-amber.json +140 -0
- package/themes/data-journal/variants/cocoa-sky.json +130 -0
- package/themes/data-journal/variants/deep-coral.json +135 -0
- package/themes/data-journal/variants/dusk-plum.json +132 -0
- package/themes/data-journal/variants/forest-green.json +138 -0
- package/themes/data-journal/variants/frost-indigo.json +141 -0
- package/themes/data-journal/variants/lilac-amber.json +141 -0
- package/themes/data-journal/variants/navy-indigo.json +131 -0
- package/themes/data-journal/variants/navy-lime.json +128 -0
- package/themes/data-journal/variants/snow-sky.json +125 -0
- package/themes/data-journal/variants/wine-indigo.json +129 -0
- package/themes/data-journal/variants/wine-magenta.json +138 -0
- package/themes/data-journal/variants/wine-teal.json +97 -0
- package/themes/debug-hud/theme.json +56 -0
- package/themes/debug-hud/variants/cocoa-gold.json +113 -0
- package/themes/debug-hud/variants/cocoa-teal.json +119 -0
- package/themes/debug-hud/variants/deep-cyan.json +85 -0
- package/themes/debug-hud/variants/deep-teal-scan.json +118 -0
- package/themes/debug-hud/variants/deep-teal.json +112 -0
- package/themes/debug-hud/variants/dusk-plum.json +116 -0
- package/themes/debug-hud/variants/dusk-violet.json +112 -0
- package/themes/debug-hud/variants/forest-amber.json +86 -0
- package/themes/debug-hud/variants/forest-lime.json +117 -0
- package/themes/debug-hud/variants/forest-magenta.json +111 -0
- package/themes/debug-hud/variants/navy-jade.json +79 -0
- package/themes/debug-hud/variants/slate-green.json +112 -0
- package/themes/debug-hud/variants/wine-gold.json +119 -0
- package/themes/debug-hud/variants/wine-jade.json +83 -0
- package/themes/debug-hud/variants/wine-sky.json +112 -0
- package/themes/depth-flight/THEME.md +54 -0
- package/themes/depth-flight/effects.ts +396 -0
- package/themes/depth-flight/sample/assets/og/logo.svg +12 -0
- package/themes/depth-flight/sample/beats.json +1005 -0
- package/themes/depth-flight/sample/index.html +11 -0
- package/themes/depth-flight/sample/kf.json +59 -0
- package/themes/depth-flight/sample/lib/facts.ts +29 -0
- package/themes/depth-flight/sample/lib/fly.ts +15 -0
- package/themes/depth-flight/sample/main.ts +9 -0
- package/themes/depth-flight/sample/scenes/end.ts +51 -0
- package/themes/depth-flight/sample/scenes/gather.ts +40 -0
- package/themes/depth-flight/sample/scenes/models.ts +75 -0
- package/themes/depth-flight/sample/scenes/price.ts +50 -0
- package/themes/depth-flight/sample/style.json +94 -0
- package/themes/depth-flight/slots.ts +196 -0
- package/themes/depth-flight/still.png +0 -0
- package/themes/depth-flight/style.json +94 -0
- package/themes/depth-flight/theme.json +119 -0
- package/themes/depth-flight/variants/cocoa-cyan.json +121 -0
- package/themes/depth-flight/variants/cocoa-indigo.json +121 -0
- package/themes/depth-flight/variants/cocoa-violet.json +122 -0
- package/themes/depth-flight/variants/deep-sky.json +126 -0
- package/themes/depth-flight/variants/dusk-violet-bold.json +117 -0
- package/themes/depth-flight/variants/dusk-violet.json +132 -0
- package/themes/depth-flight/variants/forest-blue.json +116 -0
- package/themes/depth-flight/variants/forest-cyan.json +122 -0
- package/themes/depth-flight/variants/navy-sky-grain.json +122 -0
- package/themes/depth-flight/variants/navy-sky.json +116 -0
- package/themes/depth-flight/variants/night-teal.json +116 -0
- package/themes/depth-flight/variants/slate-cyan.json +127 -0
- package/themes/depth-flight/variants/slate-indigo.json +116 -0
- package/themes/depth-flight/variants/slate-sky.json +94 -0
- package/themes/depth-flight/variants/slate-violet.json +121 -0
- package/themes/film-reel/THEME.md +60 -0
- package/themes/film-reel/effects.ts +477 -0
- package/themes/film-reel/sample/assets/og/logo.svg +12 -0
- package/themes/film-reel/sample/beats.json +1005 -0
- package/themes/film-reel/sample/index.html +11 -0
- package/themes/film-reel/sample/kf.json +59 -0
- package/themes/film-reel/sample/lib/facts.ts +29 -0
- package/themes/film-reel/sample/lib/reel.ts +9 -0
- package/themes/film-reel/sample/main.ts +9 -0
- package/themes/film-reel/sample/scenes/end.ts +31 -0
- package/themes/film-reel/sample/scenes/gather.ts +40 -0
- package/themes/film-reel/sample/scenes/models.ts +37 -0
- package/themes/film-reel/sample/scenes/price.ts +63 -0
- package/themes/film-reel/sample/style.json +103 -0
- package/themes/film-reel/slots.ts +75 -0
- package/themes/film-reel/still.png +0 -0
- package/themes/film-reel/style.json +103 -0
- package/themes/film-reel/theme.json +142 -0
- package/themes/film-reel/variants/chalk-amber.json +124 -0
- package/themes/film-reel/variants/chalk-pink.json +123 -0
- package/themes/film-reel/variants/cream-violet.json +121 -0
- package/themes/film-reel/variants/frost-blue.json +126 -0
- package/themes/film-reel/variants/frost-green.json +123 -0
- package/themes/film-reel/variants/frost-indigo.json +121 -0
- package/themes/film-reel/variants/frost-jade.json +120 -0
- package/themes/film-reel/variants/frost-plum.json +120 -0
- package/themes/film-reel/variants/frost-teal.json +93 -0
- package/themes/film-reel/variants/lilac-gold.json +120 -0
- package/themes/film-reel/variants/lilac-jade.json +123 -0
- package/themes/film-reel/variants/lilac-magenta.json +125 -0
- package/themes/film-reel/variants/lilac-violet.json +122 -0
- package/themes/film-reel/variants/sand-cyan.json +124 -0
- package/themes/film-reel/variants/sand-lime.json +96 -0
- package/themes/glass-light/THEME.md +55 -0
- package/themes/glass-light/effects.ts +433 -0
- package/themes/glass-light/sample/assets/og/logo.svg +12 -0
- package/themes/glass-light/sample/beats.json +1005 -0
- package/themes/glass-light/sample/index.html +11 -0
- package/themes/glass-light/sample/kf.json +59 -0
- package/themes/glass-light/sample/lib/facts.ts +29 -0
- package/themes/glass-light/sample/lib/glass.ts +81 -0
- package/themes/glass-light/sample/main.ts +9 -0
- package/themes/glass-light/sample/scenes/end.ts +43 -0
- package/themes/glass-light/sample/scenes/gather.ts +38 -0
- package/themes/glass-light/sample/scenes/models.ts +46 -0
- package/themes/glass-light/sample/scenes/price.ts +46 -0
- package/themes/glass-light/sample/style.json +94 -0
- package/themes/glass-light/slots.ts +198 -0
- package/themes/glass-light/still.png +0 -0
- package/themes/glass-light/style.json +94 -0
- package/themes/glass-light/theme.json +119 -0
- package/themes/glass-light/variants/blush-coral.json +116 -0
- package/themes/glass-light/variants/blush-orange.json +115 -0
- package/themes/glass-light/variants/blush-pink.json +119 -0
- package/themes/glass-light/variants/blush-plum.json +115 -0
- package/themes/glass-light/variants/blush-teal.json +115 -0
- package/themes/glass-light/variants/cream-blue.json +125 -0
- package/themes/glass-light/variants/cream-pink.json +87 -0
- package/themes/glass-light/variants/cream-violet.json +119 -0
- package/themes/glass-light/variants/frost-green.json +115 -0
- package/themes/glass-light/variants/frost-sky-suit.json +115 -0
- package/themes/glass-light/variants/frost-sky.json +121 -0
- package/themes/glass-light/variants/lilac-gold.json +126 -0
- package/themes/glass-light/variants/lilac-plum.json +114 -0
- package/themes/glass-light/variants/sage-green.json +119 -0
- package/themes/glass-light/variants/sage-rose.json +114 -0
- package/themes/ink-wash/THEME.md +59 -0
- package/themes/ink-wash/effects.ts +574 -0
- package/themes/ink-wash/sample/assets/og/logo.svg +12 -0
- package/themes/ink-wash/sample/beats.json +1005 -0
- package/themes/ink-wash/sample/index.html +11 -0
- package/themes/ink-wash/sample/kf.json +59 -0
- package/themes/ink-wash/sample/lib/facts.ts +29 -0
- package/themes/ink-wash/sample/lib/ink.ts +35 -0
- package/themes/ink-wash/sample/main.ts +9 -0
- package/themes/ink-wash/sample/scenes/end.ts +72 -0
- package/themes/ink-wash/sample/scenes/gather.ts +53 -0
- package/themes/ink-wash/sample/scenes/models.ts +58 -0
- package/themes/ink-wash/sample/scenes/price.ts +85 -0
- package/themes/ink-wash/sample/style.json +108 -0
- package/themes/ink-wash/slots.ts +150 -0
- package/themes/ink-wash/still.png +0 -0
- package/themes/ink-wash/style.json +108 -0
- package/themes/ink-wash/theme.json +131 -0
- package/themes/ink-wash/variants/blush-orange.json +125 -0
- package/themes/ink-wash/variants/blush-rose.json +124 -0
- package/themes/ink-wash/variants/chalk-coral-grain.json +125 -0
- package/themes/ink-wash/variants/chalk-coral-serif.json +118 -0
- package/themes/ink-wash/variants/chalk-coral.json +120 -0
- package/themes/ink-wash/variants/chalk-orange-grain.json +97 -0
- package/themes/ink-wash/variants/chalk-orange-serif.json +120 -0
- package/themes/ink-wash/variants/chalk-orange.json +120 -0
- package/themes/ink-wash/variants/frost-coral.json +119 -0
- package/themes/ink-wash/variants/frost-rose.json +91 -0
- package/themes/ink-wash/variants/lilac-coral.json +96 -0
- package/themes/ink-wash/variants/sage-coral.json +119 -0
- package/themes/ink-wash/variants/sage-rose.json +119 -0
- package/themes/ink-wash/variants/sand-coral.json +125 -0
- package/themes/ink-wash/variants/sand-orange.json +120 -0
- package/themes/iso-diorama/THEME.md +54 -0
- package/themes/iso-diorama/effects.ts +374 -0
- package/themes/iso-diorama/sample/assets/og/logo.svg +12 -0
- package/themes/iso-diorama/sample/beats.json +1005 -0
- package/themes/iso-diorama/sample/index.html +11 -0
- package/themes/iso-diorama/sample/kf.json +59 -0
- package/themes/iso-diorama/sample/lib/facts.ts +29 -0
- package/themes/iso-diorama/sample/lib/iso.ts +22 -0
- package/themes/iso-diorama/sample/main.ts +9 -0
- package/themes/iso-diorama/sample/scenes/end.ts +41 -0
- package/themes/iso-diorama/sample/scenes/gather.ts +39 -0
- package/themes/iso-diorama/sample/scenes/models.ts +55 -0
- package/themes/iso-diorama/sample/scenes/price.ts +49 -0
- package/themes/iso-diorama/sample/style.json +98 -0
- package/themes/iso-diorama/slots.ts +222 -0
- package/themes/iso-diorama/still.png +0 -0
- package/themes/iso-diorama/style.json +98 -0
- package/themes/iso-diorama/theme.json +131 -0
- package/themes/iso-diorama/variants/chalk-plum.json +121 -0
- package/themes/iso-diorama/variants/cocoa-gold.json +93 -0
- package/themes/iso-diorama/variants/cocoa-indigo.json +122 -0
- package/themes/iso-diorama/variants/cocoa-rose.json +125 -0
- package/themes/iso-diorama/variants/deep-green.json +125 -0
- package/themes/iso-diorama/variants/deep-plum.json +120 -0
- package/themes/iso-diorama/variants/dusk-blue.json +126 -0
- package/themes/iso-diorama/variants/dusk-coral.json +122 -0
- package/themes/iso-diorama/variants/dusk-jade.json +121 -0
- package/themes/iso-diorama/variants/forest-cyan.json +127 -0
- package/themes/iso-diorama/variants/frost-blue.json +126 -0
- package/themes/iso-diorama/variants/frost-green.json +126 -0
- package/themes/iso-diorama/variants/frost-orange.json +125 -0
- package/themes/iso-diorama/variants/frost-teal.json +123 -0
- package/themes/iso-diorama/variants/navy-amber.json +125 -0
- package/themes/isotype/THEME.md +58 -0
- package/themes/isotype/effects.ts +297 -0
- package/themes/isotype/kit.ts +102 -0
- package/themes/isotype/sample/assets/og/logo.svg +12 -0
- package/themes/isotype/sample/beats.json +1005 -0
- package/themes/isotype/sample/index.html +11 -0
- package/themes/isotype/sample/kf.json +59 -0
- package/themes/isotype/sample/lib/chart.ts +47 -0
- package/themes/isotype/sample/lib/facts.ts +29 -0
- package/themes/isotype/sample/main.ts +9 -0
- package/themes/isotype/sample/scenes/end.ts +80 -0
- package/themes/isotype/sample/scenes/gather.ts +65 -0
- package/themes/isotype/sample/scenes/models.ts +75 -0
- package/themes/isotype/sample/scenes/price.ts +90 -0
- package/themes/isotype/sample/style.json +101 -0
- package/themes/isotype/slots.ts +74 -0
- package/themes/isotype/still.png +0 -0
- package/themes/isotype/style.json +101 -0
- package/themes/isotype/theme.json +140 -0
- package/themes/isotype/variants/blush-rose.json +127 -0
- package/themes/isotype/variants/chalk-amber.json +123 -0
- package/themes/isotype/variants/chalk-coral-bold.json +118 -0
- package/themes/isotype/variants/chalk-coral.json +117 -0
- package/themes/isotype/variants/chalk-orange.json +128 -0
- package/themes/isotype/variants/frost-amber-plex.json +128 -0
- package/themes/isotype/variants/frost-amber.json +123 -0
- package/themes/isotype/variants/frost-coral-grain.json +95 -0
- package/themes/isotype/variants/frost-coral.json +123 -0
- package/themes/isotype/variants/frost-orange.json +123 -0
- package/themes/isotype/variants/lilac-rose.json +127 -0
- package/themes/isotype/variants/sage-coral.json +90 -0
- package/themes/isotype/variants/sand-amber.json +118 -0
- package/themes/isotype/variants/sand-orange.json +128 -0
- package/themes/kawaii-sticker/THEME.md +44 -0
- package/themes/kawaii-sticker/effects.ts +412 -0
- package/themes/kawaii-sticker/sample/assets/stickers/bolt.png +0 -0
- package/themes/kawaii-sticker/sample/assets/stickers/bubble.png +0 -0
- package/themes/kawaii-sticker/sample/assets/stickers/clock.png +0 -0
- package/themes/kawaii-sticker/sample/assets/stickers/coin.png +0 -0
- package/themes/kawaii-sticker/sample/assets/stickers/moon.png +0 -0
- package/themes/kawaii-sticker/sample/assets/stickers/og-logo.svg +12 -0
- package/themes/kawaii-sticker/sample/assets/stickers/server.png +0 -0
- package/themes/kawaii-sticker/sample/beats.json +1 -0
- package/themes/kawaii-sticker/sample/index.html +11 -0
- package/themes/kawaii-sticker/sample/kf.json +66 -0
- package/themes/kawaii-sticker/sample/lib/og.ts +54 -0
- package/themes/kawaii-sticker/sample/main.ts +9 -0
- package/themes/kawaii-sticker/sample/scenes/end.ts +37 -0
- package/themes/kawaii-sticker/sample/scenes/gather.ts +50 -0
- package/themes/kawaii-sticker/sample/scenes/models.ts +43 -0
- package/themes/kawaii-sticker/sample/scenes/one.ts +45 -0
- package/themes/kawaii-sticker/sample/scenes/price.ts +47 -0
- package/themes/kawaii-sticker/sample/style.json +99 -0
- package/themes/kawaii-sticker/slots.ts +95 -0
- package/themes/kawaii-sticker/still.png +0 -0
- package/themes/kawaii-sticker/style.json +99 -0
- package/themes/kawaii-sticker/theme.json +145 -0
- package/themes/kawaii-sticker/variants/blush-coral.json +134 -0
- package/themes/kawaii-sticker/variants/blush-teal.json +129 -0
- package/themes/kawaii-sticker/variants/blush-violet.json +134 -0
- package/themes/kawaii-sticker/variants/cream-gold.json +135 -0
- package/themes/kawaii-sticker/variants/deep-jade.json +134 -0
- package/themes/kawaii-sticker/variants/dusk-green.json +134 -0
- package/themes/kawaii-sticker/variants/dusk-indigo.json +130 -0
- package/themes/kawaii-sticker/variants/dusk-sky.json +135 -0
- package/themes/kawaii-sticker/variants/dusk-teal.json +134 -0
- package/themes/kawaii-sticker/variants/frost-blue.json +135 -0
- package/themes/kawaii-sticker/variants/frost-plum.json +133 -0
- package/themes/kawaii-sticker/variants/lilac-violet.json +133 -0
- package/themes/kawaii-sticker/variants/navy-gold.json +134 -0
- package/themes/kawaii-sticker/variants/navy-plum.json +134 -0
- package/themes/kawaii-sticker/variants/sage-sky.json +107 -0
- package/themes/lab-notebook/THEME.md +56 -0
- package/themes/lab-notebook/effects.ts +423 -0
- package/themes/lab-notebook/kit.ts +84 -0
- package/themes/lab-notebook/sample/assets/og/logo.svg +12 -0
- package/themes/lab-notebook/sample/beats.json +1005 -0
- package/themes/lab-notebook/sample/index.html +11 -0
- package/themes/lab-notebook/sample/kf.json +59 -0
- package/themes/lab-notebook/sample/lib/facts.ts +29 -0
- package/themes/lab-notebook/sample/lib/note.ts +53 -0
- package/themes/lab-notebook/sample/main.ts +9 -0
- package/themes/lab-notebook/sample/scenes/end.ts +127 -0
- package/themes/lab-notebook/sample/scenes/gather.ts +83 -0
- package/themes/lab-notebook/sample/scenes/models.ts +73 -0
- package/themes/lab-notebook/sample/scenes/price.ts +89 -0
- package/themes/lab-notebook/sample/style.json +109 -0
- package/themes/lab-notebook/slots.ts +75 -0
- package/themes/lab-notebook/still.png +0 -0
- package/themes/lab-notebook/style.json +109 -0
- package/themes/lab-notebook/theme.json +141 -0
- package/themes/lab-notebook/variants/blush-orange.json +125 -0
- package/themes/lab-notebook/variants/chalk-coral.json +126 -0
- package/themes/lab-notebook/variants/chalk-orange.json +129 -0
- package/themes/lab-notebook/variants/chalk-rose-2.json +96 -0
- package/themes/lab-notebook/variants/chalk-rose.json +125 -0
- package/themes/lab-notebook/variants/frost-orange.json +101 -0
- package/themes/lab-notebook/variants/frost-rose-grain.json +101 -0
- package/themes/lab-notebook/variants/frost-rose.json +96 -0
- package/themes/lab-notebook/variants/lilac-rose-2.json +96 -0
- package/themes/lab-notebook/variants/lilac-rose.json +128 -0
- package/themes/lab-notebook/variants/sage-rose.json +124 -0
- package/themes/lab-notebook/variants/sand-orange-grain.json +101 -0
- package/themes/lab-notebook/variants/sand-orange.json +129 -0
- package/themes/lab-notebook/variants/snow-orange.json +129 -0
- package/themes/lab-notebook/variants/snow-rose.json +124 -0
- package/themes/manga-panel/THEME.md +60 -0
- package/themes/manga-panel/effects.ts +791 -0
- package/themes/manga-panel/sample/assets/og/logo.svg +12 -0
- package/themes/manga-panel/sample/beats.json +1005 -0
- package/themes/manga-panel/sample/index.html +11 -0
- package/themes/manga-panel/sample/kf.json +59 -0
- package/themes/manga-panel/sample/lib/facts.ts +29 -0
- package/themes/manga-panel/sample/lib/manga.ts +58 -0
- package/themes/manga-panel/sample/main.ts +9 -0
- package/themes/manga-panel/sample/scenes/end.ts +96 -0
- package/themes/manga-panel/sample/scenes/gather.ts +100 -0
- package/themes/manga-panel/sample/scenes/models.ts +96 -0
- package/themes/manga-panel/sample/scenes/price.ts +154 -0
- package/themes/manga-panel/sample/style.json +105 -0
- package/themes/manga-panel/slots.ts +127 -0
- package/themes/manga-panel/still.png +0 -0
- package/themes/manga-panel/style.json +105 -0
- package/themes/manga-panel/theme.json +148 -0
- package/themes/manga-panel/variants/chalk-cyan-dots.json +122 -0
- package/themes/manga-panel/variants/chalk-cyan.json +122 -0
- package/themes/manga-panel/variants/chalk-magenta.json +121 -0
- package/themes/manga-panel/variants/chalk-orange-bold.json +117 -0
- package/themes/manga-panel/variants/chalk-orange.json +122 -0
- package/themes/manga-panel/variants/chalk-rose-dots.json +121 -0
- package/themes/manga-panel/variants/chalk-rose.json +116 -0
- package/themes/manga-panel/variants/chalk-sky-bold.json +117 -0
- package/themes/manga-panel/variants/chalk-sky.json +117 -0
- package/themes/manga-panel/variants/snow-cyan.json +117 -0
- package/themes/manga-panel/variants/snow-magenta-dots.json +121 -0
- package/themes/manga-panel/variants/snow-magenta.json +116 -0
- package/themes/manga-panel/variants/snow-rose-dots.json +121 -0
- package/themes/manga-panel/variants/snow-rose.json +116 -0
- package/themes/manga-panel/variants/snow-sky.json +95 -0
- package/themes/marble-run/THEME.md +73 -0
- package/themes/marble-run/effects.ts +678 -0
- package/themes/marble-run/sample/assets/og/logo.svg +12 -0
- package/themes/marble-run/sample/beats.json +1005 -0
- package/themes/marble-run/sample/index.html +11 -0
- package/themes/marble-run/sample/kf.json +59 -0
- package/themes/marble-run/sample/lib/facts.ts +29 -0
- package/themes/marble-run/sample/lib/run.ts +30 -0
- package/themes/marble-run/sample/main.ts +9 -0
- package/themes/marble-run/sample/scenes/end.ts +58 -0
- package/themes/marble-run/sample/scenes/gather.ts +51 -0
- package/themes/marble-run/sample/scenes/models.ts +73 -0
- package/themes/marble-run/sample/scenes/price.ts +51 -0
- package/themes/marble-run/sample/style.json +109 -0
- package/themes/marble-run/slots.ts +116 -0
- package/themes/marble-run/still.png +0 -0
- package/themes/marble-run/style.json +109 -0
- package/themes/marble-run/theme.json +145 -0
- package/themes/marble-run/variants/cocoa-amber.json +128 -0
- package/themes/marble-run/variants/cocoa-orange.json +142 -0
- package/themes/marble-run/variants/dusk-orange.json +133 -0
- package/themes/marble-run/variants/forest-gold.json +128 -0
- package/themes/marble-run/variants/navy-gold.json +137 -0
- package/themes/marble-run/variants/night-gold-grain.json +105 -0
- package/themes/marble-run/variants/night-gold.json +137 -0
- package/themes/marble-run/variants/slate-gold-grain.json +133 -0
- package/themes/marble-run/variants/slate-gold.json +133 -0
- package/themes/marble-run/variants/slate-orange-grain.json +105 -0
- package/themes/marble-run/variants/slate-orange-mono.json +128 -0
- package/themes/marble-run/variants/slate-orange-serif.json +128 -0
- package/themes/marble-run/variants/slate-orange.json +131 -0
- package/themes/neon-sign/THEME.md +59 -0
- package/themes/neon-sign/effects.ts +424 -0
- package/themes/neon-sign/sample/assets/og/logo.svg +12 -0
- package/themes/neon-sign/sample/beats.json +1005 -0
- package/themes/neon-sign/sample/index.html +11 -0
- package/themes/neon-sign/sample/kf.json +59 -0
- package/themes/neon-sign/sample/lib/facts.ts +29 -0
- package/themes/neon-sign/sample/lib/neon.ts +50 -0
- package/themes/neon-sign/sample/main.ts +9 -0
- package/themes/neon-sign/sample/scenes/end.ts +62 -0
- package/themes/neon-sign/sample/scenes/gather.ts +59 -0
- package/themes/neon-sign/sample/scenes/models.ts +63 -0
- package/themes/neon-sign/sample/scenes/price.ts +74 -0
- package/themes/neon-sign/sample/style.json +104 -0
- package/themes/neon-sign/slots.ts +110 -0
- package/themes/neon-sign/still.png +0 -0
- package/themes/neon-sign/style.json +104 -0
- package/themes/neon-sign/theme.json +136 -0
- package/themes/neon-sign/variants/deep-plum.json +121 -0
- package/themes/neon-sign/variants/deep-violet.json +121 -0
- package/themes/neon-sign/variants/dusk-plum.json +121 -0
- package/themes/neon-sign/variants/forest-magenta.json +126 -0
- package/themes/neon-sign/variants/forest-plum.json +98 -0
- package/themes/neon-sign/variants/night-coral.json +122 -0
- package/themes/neon-sign/variants/night-magenta-round.json +121 -0
- package/themes/neon-sign/variants/night-magenta.json +126 -0
- package/themes/neon-sign/variants/night-pink.json +125 -0
- package/themes/neon-sign/variants/night-violet.json +126 -0
- package/themes/neon-sign/variants/slate-plum.json +120 -0
- package/themes/neon-sign/variants/slate-violet.json +127 -0
- package/themes/neon-sign/variants/wine-coral.json +127 -0
- package/themes/neon-sign/variants/wine-pink.json +125 -0
- package/themes/neon-sign/variants/wine-plum.json +126 -0
- package/themes/newspaper/THEME.md +67 -0
- package/themes/newspaper/effects.ts +347 -0
- package/themes/newspaper/sample/assets/og/logo.svg +12 -0
- package/themes/newspaper/sample/beats.json +1005 -0
- package/themes/newspaper/sample/index.html +11 -0
- package/themes/newspaper/sample/kf.json +59 -0
- package/themes/newspaper/sample/lib/facts.ts +29 -0
- package/themes/newspaper/sample/lib/page.ts +27 -0
- package/themes/newspaper/sample/main.ts +9 -0
- package/themes/newspaper/sample/scenes/end.ts +62 -0
- package/themes/newspaper/sample/scenes/gather.ts +66 -0
- package/themes/newspaper/sample/scenes/models.ts +61 -0
- package/themes/newspaper/sample/scenes/price.ts +103 -0
- package/themes/newspaper/sample/style.json +100 -0
- package/themes/newspaper/slots.ts +73 -0
- package/themes/newspaper/still.png +0 -0
- package/themes/newspaper/style.json +100 -0
- package/themes/newspaper/theme.json +140 -0
- package/themes/newspaper/variants/blush-amber.json +123 -0
- package/themes/newspaper/variants/blush-orange.json +125 -0
- package/themes/newspaper/variants/chalk-cyan.json +119 -0
- package/themes/newspaper/variants/chalk-indigo.json +124 -0
- package/themes/newspaper/variants/chalk-jade.json +95 -0
- package/themes/newspaper/variants/chalk-magenta.json +127 -0
- package/themes/newspaper/variants/frost-plum.json +123 -0
- package/themes/newspaper/variants/frost-sky.json +129 -0
- package/themes/newspaper/variants/frost-violet.json +96 -0
- package/themes/newspaper/variants/lilac-coral.json +124 -0
- package/themes/newspaper/variants/lilac-green.json +127 -0
- package/themes/newspaper/variants/sage-blue.json +124 -0
- package/themes/newspaper/variants/sage-lime.json +117 -0
- package/themes/newspaper/variants/sand-gold.json +124 -0
- package/themes/newspaper/variants/sand-jade.json +123 -0
- package/themes/og-measure/theme.json +62 -0
- package/themes/og-measure/variants/chalk-orange.json +102 -0
- package/themes/og-measure/variants/cocoa-amber.json +138 -0
- package/themes/og-measure/variants/cocoa-cyan.json +138 -0
- package/themes/og-measure/variants/cocoa-gold.json +129 -0
- package/themes/og-measure/variants/cream-lime.json +137 -0
- package/themes/og-measure/variants/deep-jade.json +100 -0
- package/themes/og-measure/variants/dusk-violet.json +133 -0
- package/themes/og-measure/variants/forest-cyan.json +123 -0
- package/themes/og-measure/variants/frost-amber.json +129 -0
- package/themes/og-measure/variants/frost-cyan.json +133 -0
- package/themes/og-measure/variants/lilac-plum.json +127 -0
- package/themes/og-measure/variants/lilac-violet.json +139 -0
- package/themes/og-measure/variants/sage-green.json +137 -0
- package/themes/og-measure/variants/wine-jade.json +127 -0
- package/themes/og-measure/variants/wine-plum.json +127 -0
- package/themes/orbit-system/THEME.md +77 -0
- package/themes/orbit-system/effects.ts +665 -0
- package/themes/orbit-system/sample/assets/og/logo.svg +12 -0
- package/themes/orbit-system/sample/beats.json +1005 -0
- package/themes/orbit-system/sample/index.html +11 -0
- package/themes/orbit-system/sample/kf.json +59 -0
- package/themes/orbit-system/sample/lib/facts.ts +29 -0
- package/themes/orbit-system/sample/lib/orbit.ts +84 -0
- package/themes/orbit-system/sample/main.ts +9 -0
- package/themes/orbit-system/sample/scenes/end.ts +50 -0
- package/themes/orbit-system/sample/scenes/gather.ts +35 -0
- package/themes/orbit-system/sample/scenes/models.ts +49 -0
- package/themes/orbit-system/sample/scenes/price.ts +57 -0
- package/themes/orbit-system/sample/style.json +108 -0
- package/themes/orbit-system/slots.ts +174 -0
- package/themes/orbit-system/still.png +0 -0
- package/themes/orbit-system/style.json +108 -0
- package/themes/orbit-system/theme.json +142 -0
- package/themes/orbit-system/variants/cocoa-amber.json +122 -0
- package/themes/orbit-system/variants/cocoa-coral.json +127 -0
- package/themes/orbit-system/variants/cocoa-cyan.json +127 -0
- package/themes/orbit-system/variants/deep-cyan.json +132 -0
- package/themes/orbit-system/variants/deep-sky.json +122 -0
- package/themes/orbit-system/variants/dusk-magenta.json +121 -0
- package/themes/orbit-system/variants/dusk-plum-pretendard.json +121 -0
- package/themes/orbit-system/variants/dusk-plum.json +127 -0
- package/themes/orbit-system/variants/dusk-violet.json +122 -0
- package/themes/orbit-system/variants/forest-coral.json +126 -0
- package/themes/orbit-system/variants/forest-plum.json +94 -0
- package/themes/orbit-system/variants/navy-amber.json +127 -0
- package/themes/orbit-system/variants/wine-amber.json +127 -0
- package/themes/orbit-system/variants/wine-coral.json +123 -0
- package/themes/orbit-system/variants/wine-magenta.json +126 -0
- package/themes/origami-fold/THEME.md +74 -0
- package/themes/origami-fold/effects.ts +535 -0
- package/themes/origami-fold/sample/assets/og/logo.svg +12 -0
- package/themes/origami-fold/sample/beats.json +1005 -0
- package/themes/origami-fold/sample/index.html +11 -0
- package/themes/origami-fold/sample/kf.json +59 -0
- package/themes/origami-fold/sample/lib/facts.ts +29 -0
- package/themes/origami-fold/sample/lib/fold.ts +53 -0
- package/themes/origami-fold/sample/main.ts +9 -0
- package/themes/origami-fold/sample/scenes/end.ts +51 -0
- package/themes/origami-fold/sample/scenes/gather.ts +37 -0
- package/themes/origami-fold/sample/scenes/models.ts +46 -0
- package/themes/origami-fold/sample/scenes/price.ts +54 -0
- package/themes/origami-fold/sample/style.json +108 -0
- package/themes/origami-fold/slots.ts +176 -0
- package/themes/origami-fold/still.png +0 -0
- package/themes/origami-fold/style.json +108 -0
- package/themes/origami-fold/theme.json +123 -0
- package/themes/origami-fold/variants/deep-amber-sunflower.json +122 -0
- package/themes/origami-fold/variants/deep-amber.json +122 -0
- package/themes/origami-fold/variants/deep-orange.json +128 -0
- package/themes/origami-fold/variants/forest-coral.json +127 -0
- package/themes/origami-fold/variants/forest-pink.json +123 -0
- package/themes/origami-fold/variants/forest-rose.json +100 -0
- package/themes/origami-fold/variants/frost-amber-grain.json +127 -0
- package/themes/origami-fold/variants/frost-amber-paper.json +128 -0
- package/themes/origami-fold/variants/frost-amber.json +95 -0
- package/themes/origami-fold/variants/sage-coral-grain.json +100 -0
- package/themes/origami-fold/variants/sage-coral-sunflower.json +122 -0
- package/themes/origami-fold/variants/sage-coral.json +128 -0
- package/themes/origami-fold/variants/sage-pink-grain.json +127 -0
- package/themes/origami-fold/variants/sage-pink-round.json +124 -0
- package/themes/origami-fold/variants/sage-pink.json +127 -0
- package/themes/paper-cutout/THEME.md +63 -0
- package/themes/paper-cutout/effects.ts +609 -0
- package/themes/paper-cutout/sample/assets/og/logo.svg +12 -0
- package/themes/paper-cutout/sample/beats.json +1005 -0
- package/themes/paper-cutout/sample/index.html +11 -0
- package/themes/paper-cutout/sample/kf.json +59 -0
- package/themes/paper-cutout/sample/lib/facts.ts +29 -0
- package/themes/paper-cutout/sample/lib/paper.ts +91 -0
- package/themes/paper-cutout/sample/main.ts +9 -0
- package/themes/paper-cutout/sample/scenes/end.ts +54 -0
- package/themes/paper-cutout/sample/scenes/gather.ts +63 -0
- package/themes/paper-cutout/sample/scenes/models.ts +93 -0
- package/themes/paper-cutout/sample/scenes/price.ts +100 -0
- package/themes/paper-cutout/sample/style.json +104 -0
- package/themes/paper-cutout/slots.ts +87 -0
- package/themes/paper-cutout/still.png +0 -0
- package/themes/paper-cutout/style.json +104 -0
- package/themes/paper-cutout/theme.json +144 -0
- package/themes/paper-cutout/variants/blush-coral.json +122 -0
- package/themes/paper-cutout/variants/blush-violet.json +122 -0
- package/themes/paper-cutout/variants/chalk-teal.json +122 -0
- package/themes/paper-cutout/variants/cream-gold.json +122 -0
- package/themes/paper-cutout/variants/frost-blue.json +123 -0
- package/themes/paper-cutout/variants/frost-lime.json +121 -0
- package/themes/paper-cutout/variants/frost-plum.json +122 -0
- package/themes/paper-cutout/variants/lilac-blue.json +123 -0
- package/themes/paper-cutout/variants/lilac-gold.json +122 -0
- package/themes/paper-cutout/variants/sage-cyan.json +122 -0
- package/themes/paper-cutout/variants/sage-green.json +122 -0
- package/themes/paper-cutout/variants/sage-pink.json +122 -0
- package/themes/paper-cutout/variants/sand-blue.json +123 -0
- package/themes/paper-cutout/variants/sand-green.json +121 -0
- package/themes/paper-cutout/variants/sand-plum.json +120 -0
- package/themes/pixel-quest/THEME.md +57 -0
- package/themes/pixel-quest/effects.ts +491 -0
- package/themes/pixel-quest/kit.ts +232 -0
- package/themes/pixel-quest/sample/assets/og/logo.svg +12 -0
- package/themes/pixel-quest/sample/beats.json +1005 -0
- package/themes/pixel-quest/sample/index.html +11 -0
- package/themes/pixel-quest/sample/kf.json +59 -0
- package/themes/pixel-quest/sample/lib/facts.ts +29 -0
- package/themes/pixel-quest/sample/lib/game.ts +71 -0
- package/themes/pixel-quest/sample/lib/logo.ts +51 -0
- package/themes/pixel-quest/sample/main.ts +9 -0
- package/themes/pixel-quest/sample/scenes/end.ts +75 -0
- package/themes/pixel-quest/sample/scenes/gather.ts +65 -0
- package/themes/pixel-quest/sample/scenes/models.ts +104 -0
- package/themes/pixel-quest/sample/scenes/price.ts +118 -0
- package/themes/pixel-quest/sample/style.json +115 -0
- package/themes/pixel-quest/slots.ts +94 -0
- package/themes/pixel-quest/still.png +0 -0
- package/themes/pixel-quest/style.json +115 -0
- package/themes/pixel-quest/theme.json +143 -0
- package/themes/pixel-quest/variants/navy-gold-2.json +98 -0
- package/themes/pixel-quest/variants/navy-gold-3.json +127 -0
- package/themes/pixel-quest/variants/navy-gold-4.json +95 -0
- package/themes/pixel-quest/variants/navy-gold-pixel.json +132 -0
- package/themes/pixel-quest/variants/navy-gold-scan.json +99 -0
- package/themes/pixel-quest/variants/navy-gold.json +131 -0
- package/themes/pixel-quest/variants/navy-lime-2.json +93 -0
- package/themes/pixel-quest/variants/navy-lime-3.json +124 -0
- package/themes/pixel-quest/variants/navy-lime-pixel.json +126 -0
- package/themes/pixel-quest/variants/navy-lime-scan.json +97 -0
- package/themes/pixel-quest/variants/navy-lime.json +130 -0
- package/themes/receipt/THEME.md +72 -0
- package/themes/receipt/effects.ts +257 -0
- package/themes/receipt/sample/assets/og/logo.svg +12 -0
- package/themes/receipt/sample/beats.json +1005 -0
- package/themes/receipt/sample/index.html +11 -0
- package/themes/receipt/sample/kf.json +59 -0
- package/themes/receipt/sample/lib/facts.ts +29 -0
- package/themes/receipt/sample/lib/sheet.ts +52 -0
- package/themes/receipt/sample/main.ts +9 -0
- package/themes/receipt/sample/scenes/end.ts +44 -0
- package/themes/receipt/sample/scenes/gather.ts +57 -0
- package/themes/receipt/sample/scenes/models.ts +48 -0
- package/themes/receipt/sample/scenes/price.ts +64 -0
- package/themes/receipt/sample/style.json +104 -0
- package/themes/receipt/slots.ts +89 -0
- package/themes/receipt/still.png +0 -0
- package/themes/receipt/style.json +104 -0
- package/themes/receipt/theme.json +133 -0
- package/themes/receipt/variants/blush-coral.json +89 -0
- package/themes/receipt/variants/sand-coral-2.json +89 -0
- package/themes/receipt/variants/sand-coral-3.json +89 -0
- package/themes/receipt/variants/sand-coral-4.json +90 -0
- package/themes/receipt/variants/sand-coral-5.json +89 -0
- package/themes/receipt/variants/sand-coral-6.json +88 -0
- package/themes/receipt/variants/sand-coral-7.json +88 -0
- package/themes/receipt/variants/sand-coral-8.json +89 -0
- package/themes/receipt/variants/sand-coral-9.json +89 -0
- package/themes/receipt/variants/sand-coral.json +88 -0
- package/themes/receipt/variants/sand-orange-2.json +89 -0
- package/themes/receipt/variants/sand-orange-3.json +90 -0
- package/themes/receipt/variants/sand-orange-4.json +89 -0
- package/themes/receipt/variants/sand-orange-5.json +89 -0
- package/themes/receipt/variants/sand-orange.json +89 -0
- package/themes/riso-zine/theme.json +66 -0
- package/themes/riso-zine/variants/blush-coral.json +120 -0
- package/themes/riso-zine/variants/blush-gold.json +120 -0
- package/themes/riso-zine/variants/blush-pink.json +115 -0
- package/themes/riso-zine/variants/chalk-cyan.json +120 -0
- package/themes/riso-zine/variants/chalk-lime.json +119 -0
- package/themes/riso-zine/variants/cream-amber.json +89 -0
- package/themes/riso-zine/variants/frost-blue.json +119 -0
- package/themes/riso-zine/variants/frost-coral.json +118 -0
- package/themes/riso-zine/variants/frost-cyan.json +120 -0
- package/themes/riso-zine/variants/frost-green.json +120 -0
- package/themes/riso-zine/variants/lilac-plum.json +118 -0
- package/themes/riso-zine/variants/lilac-violet.json +123 -0
- package/themes/riso-zine/variants/sage-green.json +119 -0
- package/themes/riso-zine/variants/sand-jade.json +120 -0
- package/themes/riso-zine/variants/sand-plum.json +113 -0
- package/themes/server-hall/THEME.md +58 -0
- package/themes/server-hall/effects.ts +455 -0
- package/themes/server-hall/kit.ts +138 -0
- package/themes/server-hall/sample/assets/og/logo.svg +12 -0
- package/themes/server-hall/sample/beats.json +1005 -0
- package/themes/server-hall/sample/index.html +11 -0
- package/themes/server-hall/sample/kf.json +59 -0
- package/themes/server-hall/sample/lib/facts.ts +29 -0
- package/themes/server-hall/sample/lib/hall.ts +81 -0
- package/themes/server-hall/sample/main.ts +9 -0
- package/themes/server-hall/sample/scenes/end.ts +57 -0
- package/themes/server-hall/sample/scenes/gather.ts +38 -0
- package/themes/server-hall/sample/scenes/models.ts +49 -0
- package/themes/server-hall/sample/scenes/price.ts +65 -0
- package/themes/server-hall/sample/style.json +107 -0
- package/themes/server-hall/slots.ts +106 -0
- package/themes/server-hall/still.png +0 -0
- package/themes/server-hall/style.json +107 -0
- package/themes/server-hall/theme.json +143 -0
- package/themes/server-hall/variants/navy-indigo.json +140 -0
- package/themes/server-hall/variants/night-indigo.json +120 -0
- package/themes/server-hall/variants/wine-plum.json +130 -0
- package/themes/server-hall/variants/wine-violet.json +103 -0
- package/themes/subway-map/THEME.md +64 -0
- package/themes/subway-map/effects.ts +662 -0
- package/themes/subway-map/sample/assets/og/logo.svg +12 -0
- package/themes/subway-map/sample/beats.json +1005 -0
- package/themes/subway-map/sample/index.html +11 -0
- package/themes/subway-map/sample/kf.json +59 -0
- package/themes/subway-map/sample/lib/facts.ts +29 -0
- package/themes/subway-map/sample/lib/map.ts +58 -0
- package/themes/subway-map/sample/main.ts +9 -0
- package/themes/subway-map/sample/scenes/end.ts +94 -0
- package/themes/subway-map/sample/scenes/gather.ts +64 -0
- package/themes/subway-map/sample/scenes/models.ts +117 -0
- package/themes/subway-map/sample/scenes/price.ts +119 -0
- package/themes/subway-map/sample/style.json +108 -0
- package/themes/subway-map/slots.ts +66 -0
- package/themes/subway-map/still.png +0 -0
- package/themes/subway-map/style.json +108 -0
- package/themes/subway-map/theme.json +161 -0
- package/themes/subway-map/variants/blush-jade.json +131 -0
- package/themes/subway-map/variants/chalk-jade.json +141 -0
- package/themes/subway-map/variants/deep-green.json +131 -0
- package/themes/subway-map/variants/deep-teal.json +132 -0
- package/themes/subway-map/variants/dusk-teal-bold.json +132 -0
- package/themes/subway-map/variants/dusk-teal.json +105 -0
- package/themes/subway-map/variants/forest-green.json +141 -0
- package/themes/subway-map/variants/forest-jade.json +131 -0
- package/themes/subway-map/variants/frost-jade.json +131 -0
- package/themes/subway-map/variants/frost-teal.json +137 -0
- package/themes/subway-map/variants/sage-teal.json +132 -0
- package/themes/subway-map/variants/slate-green.json +136 -0
- package/themes/subway-map/variants/slate-jade.json +131 -0
- package/themes/subway-map/variants/snow-jade.json +136 -0
- package/themes/subway-map/variants/wine-green.json +104 -0
- package/themes/swiss-poster/THEME.md +59 -0
- package/themes/swiss-poster/effects.ts +339 -0
- package/themes/swiss-poster/grid.ts +35 -0
- package/themes/swiss-poster/sample/assets/og/logo.svg +12 -0
- package/themes/swiss-poster/sample/beats.json +1005 -0
- package/themes/swiss-poster/sample/index.html +11 -0
- package/themes/swiss-poster/sample/kf.json +59 -0
- package/themes/swiss-poster/sample/lib/facts.ts +29 -0
- package/themes/swiss-poster/sample/lib/poster.ts +36 -0
- package/themes/swiss-poster/sample/main.ts +9 -0
- package/themes/swiss-poster/sample/scenes/end.ts +70 -0
- package/themes/swiss-poster/sample/scenes/gather.ts +68 -0
- package/themes/swiss-poster/sample/scenes/models.ts +63 -0
- package/themes/swiss-poster/sample/scenes/price.ts +74 -0
- package/themes/swiss-poster/sample/style.json +100 -0
- package/themes/swiss-poster/slots.ts +69 -0
- package/themes/swiss-poster/still.png +0 -0
- package/themes/swiss-poster/style.json +100 -0
- package/themes/swiss-poster/theme.json +131 -0
- package/themes/swiss-poster/variants/blush-green.json +116 -0
- package/themes/swiss-poster/variants/chalk-plum.json +121 -0
- package/themes/swiss-poster/variants/chalk-sky.json +90 -0
- package/themes/swiss-poster/variants/cocoa-cyan.json +117 -0
- package/themes/swiss-poster/variants/dusk-coral.json +89 -0
- package/themes/swiss-poster/variants/dusk-magenta.json +117 -0
- package/themes/swiss-poster/variants/forest-amber.json +127 -0
- package/themes/swiss-poster/variants/forest-blue.json +118 -0
- package/themes/swiss-poster/variants/forest-jade.json +89 -0
- package/themes/swiss-poster/variants/frost-gold.json +128 -0
- package/themes/swiss-poster/variants/frost-indigo.json +117 -0
- package/themes/swiss-poster/variants/sand-magenta.json +126 -0
- package/themes/swiss-poster/variants/slate-orange.json +122 -0
- package/themes/swiss-poster/variants/slate-pink.json +126 -0
- package/themes/swiss-poster/variants/slate-violet.json +89 -0
- package/themes/water-works/THEME.md +61 -0
- package/themes/water-works/effects.ts +609 -0
- package/themes/water-works/sample/assets/og/logo.svg +12 -0
- package/themes/water-works/sample/beats.json +1005 -0
- package/themes/water-works/sample/index.html +11 -0
- package/themes/water-works/sample/kf.json +59 -0
- package/themes/water-works/sample/lib/facts.ts +29 -0
- package/themes/water-works/sample/lib/hall.ts +22 -0
- package/themes/water-works/sample/main.ts +9 -0
- package/themes/water-works/sample/scenes/end.ts +55 -0
- package/themes/water-works/sample/scenes/gather.ts +42 -0
- package/themes/water-works/sample/scenes/models.ts +51 -0
- package/themes/water-works/sample/scenes/price.ts +66 -0
- package/themes/water-works/sample/style.json +105 -0
- package/themes/water-works/slots.ts +140 -0
- package/themes/water-works/still.png +0 -0
- package/themes/water-works/style.json +105 -0
- package/themes/water-works/theme.json +138 -0
- package/themes/water-works/variants/blush-rose.json +123 -0
- package/themes/water-works/variants/chalk-blue.json +124 -0
- package/themes/water-works/variants/chalk-cyan-2.json +96 -0
- package/themes/water-works/variants/chalk-cyan.json +123 -0
- package/themes/water-works/variants/chalk-gold-mono.json +122 -0
- package/themes/water-works/variants/chalk-gold.json +123 -0
- package/themes/water-works/variants/chalk-green.json +123 -0
- package/themes/water-works/variants/frost-indigo.json +123 -0
- package/themes/water-works/variants/frost-rose.json +132 -0
- package/themes/water-works/variants/lilac-violet-mono.json +124 -0
- package/themes/water-works/variants/lilac-violet.json +133 -0
- package/themes/water-works/variants/sage-amber.json +133 -0
- package/themes/water-works/variants/sage-green.json +133 -0
- package/themes/water-works/variants/sand-amber.json +123 -0
- package/themes/water-works/variants/sand-plum.json +121 -0
- package/themes/whiteboard/THEME.md +78 -0
- package/themes/whiteboard/effects.ts +561 -0
- package/themes/whiteboard/sample/assets/og/logo.svg +12 -0
- package/themes/whiteboard/sample/beats.json +1005 -0
- package/themes/whiteboard/sample/index.html +11 -0
- package/themes/whiteboard/sample/kf.json +59 -0
- package/themes/whiteboard/sample/lib/board.ts +93 -0
- package/themes/whiteboard/sample/lib/facts.ts +29 -0
- package/themes/whiteboard/sample/main.ts +9 -0
- package/themes/whiteboard/sample/scenes/end.ts +59 -0
- package/themes/whiteboard/sample/scenes/gather.ts +50 -0
- package/themes/whiteboard/sample/scenes/models.ts +56 -0
- package/themes/whiteboard/sample/scenes/price.ts +79 -0
- package/themes/whiteboard/sample/style.json +106 -0
- package/themes/whiteboard/slots.ts +152 -0
- package/themes/whiteboard/still.png +0 -0
- package/themes/whiteboard/style.json +106 -0
- package/themes/whiteboard/theme.json +143 -0
- package/themes/whiteboard/variants/chalk-coral-do.json +126 -0
- package/themes/whiteboard/variants/chalk-coral.json +132 -0
- package/themes/whiteboard/variants/cream-lime.json +131 -0
- package/themes/whiteboard/variants/cream-plum.json +103 -0
- package/themes/whiteboard/variants/frost-teal-do.json +127 -0
- package/themes/whiteboard/variants/frost-teal.json +127 -0
- package/themes/whiteboard/variants/lilac-indigo.json +132 -0
- package/themes/whiteboard/variants/lilac-jade.json +103 -0
- package/themes/whiteboard/variants/sage-green.json +130 -0
- package/themes/whiteboard/variants/sage-plum.json +126 -0
- package/themes/whiteboard/variants/snow-amber.json +99 -0
- package/themes/whiteboard/variants/snow-cyan.json +132 -0
- package/themes/whiteboard/variants/snow-green.json +126 -0
- package/themes/whiteboard/variants/snow-magenta.json +126 -0
- package/themes/whiteboard/variants/snow-plum.json +130 -0
package/README.md
CHANGED
|
@@ -81,7 +81,7 @@ kf skill install # ~/.claude/skills/kasaframe 에 스킬 링
|
|
|
81
81
|
| `kf narrate` | 내레이션 먼저 — 장면별 문장을 TTS 로 읽혀 장면 길이를 목소리에 맞추고(곡이 있으면 박에), 자막을 목소리 시각으로 |
|
|
82
82
|
| `kf music` | 곡 모음(분위기 태그) 보기·넣기, 음악 생성(Lyria · Eleven Music) |
|
|
83
83
|
| `kf transitions` | 전환 목록 — 이름·출처·라이선스 |
|
|
84
|
-
| `kf theme list` · `kf theme sheet` | 테마 — `riso-zine` · `debug-hud` · `og-measure
|
|
84
|
+
| `kf theme list [--variants]` · `kf theme sheet [--variants <세계\|all>]` · `kf theme vary <세계\|all>` · `kf theme suggest [--json]` | 테마 — 세계(`riso-zine` · `debug-hud` · `og-measure` …)와 겉모습만 바꾼 변주(`og-measure/night-amber`), 같은 문장 한 장면을 테마마다 찍은 견본 격자, 변주 뽑기, 요청에 맞는 후보(kf make 의 테마 질문과 같은 고르기) |
|
|
85
85
|
| `kf app` | 작업실 — 요청 칸·실시간 미리보기·렌더·검사 보고를 브라우저로(:5150) |
|
|
86
86
|
| `kf doctor` · `kf setup` | 바깥 도구 점검 · 깔기 |
|
|
87
87
|
| `kf skill` | Claude Code 스킬 링크 |
|
package/docs/AGENTS.md
CHANGED
|
@@ -13,7 +13,7 @@ kf make "카사텀 홍보 영상 1분, 카와이 퓨처베이스" [--music 곡.m
|
|
|
13
13
|
- **그림 보기는 세션이 직접**: `kf look <폴더|mp4>` 가 장면 모음(`out/look-sheet.png`)과 장면별 확인표(`out/look.md` — 빈 화면·글 깨짐·대비·잘림·주인공 자리·할 일·테마)를 만들고 경로만 찍는다. 외부 모델을 부르지 않는다. **눈 없는 모델**(Claude Code 를 OG 로 딥시크 같은 모델에 붙였을 때 — OG `/v1/messages` 는 그림을 버려서 Read 해도 안 보인다)만 `kf look <폴더|mp4> --vision-model google/gemini-3.5-flash [--ask "<볼 것>"]` 로 그림 보는 모델이 장면마다 글로 보고한다(한 번 1센트 안팎, 묻지 않고 써도 된다). `kf make --finish` 도 기본은 그림 보는 모델 없이 끝에 장면 모음·확인표 경로를 찍는다.
|
|
14
14
|
- **곡**: 홍보·공개·뮤비는 곡이 끌고 간다. `--music` 을 안 주면 곡 모음(`KF_MUSIC_DIR`, 없으면 레포 `music/` — 곡마다 원본·라이선스·분위기 태그는 `music/tags.json`·`README.md`. npm 패키지에는 곡이 없다)에서 요청 낱말과 맞는 곡을 고른다. 곡 모음이 비었으면 `--music` 으로 준다.
|
|
15
15
|
- **목소리·곡(쇼츠·설명)**: 차분한 TTS 내레이션 + 깊은 앰비언트 곡(`deep`)이 기본이다. 곡은 분위기 태그가 맞는 곡 모음 곡을 묻지 않고 고르고(같은 틀이면 늘 같은 곡), 없으면 생성(Lyria·Eleven Music, 돈)·곡 넣기·없음을 묻는다. 목소리는 늘 맨 위 질문으로 묻는다 — 보기 차례 로컬 Qwen3(`KF_QWEN3_TTS_URL` 이 있을 때)·ElevenLabs(키가 없으면 넣는 법)·자막만·그 밖 엔진(`kf narrate --voices`). 로컬도 ElevenLabs 도 없거나 생성 키가 없으면 다른 엔진·「자막만」·「곡 없이」로 넘어가지 말고 맨 위 질문대로 사람에게 묻는다(키 넣기가 권장). 묻지 않으려면 `--voice <엔진>:<목소리>|none`·`--music <곡>|gen:lyria-3.5|none`. 그다음은 아래 「내레이션 먼저」.
|
|
16
|
-
- **용도·테마**: 용도는 확신이 낮을 때만 묻는다. 테마는 요청이 「리소 느낌으로」처럼 짚었거나 시리즈가 정했으면 그대로, 아니면 맨 위 질문으로 묻는다 —
|
|
16
|
+
- **용도·테마**: 용도는 확신이 낮을 때만 묻는다. 테마는 요청이 「리소 느낌으로」처럼 짚었거나 시리즈가 정했으면 그대로, 아니면 맨 위 질문으로 묻는다 — 테마는 「세계 × 변주」(세계 = 비유와 효과 코드, 변주 = 겉모습만 바꾼 판 `<세계>/<변주>`, 예 `og-measure/night-amber`)라 수백 판이고, 보기는 「알아서」(= `auto`, 첫 후보)와 요청·용도·분위기 낱말에 맞는 넷뿐이다. 질문 글에 넷만 담은 견본 시트 경로가 붙는다 — 그 그림을 사람에게 보인다. 사람이 보기 밖으로 분위기 한 마디나 그림·주소를 주면 `kf make --answer <폴더> --theme-mood "<말>"`·`--theme-ref <경로|URL>` 로 넣는다(후보 넷·시트·MAKE.md 를 다시 고쳐 쓰고 종료 3 — 다시 묻는다). 답이 오기 전 뼈대는 첫 후보로 깔려 있다. 못 박으려면 `--purpose <용도>`·`--theme <id>`, 테마 없이 프리셋만이면 `--theme none`. **시리즈**(`kf series list` — 예 「OG 쇼츠」)를 짚으면 용도·테마보다 먼저 그 묶음(용도·테마·목소리·곡·자막·길이·끝 카드·생성 답)으로 묻지 않고 간다 — 같은 시리즈면 매번 같다. 잘 나온 프로젝트를 묶음으로: `kf series new <id> --from <폴더> --match "…"`. 같은 말이 같은 결과를 내는지는 `kf bench "<요청>" --runs 3`. 묻는 것은 용도 확신이 낮을 때뿐(종료 코드 3).
|
|
17
17
|
- **작업실**: `kf app` 이 떠 있으면 `kf make` 가 거기에 등록하고 주소를 찍는다 — 사람은 페이지에서 실시간 미리보기·지난 작업을 본다.
|
|
18
18
|
- **Claude Code 스킬**: `kf skill install` 하면 「영상 만들어」 같은 말에 kasaframe 으로 오는 스킬이 깔린다(`skills/kasaframe/SKILL.md`).
|
|
19
19
|
- **생성 능력**(`kf doctor` 「생성 능력」): 계획은 그림 컷·주인공 3D 장면(Blender 툰 샷, 없으면 three.js)·이음매 3D 전환(three)·캐릭터가 실제로 움직이는 컷(영상 모델 — 요청에 캐릭터와 몸짓이 있거나 뮤비일 때)·곡·내레이션을 기본으로 넣는다. **묻는 것은 돈이 들거나 없는 능력뿐**이고 나머지는 틀·테마가 정한 기본값으로 간다 — 같은 말이면 같은 결과. **없는 능력은 조용히 대체하지 않는다** — 「키·도구 넣는 법(권장) · 지금 되는 다른 엔진 · 빼기(자막만·곡 없이)」를 사람에게 묻고 고른 값을 플래그로 넣는다. 네가 대신 길을 고르지 않는다(`--yes` 로도 안 넘어간다). 키는 `kf setup key <이름>` 이 숨겨 받는다. 묻지 않고 가려면 `--yes`(권장 답 — 돈도 쓴다) · `--no-gen`(돈 안 드는 길) · `--allow image,video,…`(목록 능력만 권장, 나머지는 돈 안 드는 길) · `--image`·`--video`·`--blender`·`--voice`·`--music <값>`(그 질문에 미리 답). OG 모드는 뼈대 전에 터미널에서 묻고, 터미널이 아니면 보기를 찍고 종료 코드 3.
|
package/package.json
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type SceneCtx,
|
|
11
11
|
} from "@kasaframe/core";
|
|
12
12
|
import { definePage, type KfMarker, type KfMode, type KfPage } from "./page.ts";
|
|
13
|
+
import { textureLayer } from "./texture.ts";
|
|
13
14
|
|
|
14
15
|
export interface KfSceneEntry {
|
|
15
16
|
id: string;
|
|
@@ -180,6 +181,9 @@ export function mountProject(o: MountOptions): KfPage {
|
|
|
180
181
|
}
|
|
181
182
|
live.push({ entry, root, draw });
|
|
182
183
|
}
|
|
184
|
+
// 변주 질감은 장면들 위·자막 아래 한 겹 — 장면 파일은 그대로다
|
|
185
|
+
const tex = style ? textureLayer(document, style.look?.texture, style.scheme, Math.min(kf.width, kf.height) / 1080) : null;
|
|
186
|
+
if (tex) stage.appendChild(tex);
|
|
183
187
|
// 자막 판은 장면들 위 한 겹 — 장면 파일은 그대로다
|
|
184
188
|
captions = (await caps?.mount(stage, style)) ?? null;
|
|
185
189
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { rand, type StyleLook } from "@kasaframe/core";
|
|
2
|
+
|
|
3
|
+
// 변주 질감 — 세계 코드를 안 고치고 겉모습만 바꾸는 길이라 엔진이 장면 위·자막 아래 한 겹으로 깐다.
|
|
4
|
+
// 서 있는 그림 한 장(정지 화면 검사·섬광 검사에 안 걸린다), 무늬는 씨앗 고정이라 어느 탭에서 찍어도 같다.
|
|
5
|
+
|
|
6
|
+
type Texture = NonNullable<StyleLook["texture"]>;
|
|
7
|
+
|
|
8
|
+
function tile(doc: Document, w: number, h: number, paint: (img: ImageData) => void): string {
|
|
9
|
+
const c = doc.createElement("canvas");
|
|
10
|
+
c.width = w;
|
|
11
|
+
c.height = h;
|
|
12
|
+
const g = c.getContext("2d")!;
|
|
13
|
+
const img = g.createImageData(w, h);
|
|
14
|
+
paint(img);
|
|
15
|
+
g.putImageData(img, 0, 0);
|
|
16
|
+
return c.toDataURL("image/png");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** 점 하나 — 어두운 바탕엔 흰 티, 밝은 바탕엔 검은 티 */
|
|
20
|
+
function dot(img: ImageData, i: number, ink: number, alpha: number) {
|
|
21
|
+
const o = i * 4;
|
|
22
|
+
img.data[o] = img.data[o + 1] = img.data[o + 2] = ink;
|
|
23
|
+
img.data[o + 3] = Math.max(0, Math.min(255, Math.round(alpha * 255)));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 이어 붙여도 이음매가 없는 값 잡음 — 격자를 둘레로 감는다
|
|
27
|
+
function wrapNoise(seed: string, x: number, y: number, cells: number, size: number): number {
|
|
28
|
+
const fx = (x / size) * cells;
|
|
29
|
+
const fy = (y / size) * cells;
|
|
30
|
+
const x0 = Math.floor(fx);
|
|
31
|
+
const y0 = Math.floor(fy);
|
|
32
|
+
const v = (i: number, j: number) => rand(seed, ((i % cells) + cells) % cells + (((j % cells) + cells) % cells) * cells);
|
|
33
|
+
const sx = fx - x0;
|
|
34
|
+
const sy = fy - y0;
|
|
35
|
+
const ux = sx * sx * (3 - 2 * sx);
|
|
36
|
+
const uy = sy * sy * (3 - 2 * sy);
|
|
37
|
+
const a = v(x0, y0) + (v(x0 + 1, y0) - v(x0, y0)) * ux;
|
|
38
|
+
const b = v(x0, y0 + 1) + (v(x0 + 1, y0 + 1) - v(x0, y0 + 1)) * ux;
|
|
39
|
+
return a + (b - a) * uy;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function textureLayer(doc: Document, tex: Texture | undefined, scheme: "light" | "dark", scale: number): HTMLDivElement | null {
|
|
43
|
+
if (!tex || tex.kind === "none" || !(tex.amount > 0)) return null;
|
|
44
|
+
const el = doc.createElement("div");
|
|
45
|
+
el.dataset.kfTexture = tex.kind;
|
|
46
|
+
el.style.cssText = `position:absolute;inset:0;pointer-events:none;z-index:49;opacity:${Math.min(1, tex.amount)}`;
|
|
47
|
+
const ink = scheme === "dark" ? 255 : 0;
|
|
48
|
+
const rgb = scheme === "dark" ? "255,255,255" : "0,0,0";
|
|
49
|
+
const s = Math.max(1, scale);
|
|
50
|
+
if (tex.kind === "scan") {
|
|
51
|
+
el.style.backgroundImage = `repeating-linear-gradient(0deg, rgba(${rgb},0.5) 0 ${s}px, transparent ${s}px ${4 * s}px)`;
|
|
52
|
+
} else if (tex.kind === "halftone") {
|
|
53
|
+
el.style.backgroundImage = `radial-gradient(rgba(${rgb},0.55) ${1.2 * s}px, transparent ${1.7 * s}px)`;
|
|
54
|
+
el.style.backgroundSize = `${7 * s}px ${7 * s}px`;
|
|
55
|
+
} else if (tex.kind === "grain") {
|
|
56
|
+
const n = 160;
|
|
57
|
+
el.style.backgroundImage = `url(${tile(doc, n, n, (img) => {
|
|
58
|
+
for (let i = 0; i < n * n; i++) {
|
|
59
|
+
const v = rand("kf-grain", i) - 0.5;
|
|
60
|
+
dot(img, i, v < 0 ? 255 - ink : ink, Math.abs(v) * 0.5);
|
|
61
|
+
}
|
|
62
|
+
})})`;
|
|
63
|
+
el.style.backgroundSize = `${n * s}px ${n * s}px`;
|
|
64
|
+
} else if (tex.kind === "noise") {
|
|
65
|
+
const n = 96;
|
|
66
|
+
el.style.backgroundImage = `url(${tile(doc, n, n, (img) => {
|
|
67
|
+
for (let i = 0; i < n * n; i++) dot(img, i, ink, rand("kf-noise", i) ** 2 * 0.6);
|
|
68
|
+
})})`;
|
|
69
|
+
el.style.backgroundSize = `${n * 3 * s}px ${n * 3 * s}px`;
|
|
70
|
+
el.style.imageRendering = "pixelated";
|
|
71
|
+
} else if (tex.kind === "paper") {
|
|
72
|
+
// 종이 — 큰 얼룩 두 겹에 짧은 섬유
|
|
73
|
+
const n = 256;
|
|
74
|
+
el.style.backgroundImage = `url(${tile(doc, n, n, (img) => {
|
|
75
|
+
for (let y = 0; y < n; y++)
|
|
76
|
+
for (let x = 0; x < n; x++) {
|
|
77
|
+
const v = 0.6 * wrapNoise("kf-paper-a", x, y, 6, n) + 0.4 * wrapNoise("kf-paper-b", x, y, 24, n) + 0.25 * (rand("kf-paper-c", x + y * n) - 0.5);
|
|
78
|
+
dot(img, x + y * n, ink, Math.max(0, v - 0.35) * 0.32);
|
|
79
|
+
}
|
|
80
|
+
for (let f = 0; f < 140; f++) {
|
|
81
|
+
let x = rand("kf-fiber", f * 4) * n;
|
|
82
|
+
let y = rand("kf-fiber", f * 4 + 1) * n;
|
|
83
|
+
const a = rand("kf-fiber", f * 4 + 2) * Math.PI * 2;
|
|
84
|
+
const len = 6 + rand("kf-fiber", f * 4 + 3) * 18;
|
|
85
|
+
for (let k = 0; k < len; k++, x += Math.cos(a), y += Math.sin(a)) {
|
|
86
|
+
const i = (((Math.round(x) % n) + n) % n) + (((Math.round(y) % n) + n) % n) * n;
|
|
87
|
+
dot(img, i, ink, Math.max(img.data[i * 4 + 3] / 255, 0.16));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
})})`;
|
|
91
|
+
el.style.backgroundSize = `${n * 2 * s}px ${n * 2 * s}px`;
|
|
92
|
+
}
|
|
93
|
+
return el;
|
|
94
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
// 테마 견본 칸 — 같은 문장 한 장면(쇼츠 첫 장면 hook-number)을 테마·변주마다 찍은 한 장. kf theme sheet·vary 와 kf make 테마 질문이 같이 쓴다.
|
|
2
|
+
// 변주는 세계 기본 판 표준 장면을 한 번 지어 두고 style.json 만 갈아 찍는다 — 감독이 고른 장면 문법이 같아야 겉모습만 견줄 수 있다.
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { dirname, join } from "node:path";
|
|
7
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
8
|
+
import type { KfStyle } from "@kasaframe/core";
|
|
9
|
+
import { cellPath, loadTheme, themeDims, themesDir, type Theme } from "@kasaframe/themes";
|
|
10
|
+
import { launch } from "./browser.ts";
|
|
11
|
+
|
|
12
|
+
const kfBin = new URL("./kf.ts", import.meta.url).pathname;
|
|
13
|
+
const kf = (...a: string[]) => spawnSync(process.execPath, [kfBin, ...a], { encoding: "utf8" });
|
|
14
|
+
const tail = (r: { stdout?: string; stderr?: string }, n = 3) => `${r.stderr ?? ""}${r.stdout ?? ""}`.trim().split("\n").slice(-n).join(" / ");
|
|
15
|
+
|
|
16
|
+
export const SAMPLE = {
|
|
17
|
+
title: "kasaframe",
|
|
18
|
+
request: "테마 견본 — 같은 문장을 테마마다",
|
|
19
|
+
scenes: [{ id: "hook", type: "hook-number", value: 57, unit: "×", label: "KV 캐시가 이만큼 작아진다", source: "DeepSeek-V2 기술 보고서", dur: 4 }],
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export interface Frame {
|
|
23
|
+
width: number;
|
|
24
|
+
height: number;
|
|
25
|
+
safe: { top: number; bottom: number; left: number; right: number };
|
|
26
|
+
/** 장면 끝 프레임 — 움직임이 다 앉은 자리 */
|
|
27
|
+
at: number;
|
|
28
|
+
dur: number;
|
|
29
|
+
pattern?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const readJson = (p: string) => JSON.parse(readFileSync(p, "utf8"));
|
|
33
|
+
|
|
34
|
+
function frameOf(dir: string): Frame {
|
|
35
|
+
const p = readJson(join(dir, "kf.json"));
|
|
36
|
+
const scene = p.scenes.find((x: { id: string }) => x.id === SAMPLE.scenes[0].id);
|
|
37
|
+
const d = existsSync(join(dir, "director.json")) ? readJson(join(dir, "director.json")) : null;
|
|
38
|
+
return { width: p.width, height: p.height, safe: p.safeArea, at: +(scene.from + scene.dur - 1 / p.fps).toFixed(4), dur: scene.dur, pattern: d?.scenes?.find((s: { id: string }) => s.id === scene.id)?.pattern };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** 표준 장면 프로젝트 — 감독이 짓고, check 면 검사 고리까지(떨어진 패턴은 감독이 다음 후보로). 1 = 다시 지어도 검사 오류가 남음 */
|
|
42
|
+
export function standardProject(theme: string, dir: string, o: { check: boolean }): { status: number; why: string; frame: Frame | null } {
|
|
43
|
+
rmSync(dir, { recursive: true, force: true });
|
|
44
|
+
let r = kf("new", dir, "--template", "shorts", "--theme", theme, "--title", SAMPLE.title, "--series", "none");
|
|
45
|
+
if (r.status === 0) {
|
|
46
|
+
writeFileSync(join(dir, "content.json"), `${JSON.stringify(SAMPLE, null, 2)}\n`);
|
|
47
|
+
r = kf("direct", dir, "--no-narrate", "--no-lock", ...(o.check ? [] : ["--no-check"]));
|
|
48
|
+
}
|
|
49
|
+
const built = r.status === 0 || r.status === 1;
|
|
50
|
+
return { status: r.status ?? 1, why: r.status === 0 ? "" : tail(r), frame: built && existsSync(join(dir, "director.json")) ? frameOf(dir) : null };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** 지어 둔 표준 장면에 테마(변주) style 만 갈아 끼운 복사본 — 장면 파일·패턴은 그대로 */
|
|
54
|
+
export function restyle(from: string, dir: string, id: string, style: KfStyle = loadTheme(id).style): void {
|
|
55
|
+
rmSync(dir, { recursive: true, force: true });
|
|
56
|
+
cpSync(from, dir, { recursive: true, filter: (src) => !src.startsWith(join(from, "out")) });
|
|
57
|
+
const was = readJson(join(from, "style.json"));
|
|
58
|
+
style = structuredClone(style);
|
|
59
|
+
// 틀의 움직임 규칙은 kf new 가 덮은 그대로 — 변주가 바꾸는 건 빠르기(durations)뿐
|
|
60
|
+
style.motion = { ...was.motion, ...(style.motion.durations ? { durations: style.motion.durations } : {}) };
|
|
61
|
+
writeFileSync(join(dir, "style.json"), `${JSON.stringify(style, null, 2)}\n`);
|
|
62
|
+
const p = readJson(join(dir, "kf.json"));
|
|
63
|
+
writeFileSync(join(dir, "kf.json"), `${JSON.stringify({ ...p, theme: id }, null, 2)}\n`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface Verdict {
|
|
67
|
+
ok: boolean;
|
|
68
|
+
/** 오류 규칙·한 줄 */
|
|
69
|
+
errors: string[];
|
|
70
|
+
ran: boolean;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** kf check — 잠금은 부르는 쪽이 쥔다. from·to 를 주면 그 구간만(입체 세계는 무거워 끝 구간만) */
|
|
74
|
+
export function checkProject(dir: string, win?: { from: number; to: number }): Verdict {
|
|
75
|
+
const file = join(dir, "out", "check.json");
|
|
76
|
+
rmSync(file, { force: true });
|
|
77
|
+
const r = kf("check", dir, "--no-lock", "--tabs", "2", ...(win ? ["--from", String(win.from), "--to", String(win.to)] : []));
|
|
78
|
+
if (!existsSync(file)) return { ok: false, ran: false, errors: [`kf check 를 못 돌렸다(종료 ${r.status}) — ${tail(r)}`] };
|
|
79
|
+
const rep = readJson(file);
|
|
80
|
+
const errors = (rep.findings ?? []).filter((f: { severity: string }) => f.severity === "error").map((f: { rule: string; message: string }) => `${f.rule}: ${f.message}`);
|
|
81
|
+
return { ok: r.status === 0 && !errors.length, ran: true, errors };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function still(dir: string, at: number, out: string): string | null {
|
|
85
|
+
mkdirSync(dirname(out), { recursive: true });
|
|
86
|
+
const r = kf("still", dir, "--t", String(at), "--out", out);
|
|
87
|
+
return r.status === 0 ? null : tail(r);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** 칸 그림을 36×64 로 줄인 RGB — 판끼리 얼마나 다른지 잰다 */
|
|
91
|
+
export function thumb(png: string): Uint8Array {
|
|
92
|
+
const r = spawnSync("ffmpeg", ["-v", "error", "-i", png, "-vf", "scale=36:64:flags=area", "-f", "rawvideo", "-pix_fmt", "rgb24", "-"], { maxBuffer: 1 << 20 });
|
|
93
|
+
return new Uint8Array(r.stdout ?? []);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** 0..1 — 평균 화소 차. 0.04 아래면 사람 눈에 같은 판 */
|
|
97
|
+
export function imageDiff(a: Uint8Array, b: Uint8Array): number {
|
|
98
|
+
if (!a.length || a.length !== b.length) return 1;
|
|
99
|
+
let s = 0;
|
|
100
|
+
for (let i = 0; i < a.length; i++) s += Math.abs(a[i] - b[i]);
|
|
101
|
+
return s / a.length / 255;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// 칸 캐시 열쇠 — 겉모습(style)·견본 내용·세계 코드·견본 장면 문법(hook-number 패턴과 그 도구)이 같으면 같은 칸
|
|
105
|
+
const patternsDir = fileURLToPath(new URL("../../patterns/src/", import.meta.url));
|
|
106
|
+
const SAMPLE_CODE = [join(patternsDir, "kit.ts"), ...readdirSync(join(patternsDir, "hook-number")).sort().map((f) => join(patternsDir, "hook-number", f))];
|
|
107
|
+
|
|
108
|
+
export function cellKey(t: Theme): string {
|
|
109
|
+
const h = createHash("sha256");
|
|
110
|
+
h.update(JSON.stringify(t.style));
|
|
111
|
+
h.update(JSON.stringify(SAMPLE));
|
|
112
|
+
for (const f of ["effects.ts", "slots.ts"]) if (existsSync(join(themesDir, t.world, f))) h.update(readFileSync(join(themesDir, t.world, f)));
|
|
113
|
+
for (const f of SAMPLE_CODE) if (existsSync(f)) h.update(readFileSync(f));
|
|
114
|
+
return h.digest("hex").slice(0, 16);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const metaOf = (id: string) => cellPath(id).replace(/\.png$/, ".json");
|
|
118
|
+
|
|
119
|
+
export function cellFresh(t: Theme): boolean {
|
|
120
|
+
const m = metaOf(t.id);
|
|
121
|
+
return existsSync(cellPath(t.id)) && existsSync(m) && readJson(m).key === cellKey(t);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function markCell(t: Theme, frame: Frame): void {
|
|
125
|
+
writeFileSync(metaOf(t.id), `${JSON.stringify({ key: cellKey(t), at: frame.at, width: frame.width, height: frame.height, safe: frame.safe, pattern: frame.pattern ?? null }, null, 2)}\n`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export const cellFrame = (id: string): Frame | null => (existsSync(metaOf(id)) ? readJson(metaOf(id)) : null);
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* 칸이 없거나 낡은 테마만 찍는다(검사 없이 — 변주는 뽑을 때 검사를 넘었다). 세계마다 표준 장면을 한 번 짓고 변주는 style 만 갈아 찍는다.
|
|
132
|
+
* 돌려주는 것: id → 칸 경로(못 찍은 것은 빠진다)
|
|
133
|
+
*/
|
|
134
|
+
export function ensureCells(ids: string[], tmp: string, log: (l: string) => void = () => {}): Map<string, string> {
|
|
135
|
+
const out = new Map<string, string>();
|
|
136
|
+
const byWorld = new Map<string, Theme[]>();
|
|
137
|
+
for (const id of ids) {
|
|
138
|
+
const t = loadTheme(id);
|
|
139
|
+
if (cellFresh(t)) out.set(id, cellPath(id));
|
|
140
|
+
else byWorld.set(t.world, [...(byWorld.get(t.world) ?? []), t]);
|
|
141
|
+
}
|
|
142
|
+
for (const [world, list] of byWorld) {
|
|
143
|
+
const base = join(tmp, `${world}-base`);
|
|
144
|
+
const b = standardProject(world, base, { check: false });
|
|
145
|
+
if (!b.frame) {
|
|
146
|
+
log(`견본 칸 ${world}: 표준 장면을 못 지었다 — ${b.why}`);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
for (const t of list) {
|
|
150
|
+
const dir = t.variant ? join(tmp, t.id.replace("/", "--")) : base;
|
|
151
|
+
if (t.variant) restyle(base, dir, t.id);
|
|
152
|
+
const bad = still(dir, b.frame.at, cellPath(t.id));
|
|
153
|
+
if (bad) {
|
|
154
|
+
log(`견본 칸 ${t.id}: 못 찍음 — ${bad}`);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
markCell(t, b.frame);
|
|
158
|
+
out.set(t.id, cellPath(t.id));
|
|
159
|
+
log(`견본 칸 ${t.id}: ${cellPath(t.id)}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export interface GridCell {
|
|
166
|
+
png: string;
|
|
167
|
+
title: string;
|
|
168
|
+
sub?: string;
|
|
169
|
+
note?: string;
|
|
170
|
+
swatches?: string[];
|
|
171
|
+
badge?: string;
|
|
172
|
+
bad?: boolean;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const esc = (s: string) => s.replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]!);
|
|
176
|
+
|
|
177
|
+
/** 칸 격자 한 장 — 안전 영역 점선, 이름·설명·색 견본 */
|
|
178
|
+
export async function gridSheet(cells: GridCell[], out: string, o: { heading: string; cols: number; w: number; frame: Pick<Frame, "width" | "height" | "safe"> }): Promise<string> {
|
|
179
|
+
const { w, cols, frame } = o;
|
|
180
|
+
const h = Math.round((w * frame.height) / frame.width);
|
|
181
|
+
const k = w / frame.width;
|
|
182
|
+
const html = `<!doctype html><meta charset="utf-8"><style>
|
|
183
|
+
body { margin: 0; padding: 24px; background: #111; font: 15px/1.35 -apple-system, "Apple SD Gothic Neo", sans-serif; color: #ddd; width: ${cols * w + (cols - 1) * 16}px; }
|
|
184
|
+
h1 { margin: 0 0 16px; font-size: 18px; font-weight: 600; color: #fff; }
|
|
185
|
+
main { display: grid; grid-template-columns: repeat(${cols}, ${w}px); gap: 22px 16px; }
|
|
186
|
+
figure { margin: 0; position: relative; }
|
|
187
|
+
.safe { position: absolute; left: 0; width: ${w}px; border-top: 2px dashed #ff4d4d; opacity: .8; }
|
|
188
|
+
img { display: block; width: ${w}px; height: ${h}px; outline: 1px solid #333; object-fit: cover; }
|
|
189
|
+
figcaption { padding: 8px 2px 0; }
|
|
190
|
+
b { color: #fff; }
|
|
191
|
+
.d { display: inline-block; margin-left: 6px; padding: 0 6px; border: 1px solid #666; border-radius: 4px; font-size: 12px; }
|
|
192
|
+
small { display: block; color: #999; font-size: 12.5px; word-break: keep-all; }
|
|
193
|
+
.sw { display: flex; gap: 3px; margin-top: 5px; }
|
|
194
|
+
.sw i { width: 18px; height: 12px; border-radius: 2px; outline: 1px solid #444; }
|
|
195
|
+
.bad { color: #ff6b6b; }
|
|
196
|
+
</style><h1>${esc(o.heading)}</h1><main>${cells
|
|
197
|
+
.map(
|
|
198
|
+
(c) =>
|
|
199
|
+
`<figure><img src="${pathToFileURL(c.png).href}"><div class="safe" style="top:${Math.round(frame.safe.top * k)}px"></div><div class="safe" style="top:${Math.round((frame.height - frame.safe.bottom) * k)}px"></div><figcaption><b>${esc(c.title)}</b>${c.badge ? `<span class="d">${esc(c.badge)}</span>` : ""}${c.sub ? `<small>${esc(c.sub)}</small>` : ""}${c.note ? `<small class="${c.bad ? "bad" : ""}">${esc(c.note)}</small>` : ""}${c.swatches ? `<div class="sw">${c.swatches.map((s) => `<i style="background:${s}"></i>`).join("")}</div>` : ""}</figcaption></figure>`,
|
|
200
|
+
)
|
|
201
|
+
.join("")}</main>`;
|
|
202
|
+
mkdirSync(dirname(out), { recursive: true });
|
|
203
|
+
const page = out.replace(/\.png$/, ".html");
|
|
204
|
+
writeFileSync(page, html);
|
|
205
|
+
const browser = await launch();
|
|
206
|
+
try {
|
|
207
|
+
const p = await browser.newPage({ viewport: { width: 48 + cols * w + (cols - 1) * 16, height: 400 } });
|
|
208
|
+
await p.goto(pathToFileURL(page).href, { waitUntil: "load" });
|
|
209
|
+
writeFileSync(out, await p.screenshot({ fullPage: true, type: "png" }));
|
|
210
|
+
} finally {
|
|
211
|
+
await browser.close();
|
|
212
|
+
rmSync(page, { force: true });
|
|
213
|
+
}
|
|
214
|
+
return out;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** 격자 칸 글 — 이름·2D/3D·설명·색 견본 */
|
|
218
|
+
export function cellOf(t: Theme, png: string): GridCell {
|
|
219
|
+
const c = t.style.colors;
|
|
220
|
+
return {
|
|
221
|
+
png,
|
|
222
|
+
title: t.variant ? t.variant.name : `${t.name} · 기본`,
|
|
223
|
+
badge: themeDims(t),
|
|
224
|
+
sub: t.variant ? `${t.id} — ${t.variant.desc}` : `${t.id} — 세계 그대로`,
|
|
225
|
+
swatches: [c.bg, c.surface, c.ink, c.accent, c.success, c.danger],
|
|
226
|
+
};
|
|
227
|
+
}
|
|
@@ -4,14 +4,15 @@ import { basename, dirname, extname, join, resolve } from "node:path";
|
|
|
4
4
|
import { createInterface } from "node:readline/promises";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { askTerminal, blenderLibDir, capabilities, genImage, genVideo, hasKey, NeedsApproval, parseAllow, type Question, questionsText, seam, seamFrames, settle, still, whereToPut } from "@kasaframe/gen";
|
|
7
|
-
import { applyAnswers, attachStudio, loadSeries, type Series, seriesFromRequest, chat, codeBlock, detect, formatLook, jsonBlock, listTemplates, loadTemplate, look, lookSheet, makePlan, type Message, type Plan, planQuestions, premiumBlock, projectBrief, PURPOSES, type Purpose, readProject, spend, spentLine, WAIT, writeCaptions, writeStats } from "@kasaframe/plan";
|
|
7
|
+
import { applyAnswers, attachStudio, type LookInput, loadSeries, suggestThemes, usableTheme, type Series, seriesFromRequest, chat, codeBlock, detect, formatLook, jsonBlock, listTemplates, loadTemplate, look, lookSheet, makePlan, type Message, type Plan, planQuestions, premiumBlock, projectBrief, PURPOSES, type Purpose, readProject, spend, spentLine, WAIT, writeCaptions, writeStats } from "@kasaframe/plan";
|
|
8
8
|
import { checkContent, contentPrompt, directBrief } from "@kasaframe/director";
|
|
9
9
|
import { transform } from "esbuild";
|
|
10
10
|
import { bundleFor, dressSeed, pickDress } from "@kasaframe/motion/menu";
|
|
11
|
-
import { themeStyle } from "@kasaframe/themes";
|
|
11
|
+
import { themeStyle, worldOf } from "@kasaframe/themes";
|
|
12
12
|
import { captionMode } from "@kasaframe/motion/captions";
|
|
13
13
|
import { jizuraCheck } from "@kasaframe/jizura/install";
|
|
14
14
|
import { openPage } from "../browser.ts";
|
|
15
|
+
import { askThemeTerminal, candidateSheet, refLook } from "../pick.ts";
|
|
15
16
|
import { librosa } from "../deps.ts";
|
|
16
17
|
import { lyricsCheck } from "./lyrics.ts";
|
|
17
18
|
import { type Command, num, parseFlags } from "../command.ts";
|
|
@@ -92,8 +93,11 @@ kf make --answer <폴더> --image <값> --video <값> … Claude Code 모드
|
|
|
92
93
|
끝날 때(성공·실패·중단) <작업 폴더>/make-stats.json 에 단계별 모델·ms·토큰·usd 와 합계를 남기고 「OG 호출 N번 · 토큰 · $」 한 줄을 찍는다
|
|
93
94
|
--series 시리즈 묶음(series/<id>.json) · none. 안 주면 요청이 짚은 시리즈(「OG 쇼츠」처럼) — 용도·테마·목소리·곡·자막·길이·끝 카드·생성 답을 묻지 않고 그 묶음대로
|
|
94
95
|
--purpose 용도를 못 박는다: ${PURPOSES.join(" · ")}
|
|
95
|
-
--theme 테마 id · auto(요청이 「리소 느낌」처럼 짚은 테마, 아니면
|
|
96
|
-
안 주면(시리즈가 정하지도 않았으면) 묻는다 — 보기는
|
|
96
|
+
--theme 테마 id·변주 「<세계>/<변주>」 · auto(요청이 「리소 느낌」처럼 짚은 테마, 아니면 요청·분위기에 맞는 approved 후보 중 첫째) · none(프리셋만)
|
|
97
|
+
안 주면(시리즈가 정하지도 않았으면) 묻는다 — 보기는 「알아서」(= auto)와 요청·용도·분위기 낱말에 맞는 approved 세계·변주 넷,
|
|
98
|
+
넷만 담은 견본 시트를 그 자리에서 만든다(칸은 캐시). 테마 이름이 아닌 말을 주면 분위기 한 마디로 읽는다
|
|
99
|
+
--theme-mood 분위기 한 마디(「따뜻한 종이 느낌」·「어두운 네온」) — 그걸로 후보 넷을 다시 고른다. --answer 와 함께 주면 다시 묻는다
|
|
100
|
+
--theme-ref 레퍼런스 그림 경로·그림 주소·웹 페이지 주소 — 바탕·강조색을 읽어 후보 넷을 다시 고른다
|
|
97
101
|
--yes 묻지 않고 권장 답으로 — 돈이 드는 그림·영상도 승인한다(지역 제한이 걸린 H3 는 --video h3-pod 로 짚어야만)
|
|
98
102
|
--max-usd 영상 하나 상한(기본 1)
|
|
99
103
|
--video-provider 영상 공급자를 못 박는다(예: h3-pod — KF_H3_URL·KF_H3_STEPS 필요). 기본은 KF_VIDEO_PROVIDER, 없으면 생성 담당 기본
|
|
@@ -228,6 +232,13 @@ async function make(argv: string[], at: Track): Promise<number> {
|
|
|
228
232
|
return 2;
|
|
229
233
|
}
|
|
230
234
|
const assetFiles = str("assets") ? listFiles(resolve(str("assets")!)) : [];
|
|
235
|
+
let themeLook: LookInput;
|
|
236
|
+
try {
|
|
237
|
+
themeLook = await lookFlags(opts);
|
|
238
|
+
} catch (e) {
|
|
239
|
+
console.error(`kf make: ${(e as Error).message}`);
|
|
240
|
+
return 2;
|
|
241
|
+
}
|
|
231
242
|
// 시리즈가 먼저 — 같은 시리즈면 매번 같은 묶음. 사람이 따로 준 플래그는 그대로 이긴다
|
|
232
243
|
const series: Series | null = str("series") === "none" ? null : str("series") ? loadSeries(str("series")!) : seriesFromRequest(request);
|
|
233
244
|
if (series) console.error(`시리즈 ${series.id}(${series.label}) — 용도·테마·목소리·곡·자막·길이·끝 카드를 묶음대로`);
|
|
@@ -256,8 +267,10 @@ async function make(argv: string[], at: Track): Promise<number> {
|
|
|
256
267
|
|
|
257
268
|
// 만들기 전에 묻는다 — 뼈대를 만들고 나서 멈추면 반쯤 만든 폴더가 남는다
|
|
258
269
|
const caps = await capabilities({ probe: true });
|
|
259
|
-
const draft = makePlan({ request, purpose, assets: assetFiles, music: given ?? null, series: series?.id ?? "none" });
|
|
270
|
+
const draft = makePlan({ request, purpose, assets: assetFiles, music: given ?? null, series: series?.id ?? "none", look: themeLook });
|
|
260
271
|
const { questions, auto } = planQuestions(draft, caps);
|
|
272
|
+
// 테마를 물을 거면 후보 넷 견본 시트를 그 자리에서 — 질문 글에 시트 경로가 붙는다
|
|
273
|
+
const themeQ = questions.find((q) => q.id === "theme");
|
|
261
274
|
const flags = { ...seriesAnswers(series), ...opts };
|
|
262
275
|
const settled = settle(questions, { given: flags, yes: !!opts.yes, noGen: !!opts["no-gen"], allow: parseAllow(opts.allow) });
|
|
263
276
|
// 묻지 않고 정한 답(있는 공짜 능력)도 사람이 준 플래그·시리즈 답이 이긴다. --no-gen 이면 공짜라도 생성 모델(그림·영상)은 뺀다
|
|
@@ -282,6 +295,20 @@ async function make(argv: string[], at: Track): Promise<number> {
|
|
|
282
295
|
answers = { ...answers, ...asked };
|
|
283
296
|
}
|
|
284
297
|
if (answers.beats === "none" && answers.music && !/^(gen:|none$)/.test(answers.music)) answers.music = "none";
|
|
298
|
+
if (themeQ && open.includes(themeQ)) await candidateSheet(themeQ, (l) => console.error(l));
|
|
299
|
+
// 터미널이면 테마는 따로 — 분위기 한 마디·그림 경로·주소를 치면 그걸로 후보를 다시 골라 다시 묻는다
|
|
300
|
+
if (themeQ && open.includes(themeQ) && model !== "claude-code") {
|
|
301
|
+
const picked = await askThemeTerminal(themeQ, async (r) => {
|
|
302
|
+
themeLook = { ...themeLook, ...r, ...(r.mood ? { mood: [themeLook.mood, r.mood].filter(Boolean).join(" ") } : {}) };
|
|
303
|
+
const q = planQuestions(makePlan({ request, purpose, assets: assetFiles, music: given ?? null, series: series?.id ?? "none", look: themeLook }), caps).questions.find((x) => x.id === "theme")!;
|
|
304
|
+
await candidateSheet(q, (l) => console.error(l));
|
|
305
|
+
return q;
|
|
306
|
+
});
|
|
307
|
+
if (picked) {
|
|
308
|
+
answers.theme = picked;
|
|
309
|
+
open = open.filter((q) => q !== themeQ);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
285
312
|
if (open.length && model !== "claude-code") {
|
|
286
313
|
const asked = await askTerminal(open);
|
|
287
314
|
if (!asked) {
|
|
@@ -307,7 +334,10 @@ async function make(argv: string[], at: Track): Promise<number> {
|
|
|
307
334
|
if (song) newArgs.push("--music", song);
|
|
308
335
|
if (str("title")) newArgs.push("--title", str("title")!);
|
|
309
336
|
// 테마 질문의 답(플래그·터미널) → 아직 묻는 중이거나 묻지 않은 테마(시리즈·요청이 짚은 것)는 auto. 테마 없이 프리셋만 쓰려면 --theme none
|
|
310
|
-
|
|
337
|
+
// 「알아서」·묻는 중이면 후보 첫째 — 분위기·레퍼런스로 고른 넷이라 kf new 의 auto(요청 낱말만)와 다를 수 있다
|
|
338
|
+
const firstPick = themeQ?.choices.find((c) => c.value !== "auto")?.value;
|
|
339
|
+
const themeArg = answers.theme && answers.theme !== WAIT && answers.theme !== "auto" ? answers.theme : (str("theme") ?? (firstPick && (answers.theme === "auto" || open.includes(themeQ!)) ? firstPick : "auto"));
|
|
340
|
+
newArgs.push("--theme", themeArg);
|
|
311
341
|
if (opts.force) newArgs.push("--force");
|
|
312
342
|
const made = spawnSync(process.execPath, newArgs, { stdio: ["ignore", "inherit", "inherit"] });
|
|
313
343
|
if (made.status !== 0) return made.status ?? 1;
|
|
@@ -315,7 +345,7 @@ async function make(argv: string[], at: Track): Promise<number> {
|
|
|
315
345
|
const studio = await attachStudio({ dir, request, model, purpose });
|
|
316
346
|
const unmirror = studio?.mirror();
|
|
317
347
|
if (studio) console.log(`작업실: ${studio.url}`);
|
|
318
|
-
const plan: Plan = { ...applyAnswers(JSON.parse(readFileSync(join(dir, "plan.json"), "utf8")), answers).plan, asks: open };
|
|
348
|
+
const plan: Plan = { ...applyAnswers(JSON.parse(readFileSync(join(dir, "plan.json"), "utf8")), answers).plan, asks: open, ...(themeLook.mood || themeLook.ref ? { themeLook } : {}) };
|
|
319
349
|
// 새 프로젝트는 이 영상의 기본으로 적는다 — 계획 다듬기가 내레이션을 쓸지도 이걸 본다
|
|
320
350
|
if (captions) {
|
|
321
351
|
const kfPath = join(dir, "kf.json");
|
|
@@ -582,6 +612,19 @@ async function probeScene(dir: string, id: string): Promise<string[]> {
|
|
|
582
612
|
return [...new Set(problems)];
|
|
583
613
|
}
|
|
584
614
|
|
|
615
|
+
// 테마 고르기 플래그 — --theme-mood·--theme-ref, 그리고 테마 이름이 아닌 --theme 값(분위기 한 마디로 읽는다)
|
|
616
|
+
async function lookFlags(opts: Record<string, string | boolean | undefined>): Promise<LookInput> {
|
|
617
|
+
const look: LookInput = {};
|
|
618
|
+
const theme = typeof opts.theme === "string" ? opts.theme : undefined;
|
|
619
|
+
if (theme && theme !== "auto" && theme !== "none" && !usableTheme(theme)) {
|
|
620
|
+
look.mood = theme;
|
|
621
|
+
delete opts.theme;
|
|
622
|
+
}
|
|
623
|
+
if (typeof opts["theme-mood"] === "string") look.mood = [look.mood, opts["theme-mood"]].filter(Boolean).join(" ");
|
|
624
|
+
if (typeof opts["theme-ref"] === "string") look.ref = await refLook(opts["theme-ref"]);
|
|
625
|
+
return look;
|
|
626
|
+
}
|
|
627
|
+
|
|
585
628
|
// 테마 후보마다 첫 장면을 그 테마로 한 장 — 사람이 셋을 나란히 보고 고른다. style.json 만 잠깐 바꿔 찍고 되돌린다
|
|
586
629
|
function themeStills(dir: string, ids: string[]): void {
|
|
587
630
|
const stylePath = join(dir, "style.json");
|
|
@@ -734,6 +777,30 @@ async function answerProject(dir: string, opts: Record<string, string | boolean
|
|
|
734
777
|
return 2;
|
|
735
778
|
}
|
|
736
779
|
const plan: Plan = JSON.parse(readFileSync(file, "utf8"));
|
|
780
|
+
// 테마에 분위기 한 마디·레퍼런스를 줬으면 후보 넷을 다시 고르고 견본 시트를 새로 만들어 다시 묻는다 — 답은 그다음
|
|
781
|
+
let look: LookInput;
|
|
782
|
+
try {
|
|
783
|
+
look = await lookFlags(opts);
|
|
784
|
+
} catch (e) {
|
|
785
|
+
console.error(`kf make --answer: ${(e as Error).message}`);
|
|
786
|
+
return 2;
|
|
787
|
+
}
|
|
788
|
+
if (look.mood || look.ref) {
|
|
789
|
+
plan.themeLook = { ...plan.themeLook, ...look, ...(look.mood ? { mood: [plan.themeLook?.mood, look.mood].filter(Boolean).join(" ") } : {}) };
|
|
790
|
+
const q = planQuestions(plan, await capabilities({ probe: false })).questions.find((x) => x.id === "theme");
|
|
791
|
+
if (!q) {
|
|
792
|
+
console.error("kf make --answer: 이 프로젝트는 테마를 묻지 않는다(시리즈나 요청이 테마를 정했다) — --theme <id> 로 바꾼다");
|
|
793
|
+
return 2;
|
|
794
|
+
}
|
|
795
|
+
const sheet = await candidateSheet(q, (l) => console.error(l));
|
|
796
|
+
plan.asks = [...(plan.asks ?? []).filter((x) => x.id !== "theme"), q];
|
|
797
|
+
writeJson(file, plan);
|
|
798
|
+
writeFileSync(join(dir, "MAKE.md"), isDirect(dir) ? directBrief(dir) : projectBrief(dir));
|
|
799
|
+
console.log(`테마 후보를 다시 골랐다${sheet ? ` — 견본 시트 ${sheet}` : ""}:`);
|
|
800
|
+
for (const c of q.choices) console.log(` --theme ${c.value.padEnd(30)} ${c.label}${c.note ? ` — ${c.note}` : ""}`);
|
|
801
|
+
console.error("사람에게 다시 묻고 kf make --answer <폴더> --theme <값> 으로 답을 넣는다");
|
|
802
|
+
return 3;
|
|
803
|
+
}
|
|
737
804
|
const waiting = new Set((plan.asks ?? []).map((q) => q.id));
|
|
738
805
|
const fresh = planQuestions(plan, await capabilities({ probe: true })).questions.filter((q) => waiting.has(q.id));
|
|
739
806
|
const settled = settle(fresh, { given: opts, yes: !!opts.yes, noGen: !!opts["no-gen"], allow: parseAllow(opts.allow) });
|
|
@@ -765,7 +832,8 @@ function retheme(dir: string, answer: string): string | null {
|
|
|
765
832
|
const plan = readPlan(dir) as Plan;
|
|
766
833
|
const kfPath = join(dir, "kf.json");
|
|
767
834
|
const kf = JSON.parse(readFileSync(kfPath, "utf8"));
|
|
768
|
-
const id: string | null =
|
|
835
|
+
const id: string | null =
|
|
836
|
+
answer === "auto" ? (suggestThemes(plan.request, plan.purpose, plan.aspect, 1, plan.themeLook ?? {})[0]?.id ?? plan.themeCandidates?.[0]?.id ?? kf.theme ?? null) : answer === "none" ? null : answer;
|
|
769
837
|
if ((kf.theme ?? null) === id) return id;
|
|
770
838
|
const tpl = loadTemplate(plan.purpose);
|
|
771
839
|
// 프리셋으로 돌아가면 kf new 가 테마 없이 골랐을 프리셋 — 시리즈·요청 낱말·틀 차례
|
|
@@ -774,7 +842,7 @@ function retheme(dir: string, answer: string): string | null {
|
|
|
774
842
|
style.motion = { ...style.motion, ...tpl.motion };
|
|
775
843
|
writeJson(join(dir, "style.json"), style);
|
|
776
844
|
if (tpl.moves) {
|
|
777
|
-
const dress = pickDress(dressSeed(plan.request || plan.title, plan.purpose, id ?? preset!), plan.scenes, bundleFor(tpl.moves, id ?? undefined));
|
|
845
|
+
const dress = pickDress(dressSeed(plan.request || plan.title, plan.purpose, worldOf(id) ?? preset!), plan.scenes, bundleFor(tpl.moves, id ?? undefined));
|
|
778
846
|
const byId = new Map(plan.scenes.map((s, i) => [s.id, dress[i]]));
|
|
779
847
|
for (const s of kf.scenes as { id: string; file: string; dress?: Record<string, string> }[]) {
|
|
780
848
|
const next = byId.get(s.id);
|
|
@@ -3,7 +3,7 @@ import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFi
|
|
|
3
3
|
import { basename, join, relative, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { bundleFor, dressSeed, NO_DRESS, pickDress } from "@kasaframe/motion/menu";
|
|
6
|
-
import { themeStyle } from "@kasaframe/themes";
|
|
6
|
+
import { themeStyle, worldOf } from "@kasaframe/themes";
|
|
7
7
|
import { type Aspect, type BeatsLike, type Plan, type Purpose, listTemplates, loadTemplate, makePlan, parseTitle, PURPOSES, sceneSkeleton, templatesDir } from "@kasaframe/plan";
|
|
8
8
|
import { type Command, num, parseFlags } from "../command.ts";
|
|
9
9
|
|
|
@@ -116,7 +116,7 @@ kf new <폴더> --plan plan.json kf make 가 세운 계
|
|
|
116
116
|
|
|
117
117
|
// 장면마다 연출 수(바탕·글·경계 덮기) — 용도 틀·테마 묶음에서 요청 글을 씨앗으로 고른다. 같은 요청이면 같은 수가 걸린다
|
|
118
118
|
// 틀에 묶음이 없으면(뮤비 — 가사 층이 화면을 맡는다) 무대 기본 그대로
|
|
119
|
-
const dress = tpl.moves ? pickDress(dressSeed(plan.request || plan.title, plan.purpose, plan.theme ?? plan.style), plan.scenes, bundleFor(tpl.moves, plan.theme ?? undefined)) : plan.scenes.map(() => ({ ...NO_DRESS }));
|
|
119
|
+
const dress = tpl.moves ? pickDress(dressSeed(plan.request || plan.title, plan.purpose, worldOf(plan.theme) ?? plan.style), plan.scenes, bundleFor(tpl.moves, plan.theme ?? undefined)) : plan.scenes.map(() => ({ ...NO_DRESS }));
|
|
120
120
|
|
|
121
121
|
const frame = { width: plan.width, height: plan.height };
|
|
122
122
|
const safeArea = plan.aspect === tpl.aspect ? tpl.safeArea : (tpl.variants?.[plan.aspect]?.safeArea ?? tpl.safeArea);
|