@nodaro/prompts 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +105 -0
- package/README.md +27 -0
- package/dist/index.cjs +21240 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3599 -0
- package/dist/index.d.ts +3599 -0
- package/dist/index.js +20854 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -0
- package/src/__tests__/__snapshots__/prompt-builder-segments.test.ts.snap +65 -0
- package/src/__tests__/action-fx.test.ts +155 -0
- package/src/__tests__/apply-picker-json.test.ts +50 -0
- package/src/__tests__/assemble-image-input.test.ts +248 -0
- package/src/__tests__/assemble-suno-input.test.ts +283 -0
- package/src/__tests__/brand-tokens.test.ts +81 -0
- package/src/__tests__/build-image-prompt-element-injection.test.ts +118 -0
- package/src/__tests__/build-image-prompt-hybrid-format.test.ts +131 -0
- package/src/__tests__/build-image-prompt-mentions.test.ts +809 -0
- package/src/__tests__/build-image-prompt-reference-cap.test.ts +57 -0
- package/src/__tests__/build-image-prompt-reference-numbering.test.ts +237 -0
- package/src/__tests__/build-image-prompt-reference-order.test.ts +313 -0
- package/src/__tests__/camera-motions-from-connections.test.ts +71 -0
- package/src/__tests__/catalog-gapfill.test.ts +53 -0
- package/src/__tests__/character-convergence-image.test.ts +217 -0
- package/src/__tests__/character-default-role-image.test.ts +167 -0
- package/src/__tests__/character-default-role-video.test.ts +168 -0
- package/src/__tests__/character-default-role.test.ts +70 -0
- package/src/__tests__/character-fx.test.ts +200 -0
- package/src/__tests__/entity-prompts-location.test.ts +97 -0
- package/src/__tests__/entity-prompts.test.ts +240 -0
- package/src/__tests__/expand-extra-refs-role.test.ts +50 -0
- package/src/__tests__/factory-presets.test.ts +1045 -0
- package/src/__tests__/factory-snippets.test.ts +68 -0
- package/src/__tests__/framing-multi.test.ts +71 -0
- package/src/__tests__/framing-vantage.test.ts +39 -0
- package/src/__tests__/i18n-entry-completeness.test.ts +269 -0
- package/src/__tests__/identity-lock.test.ts +46 -0
- package/src/__tests__/instrumentation.test.ts +68 -0
- package/src/__tests__/lighting-multi.test.ts +68 -0
- package/src/__tests__/location-convergence-image.test.ts +124 -0
- package/src/__tests__/mention-lock-flag.test.ts +499 -0
- package/src/__tests__/multi-picker-spec.test.ts +71 -0
- package/src/__tests__/music-genre.test.ts +103 -0
- package/src/__tests__/music-mood.test.ts +87 -0
- package/src/__tests__/object-creature-convergence-image.test.ts +105 -0
- package/src/__tests__/parameter-prompt-hint.test.ts +270 -0
- package/src/__tests__/parameter-registry-sync.test.ts +243 -0
- package/src/__tests__/person-age.test.ts +80 -0
- package/src/__tests__/person-analyzer-invariants.test.ts +47 -0
- package/src/__tests__/person-body-axes.test.ts +67 -0
- package/src/__tests__/person-facial-geometry.test.ts +156 -0
- package/src/__tests__/person-regional-aesthetic.test.ts +161 -0
- package/src/__tests__/person-sections.test.ts +18 -0
- package/src/__tests__/picker-analyzer-registry.test.ts +108 -0
- package/src/__tests__/picker-catalogs-project.test.ts +85 -0
- package/src/__tests__/picker-catalogs.test.ts +53 -0
- package/src/__tests__/picker-limits.test.ts +20 -0
- package/src/__tests__/prompt-builder-segments.test.ts +183 -0
- package/src/__tests__/prompt-builder-structured-fields.test.ts +40 -0
- package/src/__tests__/prompt-builder.test.ts +1773 -0
- package/src/__tests__/prompt-wizard-categories.test.ts +31 -0
- package/src/__tests__/provider-prompt-doctrine.test.ts +49 -0
- package/src/__tests__/resolve-prompt-append.test.ts +58 -0
- package/src/__tests__/resolve-prompt.test.ts +44 -0
- package/src/__tests__/role-picker-shared.test.ts +208 -0
- package/src/__tests__/seedance-2-inputs.test.ts +173 -0
- package/src/__tests__/seedance-extend.test.ts +44 -0
- package/src/__tests__/sound-aggregator.test.ts +350 -0
- package/src/__tests__/style-presets.test.ts +34 -0
- package/src/__tests__/temporal-multi.test.ts +74 -0
- package/src/__tests__/transitions.test.ts +213 -0
- package/src/__tests__/video-reference-features.test.ts +41 -0
- package/src/__tests__/video-reference-leading-refs.test.ts +90 -0
- package/src/__tests__/video-reference-resolver.test.ts +233 -0
- package/src/__tests__/video-reference-roles.test.ts +96 -0
- package/src/__tests__/voice-character.test.ts +48 -0
- package/src/__tests__/voice-delivery.test.ts +41 -0
- package/src/__tests__/wardrobe.test.ts +25 -0
- package/src/action-fx.ts +255 -0
- package/src/aesthetic.ts +435 -0
- package/src/assemble-image-input.ts +236 -0
- package/src/assemble-suno-input.ts +147 -0
- package/src/atmosphere.ts +104 -0
- package/src/backdrop.ts +131 -0
- package/src/brand-tokens.ts +154 -0
- package/src/camera-format.ts +76 -0
- package/src/camera-motions.ts +615 -0
- package/src/character-fx.ts +274 -0
- package/src/color-look.ts +103 -0
- package/src/composition-effects.ts +67 -0
- package/src/entity-prompts.ts +231 -0
- package/src/era.ts +292 -0
- package/src/exposure-settings.ts +142 -0
- package/src/factory-presets/generate-image.ts +1644 -0
- package/src/factory-presets/generate-video.ts +1116 -0
- package/src/factory-presets/index.ts +46 -0
- package/src/factory-presets/lottie-overlay.ts +166 -0
- package/src/factory-presets/motion-graphics.ts +350 -0
- package/src/factory-presets/music.ts +734 -0
- package/src/factory-presets/sfx.ts +136 -0
- package/src/factory-presets/shared-image.ts +207 -0
- package/src/factory-presets/switchx.ts +65 -0
- package/src/factory-presets/text.ts +292 -0
- package/src/factory-presets/types.ts +51 -0
- package/src/factory-presets/video-edit.ts +136 -0
- package/src/factory-presets/voice.ts +172 -0
- package/src/factory-presets.ts +2 -0
- package/src/factory-snippets/catalog.ts +105 -0
- package/src/factory-snippets/index.ts +16 -0
- package/src/factory-snippets/types.ts +33 -0
- package/src/framing.ts +634 -0
- package/src/held-prop.ts +187 -0
- package/src/identity-lock.ts +213 -0
- package/src/index.ts +66 -0
- package/src/instrumentation.ts +337 -0
- package/src/lens.ts +59 -0
- package/src/lighting.ts +229 -0
- package/src/loop-subject.ts +276 -0
- package/src/materials.ts +184 -0
- package/src/mood.ts +186 -0
- package/src/music-genre.ts +662 -0
- package/src/music-mood.ts +137 -0
- package/src/object-asset-presets.ts +81 -0
- package/src/parameter-prompt-hint.ts +281 -0
- package/src/person.ts +1368 -0
- package/src/photo-genre.ts +151 -0
- package/src/photographer.ts +612 -0
- package/src/picker-analyzer-registry.ts +374 -0
- package/src/picker-catalogs.ts +858 -0
- package/src/pose.ts +246 -0
- package/src/post-process-effects.ts +94 -0
- package/src/prompt-builder-structured-fields.ts +116 -0
- package/src/prompt-builder.ts +2964 -0
- package/src/prompt-templates.ts +50 -0
- package/src/prompt-wizard-categories.ts +334 -0
- package/src/provider-prompt-doctrine.ts +85 -0
- package/src/render-quality.ts +89 -0
- package/src/resolve-prompt.ts +120 -0
- package/src/seedance-2-inputs.ts +100 -0
- package/src/setting.ts +130 -0
- package/src/sound-aggregator.ts +241 -0
- package/src/style-presets.ts +162 -0
- package/src/style.ts +99 -0
- package/src/styling.ts +585 -0
- package/src/temporal.ts +151 -0
- package/src/transitions.ts +333 -0
- package/src/video-reference-resolver.ts +823 -0
- package/src/voice-character.ts +237 -0
- package/src/voice-delivery.ts +142 -0
- package/src/wardrobe.ts +179 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical catalog of character-driven effects for AI-video generation.
|
|
3
|
+
*
|
|
4
|
+
* Shared between frontend (picker UI, prompt hint injection) and backend
|
|
5
|
+
* (orchestrator payload builder). The `promptHint` is a natural-language
|
|
6
|
+
* cue that gets composed into the user prompt when a character-fx node
|
|
7
|
+
* is connected to a video consumer.
|
|
8
|
+
*
|
|
9
|
+
* Every `promptHint` references "the subject" at least once — the composer
|
|
10
|
+
* does a global regex replace of "the subject" with the target ref's
|
|
11
|
+
* display name (character/face/object/location) when a target is wired.
|
|
12
|
+
*
|
|
13
|
+
* Multi-pick supported: value field accepts `string | string[]` (cap 2).
|
|
14
|
+
* Per-id substitution: each base hint is independently rewritten BEFORE
|
|
15
|
+
* the join, so "Aria transforms into a werewolf, and Aria opens their
|
|
16
|
+
* mouth and exhales..." reads correctly.
|
|
17
|
+
*
|
|
18
|
+
* null input is treated like undefined (falsy short-circuit → returns "")
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export type CharacterFxCategory =
|
|
22
|
+
| "transformation"
|
|
23
|
+
| "power"
|
|
24
|
+
| "body-mod"
|
|
25
|
+
| "face-expression"
|
|
26
|
+
| "aura-ambient"
|
|
27
|
+
|
|
28
|
+
export interface CharacterFx {
|
|
29
|
+
readonly id: string
|
|
30
|
+
readonly label: string
|
|
31
|
+
readonly category: CharacterFxCategory
|
|
32
|
+
readonly description: string
|
|
33
|
+
readonly promptHint: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type CharacterFxPosition = "auto" | "start" | "middle" | "end" | "full"
|
|
37
|
+
export type CharacterFxDuration = "auto" | "instant" | "short" | "medium" | "long"
|
|
38
|
+
export type CharacterFxIntensity = "auto" | "subtle" | "natural" | "dynamic" | "crazy"
|
|
39
|
+
|
|
40
|
+
export interface CharacterFxTiming {
|
|
41
|
+
position?: CharacterFxPosition
|
|
42
|
+
duration?: CharacterFxDuration
|
|
43
|
+
intensity?: CharacterFxIntensity
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const CHARACTER_FX: ReadonlyArray<CharacterFx> = [
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// TRANSFORMATION — 14 entries — subject becomes a different entity
|
|
49
|
+
// (12 transformations + 2 defaults: "auto" / "none")
|
|
50
|
+
// ============================================================================
|
|
51
|
+
{ id: "auto", label: "Auto", category: "transformation", description: "Let the model choose", promptHint: "" },
|
|
52
|
+
{ id: "none", label: "None", category: "transformation", description: "No character effect", promptHint: "" },
|
|
53
|
+
{ id: "werewolf", label: "Werewolf", category: "transformation", description: "Transforms into a werewolf",
|
|
54
|
+
promptHint: "the subject transforms into a werewolf — fur sprouts across the skin, fangs and claws extend, the snout elongates, eyes glow yellow, body re-shapes with visible muscle and bone movement, clothing tears" },
|
|
55
|
+
{ id: "vampire", label: "Vampire", category: "transformation", description: "Transforms into a vampire",
|
|
56
|
+
promptHint: "the subject transforms into a vampire — skin pales, fangs extend, eyes shift to crimson, pupils dilate, posture shifts predatory, with a faint mist drifting around the body" },
|
|
57
|
+
{ id: "cyborg", label: "Cyborg Reveal", category: "transformation", description: "Skin peels back revealing cybernetics",
|
|
58
|
+
promptHint: "the subject's skin peels open along seams to reveal glowing cybernetic mechanisms beneath — exposed circuit boards, hydraulic joints, blue LED indicators along the limbs and torso" },
|
|
59
|
+
{ id: "ghost-form", label: "Ghost Form", category: "transformation", description: "Body becomes translucent / ethereal",
|
|
60
|
+
promptHint: "the subject becomes translucent and ethereal, body edges feathering into mist, faint inner glow visible through the skin, feet detaching from the ground in slow float" },
|
|
61
|
+
{ id: "statue-stone", label: "Petrify to Stone", category: "transformation", description: "Body petrifies into stone statue",
|
|
62
|
+
promptHint: "the subject's body petrifies into grey weathered stone starting from the extremities and creeping inward, fine cracks forming as the transformation locks the pose into a statue" },
|
|
63
|
+
{ id: "liquid-metal", label: "Liquid Metal", category: "transformation", description: "T-1000 style liquid metal form",
|
|
64
|
+
promptHint: "the subject's body shifts into glossy chrome-silver liquid metal that reflects the environment, surface rippling, features re-forming with mirror-smooth fluid motion (T-1000 style)" },
|
|
65
|
+
{ id: "animalization", label: "Animalization", category: "transformation", description: "Morphs into an animal",
|
|
66
|
+
promptHint: "the subject morphs into a wild animal — body re-shaping, fur or feathers emerging, limbs reconfiguring, the head transforming into the animal's, eyes shifting to the animal's coloration" },
|
|
67
|
+
{ id: "gorilla-form", label: "Gorilla Form", category: "transformation", description: "Transforms into a gorilla",
|
|
68
|
+
promptHint: "the subject transforms into a massive silverback gorilla — body bulks up dramatically, dark fur sprouts, face re-shapes with a heavy brow, posture shifts to hunched primate stance" },
|
|
69
|
+
{ id: "mystification", label: "Mystification", category: "transformation", description: "Magical aura wraps & transforms subject",
|
|
70
|
+
promptHint: "the subject is enveloped in swirling magical particles and arcane symbols that orbit the body, the form within visibly shifting until the aura clears revealing the transformed subject" },
|
|
71
|
+
{ id: "gas-form", label: "Gas Transformation", category: "transformation", description: "Body dissipates into gaseous form",
|
|
72
|
+
promptHint: "the subject's body dissolves into a swirling cloud of coloured gas that drifts and re-coalesces in the same space, the form re-condensing into a faintly altered version of the subject" },
|
|
73
|
+
{ id: "diamond-skin", label: "Diamond Skin", category: "transformation", description: "Body crystallizes into diamond facets",
|
|
74
|
+
promptHint: "the subject's body crystallizes into faceted diamond — skin hardening into reflective gem facets that refract light in rainbow caustics, the silhouette holding the same pose" },
|
|
75
|
+
{ id: "agent-reveal", label: "Agent Reveal", category: "transformation", description: "Suit and shades materialize on subject",
|
|
76
|
+
promptHint: "the subject's everyday clothing rapidly morphs into a sharp black suit, tie tightening, dark sunglasses materializing onto the face, posture stiffening into agent stance (Men-in-Black style)" },
|
|
77
|
+
|
|
78
|
+
// ============================================================================
|
|
79
|
+
// POWER — 12 entries — subject demonstrates a fantastical ability
|
|
80
|
+
// ============================================================================
|
|
81
|
+
{ id: "fire-breathe", label: "Fire Breathe", category: "power", description: "Breathes a sustained jet of flame",
|
|
82
|
+
promptHint: "the subject opens their mouth and exhales a sustained jet of orange-yellow fire that arcs forward through the frame, with smoke trailing and embers scattering, lighting their face in warm reflected glow" },
|
|
83
|
+
{ id: "ice-breathe", label: "Ice Breathe", category: "power", description: "Breathes a stream of freezing air",
|
|
84
|
+
promptHint: "the subject exhales a stream of frigid pale-blue air with visible ice crystals forming in the breath, surfaces in front of them rapidly frosting over with creeping ice patterns" },
|
|
85
|
+
{ id: "air-bending", label: "Air Bending", category: "power", description: "Manipulates a swirling vortex of air",
|
|
86
|
+
promptHint: "the subject's hands trace through the air and a visible swirling vortex of wind follows the gestures, dust and loose objects spiraling along the path of the conjured air currents" },
|
|
87
|
+
{ id: "water-bending", label: "Water Bending", category: "power", description: "Manipulates flowing water with gestures",
|
|
88
|
+
promptHint: "the subject's hand gestures pull a ribbon of water into the air, the water arcing and twisting in fluid sculpted shapes that follow the motion of the fingertips" },
|
|
89
|
+
{ id: "earth-bending", label: "Earth Bending", category: "power", description: "Raises stone slabs from the ground",
|
|
90
|
+
promptHint: "the subject stomps or gestures downward and slabs of stone or earth tear upward from the ground around them in geometric shards, dust and debris falling away as the rock rises" },
|
|
91
|
+
{ id: "lightning-hands", label: "Lightning Hands", category: "power", description: "Arcs of electricity from hands",
|
|
92
|
+
promptHint: "the subject's hands crackle with bright blue-white electric arcs that branch outward in jagged forking patterns, the room flickering with the strobing illumination of the discharge" },
|
|
93
|
+
{ id: "levitation", label: "Levitation", category: "power", description: "Rises off the ground, body horizontal or vertical",
|
|
94
|
+
promptHint: "the subject rises slowly off the ground in a controlled vertical lift, hair and loose clothing drifting upward in zero-gravity sway, faint heat-haze air distortion visible below the feet" },
|
|
95
|
+
{ id: "telekinesis", label: "Telekinesis", category: "power", description: "Nearby objects float and orbit",
|
|
96
|
+
promptHint: "the subject extends a hand and nearby objects rise into the air around them, slowly rotating and orbiting in unsupported flight, debris and small items drawn into a halo of suspended motion" },
|
|
97
|
+
{ id: "invisibility", label: "Invisibility", category: "power", description: "Body fades to transparent / refractive",
|
|
98
|
+
promptHint: "the subject's body fades into transparency with a faint refractive shimmer at the edges, only a barely-visible heat-haze outline indicating where they stand as they vanish from sight" },
|
|
99
|
+
{ id: "hero-flight", label: "Hero Flight", category: "power", description: "Launches into the sky in flight pose",
|
|
100
|
+
promptHint: "the subject launches upward into the sky in a heroic superhero flight pose, arms forward, cape or clothing whipping behind, with a sonic-boom shockwave at the launch point" },
|
|
101
|
+
{ id: "super-speed", label: "Super Speed", category: "power", description: "Blurs into super-fast motion",
|
|
102
|
+
promptHint: "the subject blurs into super-fast motion leaving multiple trailing afterimages and lightning-streak motion lines, the surrounding scene appearing momentarily frozen against their speed" },
|
|
103
|
+
{ id: "soul-departure", label: "Soul Departure", category: "power", description: "Translucent soul rises from body",
|
|
104
|
+
promptHint: "a translucent luminous soul rises out of the subject's body, drifting upward as a ghost-like figure while the physical body remains in its pose, a faint silver thread connecting the two" },
|
|
105
|
+
|
|
106
|
+
// ============================================================================
|
|
107
|
+
// BODY-MOD — 9 entries — parts of the subject change / emerge / leave
|
|
108
|
+
// ============================================================================
|
|
109
|
+
{ id: "wings-grow", label: "Wings Grow", category: "body-mod", description: "Wings sprout and unfurl from back",
|
|
110
|
+
promptHint: "the subject's back arches and two large wings — feathered angelic or leathery demonic — unfurl outward from the shoulder blades, extending to full span behind them" },
|
|
111
|
+
{ id: "horns-grow", label: "Horns Emerge", category: "body-mod", description: "Horns push out from the head",
|
|
112
|
+
promptHint: "the subject's forehead furrows as two pointed horns push outward from the skull, growing in a curving arc above the brows with the skin parting cleanly as the bone emerges" },
|
|
113
|
+
{ id: "tail-emerge", label: "Tail Emerge", category: "body-mod", description: "Tail extends from base of spine",
|
|
114
|
+
promptHint: "a tail — feline, reptilian, or demonic — extends rapidly from the base of the subject's spine, swishing into motion behind them once fully grown" },
|
|
115
|
+
{ id: "tentacles-emerge", label: "Tentacles Emerge", category: "body-mod", description: "Tentacles writhe out from back / body",
|
|
116
|
+
promptHint: "long writhing tentacles emerge from the subject's back or torso, slick and dark, snaking outward in undulating motion, the skin parting around the base of each appendage" },
|
|
117
|
+
{ id: "extra-eyes", label: "Extra Eyes Open", category: "body-mod", description: "Additional eyes open across face / body",
|
|
118
|
+
promptHint: "additional eyes open across the subject's face, forehead, and body — blinking in sequence and tracking independently, with the skin smoothly accommodating each new aperture" },
|
|
119
|
+
{ id: "head-explode", label: "Head Explosion", category: "body-mod", description: "Head bursts apart violently (PG-13)",
|
|
120
|
+
promptHint: "the subject's head bursts apart in a violent explosion of light and abstract particles, the body remaining standing momentarily before the camera cuts away — stylized, non-graphic" },
|
|
121
|
+
{ id: "head-off", label: "Head Removal", category: "body-mod", description: "Head detaches and floats free (PG-13, stylized)",
|
|
122
|
+
promptHint: "the subject's head smoothly detaches from the neck and floats free above the body in stylized magical detachment, the body remaining poised and the head rotating to face the camera" },
|
|
123
|
+
{ id: "spiders-from-mouth", label: "Spiders From Mouth", category: "body-mod", description: "Spiders crawl out from open mouth (horror)",
|
|
124
|
+
promptHint: "the subject's mouth opens wide and a stream of dark spiders crawls outward across the lips and cheeks, scattering down the face and body in a horror-genre reveal" },
|
|
125
|
+
{ id: "skin-surge", label: "Skin Surge", category: "body-mod", description: "Skin ripples with under-the-surface motion",
|
|
126
|
+
promptHint: "the subject's skin ripples with visible wave-like surges of motion underneath the surface, as if something is shifting through the body, the skin stretching and re-settling in pulsing rhythm" },
|
|
127
|
+
|
|
128
|
+
// ============================================================================
|
|
129
|
+
// FACE-EXPRESSION — 8 entries — face contorts / mask / eyes change
|
|
130
|
+
// ============================================================================
|
|
131
|
+
{ id: "horror-face", label: "Horror Face", category: "face-expression", description: "Face contorts into horror expression",
|
|
132
|
+
promptHint: "the subject's face contorts into a horror expression — eyes widen and bulge, mouth stretches unnaturally wide, skin pales with visible veins emerging, jaw distending in unnatural proportions" },
|
|
133
|
+
{ id: "oni-mask", label: "Oni Mask", category: "face-expression", description: "Demon mask materializes over face",
|
|
134
|
+
promptHint: "a red and gold oni demon mask materializes and slides into place over the subject's face, painted features sharp and menacing, with curling smoke and faint magical glyphs around the edges" },
|
|
135
|
+
{ id: "glowing-eyes", label: "Glowing Eyes", category: "face-expression", description: "Eyes ignite with internal light",
|
|
136
|
+
promptHint: "the subject's eyes ignite with a brilliant internal glow — white, gold, or coloured — casting visible light beams outward and illuminating the bridge of the nose and upper cheeks" },
|
|
137
|
+
{ id: "floral-eyes", label: "Floral Eyes", category: "face-expression", description: "Flowers bloom from eye sockets",
|
|
138
|
+
promptHint: "delicate flowers bloom outward from the subject's eye sockets, petals unfurling in slow motion to replace the eyes, vines drifting down the cheeks in surreal botanical reveal" },
|
|
139
|
+
{ id: "bloom-mouth", label: "Bloom Mouth", category: "face-expression", description: "Flowers bloom from open mouth",
|
|
140
|
+
promptHint: "the subject opens their mouth and a cascade of flowers and vines blooms outward from within, unfurling in slow motion across the lower face in a surreal botanical reveal" },
|
|
141
|
+
{ id: "x-ray", label: "X-Ray Reveal", category: "face-expression", description: "Body becomes X-ray visible skeleton",
|
|
142
|
+
promptHint: "the subject's body becomes semi-transparent in X-ray style, revealing the skeletal structure beneath with a faint cyan or green glow outlining bones and major internal organs" },
|
|
143
|
+
{ id: "agent-snap", label: "Sunglasses Snap-On", category: "face-expression", description: "Sunglasses materialize over eyes",
|
|
144
|
+
promptHint: "dark sunglasses snap into place over the subject's eyes with a sharp visual punctuation — sometimes accompanied by lens flare bloom and a tight zoom on the bridge of the nose" },
|
|
145
|
+
{ id: "visor-x", label: "Cyber Visor", category: "face-expression", description: "Sci-fi cyber visor materializes",
|
|
146
|
+
promptHint: "a futuristic cybernetic visor materializes across the subject's eyes — sleek, semi-transparent with internal HUD readouts visible, faint scanline shimmer across the surface" },
|
|
147
|
+
|
|
148
|
+
// ============================================================================
|
|
149
|
+
// AURA-AMBIENT — 14 entries — environmental FX bound to the subject
|
|
150
|
+
// ============================================================================
|
|
151
|
+
{ id: "paparazzi", label: "Paparazzi Flashes", category: "aura-ambient", description: "Camera flashes pop around the subject",
|
|
152
|
+
promptHint: "the subject stands or moves while multiple camera flash bursts pop intermittently around them from off-screen photographers, each flash briefly overexposing the subject's face in white bloom" },
|
|
153
|
+
{ id: "money-rain", label: "Money Rain", category: "aura-ambient", description: "Currency rains around subject",
|
|
154
|
+
promptHint: "the subject stands or moves through a slow-motion cascade of currency notes raining down from above, bills fluttering and stacking around them, the money filling the air around the body" },
|
|
155
|
+
{ id: "color-rain", label: "Color Rain", category: "aura-ambient", description: "Brightly coloured rain around subject",
|
|
156
|
+
promptHint: "vivid brightly coloured raindrops or pigment streams fall around the subject from above, splashing on the ground and forming pools of saturated colour, the subject untouched by the cascade" },
|
|
157
|
+
{ id: "saint-glow", label: "Saint Glow", category: "aura-ambient", description: "Halo and divine glow around subject",
|
|
158
|
+
promptHint: "a soft golden halo glows behind the subject's head and warm celestial light radiates outward from the body, with faint dust motes drifting in the beams in a saintly halation" },
|
|
159
|
+
{ id: "fire-aura", label: "Fire Aura", category: "aura-ambient", description: "Flames lick around subject's body",
|
|
160
|
+
promptHint: "flames lick and curl around the subject's body without burning them, the fire wrapping the silhouette in a halo of orange and yellow tongues with heat-haze distortion in the air around" },
|
|
161
|
+
{ id: "frost-aura", label: "Frost Aura", category: "aura-ambient", description: "Frost and ice radiate from subject",
|
|
162
|
+
promptHint: "frost and ice radiate outward from the subject — surfaces around them rapidly icing over with crystalline patterns, breath visible in the cold air, faint blue-white snowflakes drifting" },
|
|
163
|
+
{ id: "shadow-aura", label: "Shadow Aura", category: "aura-ambient", description: "Dark shadow tendrils swirl around subject",
|
|
164
|
+
promptHint: "dark shadow tendrils swirl and writhe around the subject's body, the surrounding light dimming as the inky aura coils outward from the silhouette in slow undulating motion" },
|
|
165
|
+
{ id: "electricity-aura", label: "Electricity Aura", category: "aura-ambient", description: "Tesla-coil electric arcs around subject",
|
|
166
|
+
promptHint: "bright blue-white electric arcs crackle around the subject's body in branching tesla-coil patterns, jumping between extremities and the surrounding air with rhythmic strobing flashes" },
|
|
167
|
+
{ id: "sparkles-around", label: "Magical Sparkles", category: "aura-ambient", description: "Magical sparkles orbit the subject",
|
|
168
|
+
promptHint: "delicate magical sparkles and small star-shaped particles orbit and trail around the subject's body in slow-motion arcs, leaving faint light streaks in their path" },
|
|
169
|
+
{ id: "fairies-around", label: "Fairies Around", category: "aura-ambient", description: "Tiny glowing fairies flutter around subject",
|
|
170
|
+
promptHint: "tiny glowing fairies with translucent wings flutter around the subject in playful loops, each fairy leaving a faint trail of pixie-dust shimmer in their wake" },
|
|
171
|
+
{ id: "objects-orbit", label: "Objects Orbit", category: "aura-ambient", description: "Small objects float and orbit the subject",
|
|
172
|
+
promptHint: "small objects relevant to the subject — books, tools, fruits, gemstones — rise from the ground and orbit slowly around them in concentric rings of unsupported flight" },
|
|
173
|
+
{ id: "petals-around", label: "Petals Around", category: "aura-ambient", description: "Cherry blossom petals drift around subject",
|
|
174
|
+
promptHint: "soft cherry blossom petals drift gently around the subject from above, the petals catching in their hair and clothing in slow-motion pink-rose flurry" },
|
|
175
|
+
{ id: "glow-trace", label: "Glow Trace", category: "aura-ambient", description: "Light trails follow subject's motion",
|
|
176
|
+
promptHint: "bright luminous trails follow every motion of the subject's body — limbs leaving glowing afterimage streaks that fade slowly behind, creating ribbons of light tracing the choreography" },
|
|
177
|
+
{ id: "tattoo-animation", label: "Tattoo Animation", category: "aura-ambient", description: "Tattoos glow and animate on skin",
|
|
178
|
+
promptHint: "tattoos on the subject's skin begin to glow with internal light and the linework animates in slow motion — scenes within the tattoos visibly moving, ink shifting position across the body" },
|
|
179
|
+
]
|
|
180
|
+
|
|
181
|
+
export const CHARACTER_FX_CATEGORY_ORDER: ReadonlyArray<CharacterFxCategory> = [
|
|
182
|
+
"transformation", "power", "body-mod", "face-expression", "aura-ambient",
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
export const CHARACTER_FX_CATEGORY_LABELS: Readonly<Record<CharacterFxCategory, string>> = {
|
|
186
|
+
"transformation": "Transformation",
|
|
187
|
+
"power": "Power & Ability",
|
|
188
|
+
"body-mod": "Body Modification",
|
|
189
|
+
"face-expression": "Face & Expression",
|
|
190
|
+
"aura-ambient": "Aura & Ambient",
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const characterFxById = new Map<string, CharacterFx>(
|
|
194
|
+
CHARACTER_FX.map((c) => [c.id, c]),
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
export function getCharacterFx(id: string | undefined | null): CharacterFx | undefined {
|
|
198
|
+
if (!id) return undefined
|
|
199
|
+
return characterFxById.get(id)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export function getCharacterFxLabel(id: string | undefined | null, fallback?: string): string {
|
|
203
|
+
const c = getCharacterFx(id)
|
|
204
|
+
if (c) return c.label
|
|
205
|
+
if (fallback !== undefined) return fallback
|
|
206
|
+
return (id ?? "").replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function getCharacterFxPromptHint(id: string | undefined | null): string {
|
|
210
|
+
return getCharacterFx(id)?.promptHint ?? ""
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export const CHARACTER_FX_IDS: ReadonlyArray<string> = CHARACTER_FX.map((c) => c.id)
|
|
214
|
+
|
|
215
|
+
// ---------------------------------------------------------------------------
|
|
216
|
+
// Graph-aware composer — target input handle + timing fields + multi-pick
|
|
217
|
+
// ---------------------------------------------------------------------------
|
|
218
|
+
|
|
219
|
+
const POSITION_CLAUSES: Record<Exclude<CharacterFxPosition, "auto">, string> = {
|
|
220
|
+
start: "the effect occurs at the opening of the clip",
|
|
221
|
+
middle: "the effect occurs in the middle of the clip",
|
|
222
|
+
end: "the effect occurs at the end of the clip",
|
|
223
|
+
full: "the effect persists for the entire clip",
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const DURATION_CLAUSES: Record<Exclude<CharacterFxDuration, "auto">, string> = {
|
|
227
|
+
instant: "manifesting instantaneously",
|
|
228
|
+
short: "manifesting over approximately 1 second",
|
|
229
|
+
medium: "manifesting over approximately 2 seconds",
|
|
230
|
+
long: "manifesting over approximately 3 seconds",
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const INTENSITY_CLAUSES: Record<Exclude<CharacterFxIntensity, "auto">, string> = {
|
|
234
|
+
subtle: "with subtle restrained energy and minimal flourish",
|
|
235
|
+
natural: "with natural unhurried timing",
|
|
236
|
+
dynamic: "with dynamic energy and assertive flourish",
|
|
237
|
+
crazy: "with extreme exaggerated energy, wild flourishes, and dramatic distortion",
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Compose a character-fx prompt-hint sentence from an effect id (or array
|
|
242
|
+
* of 1-2 ids for multi-pick) plus target-ref display names (from upstream
|
|
243
|
+
* character/face/object/location nodes wired to the `target` handle) plus
|
|
244
|
+
* optional timing fields.
|
|
245
|
+
*
|
|
246
|
+
* Substitution: each base hint has every `"the subject"` occurrence
|
|
247
|
+
* rewritten to the target name BEFORE the join. Empty targetHints leaves
|
|
248
|
+
* "the subject" intact in the prompt.
|
|
249
|
+
*/
|
|
250
|
+
export function composeCharacterFxHintFromConnections(
|
|
251
|
+
effectId: string | ReadonlyArray<string> | undefined,
|
|
252
|
+
targetHints: ReadonlyArray<string>,
|
|
253
|
+
timing?: CharacterFxTiming,
|
|
254
|
+
): string {
|
|
255
|
+
const ids = Array.isArray(effectId)
|
|
256
|
+
? Array.from(new Set(effectId)).slice(0, 2)
|
|
257
|
+
: effectId ? [effectId] : []
|
|
258
|
+
const baseHints = ids.map(getCharacterFxPromptHint).filter((h) => h.length > 0)
|
|
259
|
+
if (baseHints.length === 0) return ""
|
|
260
|
+
|
|
261
|
+
const targetClause = targetHints.filter((h) => h && h.length > 0).join(" and ")
|
|
262
|
+
const substituted = targetClause
|
|
263
|
+
? baseHints.map((b) => b.replace(/\bthe subject\b/g, targetClause))
|
|
264
|
+
: baseHints
|
|
265
|
+
|
|
266
|
+
const combinedBase = substituted.join(", and ")
|
|
267
|
+
const parts: string[] = [combinedBase]
|
|
268
|
+
|
|
269
|
+
if (timing?.position && timing.position !== "auto") parts.push(POSITION_CLAUSES [timing.position])
|
|
270
|
+
if (timing?.duration && timing.duration !== "auto") parts.push(DURATION_CLAUSES [timing.duration])
|
|
271
|
+
if (timing?.intensity && timing.intensity !== "auto") parts.push(INTENSITY_CLAUSES[timing.intensity])
|
|
272
|
+
|
|
273
|
+
return parts.join(", ")
|
|
274
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical catalog of color/look choices.
|
|
3
|
+
*
|
|
4
|
+
* Color/look is a multi-category dimension of a shot — it covers both
|
|
5
|
+
* stylistic color palettes (warm, cool, teal-orange, etc.) and film-stock
|
|
6
|
+
* emulations (Kodak Portra, Cinestill 800T, bleach bypass, etc.). Independent
|
|
7
|
+
* of optics (lens), framing, camera motion, capture medium (camera-format),
|
|
8
|
+
* and lighting setup.
|
|
9
|
+
*
|
|
10
|
+
* Shared between the picker UI and the prompt-hint injection on both the
|
|
11
|
+
* frontend DAG executor and the backend orchestrator.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export type ColorLookCategory = "palette" | "film-emulation" | "social-preset"
|
|
15
|
+
|
|
16
|
+
export interface ColorLook {
|
|
17
|
+
readonly id: string
|
|
18
|
+
readonly label: string
|
|
19
|
+
readonly category: ColorLookCategory
|
|
20
|
+
readonly description: string
|
|
21
|
+
readonly promptHint: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const COLOR_LOOKS: ReadonlyArray<ColorLook> = [
|
|
25
|
+
// Palette (13)
|
|
26
|
+
{ id: "warm", label: "Warm", category: "palette", description: "Warm orange/red tones", promptHint: "warm color palette, orange and red tones throughout the image with golden highlights" },
|
|
27
|
+
{ id: "cool", label: "Cool", category: "palette", description: "Cool blue/teal tones", promptHint: "cool color palette, blue and teal tones throughout the image with subdued warm accents" },
|
|
28
|
+
{ id: "teal-orange", label: "Teal & Orange", category: "palette", description: "Hollywood complementary grade", promptHint: "teal and orange color grade, warm skin tones against cool teal shadows, Hollywood blockbuster look" },
|
|
29
|
+
{ id: "split-toning", label: "Split Toning", category: "palette", description: "Cool shadows, warm highlights", promptHint: "split-toning color grade, cool blue-green tinted shadows paired with warm amber highlights, nuanced tonal separation distinct from a flat teal-orange wash" },
|
|
30
|
+
{ id: "selective-color", label: "Selective Color", category: "palette", description: "B&W with one accent color", promptHint: "selective color treatment, image rendered nearly monochromatic black-and-white with a single accent hue (such as red lipstick or a red dress) preserved in full saturation against the desaturated frame" },
|
|
31
|
+
{ id: "faded-matte", label: "Faded Matte", category: "palette", description: "Lifted blacks, milky low-contrast", promptHint: "faded matte color grade, lifted blacks and milky low-contrast shadows with soft hazy highlights, flat Instagram-soft aesthetic with reduced dynamic range" },
|
|
32
|
+
{ id: "log-flat", label: "Log Flat", category: "palette", description: "Pre-grade S-Log/V-Log neutral", promptHint: "log-flat ungraded footage look, washed-out neutral S-Log or V-Log appearance with low contrast and desaturated muddy mids before any creative color grading is applied" },
|
|
33
|
+
{ id: "desaturated", label: "Desaturated", category: "palette", description: "Low saturation, muted", promptHint: "desaturated color grading, muted low-saturation tones throughout, almost monochromatic feel" },
|
|
34
|
+
{ id: "monochrome-bw", label: "Monochrome B&W", category: "palette", description: "Pure black and white", promptHint: "monochrome black and white, pure grayscale image with no color information" },
|
|
35
|
+
{ id: "sepia", label: "Sepia", category: "palette", description: "Vintage brown tone", promptHint: "sepia toned image, warm brown vintage monochrome with classic photographic feel" },
|
|
36
|
+
{ id: "pastel", label: "Pastel", category: "palette", description: "Soft, low-contrast pastels", promptHint: "pastel color palette, soft low-contrast pastel hues with light airy tones" },
|
|
37
|
+
{ id: "high-contrast", label: "High Contrast", category: "palette", description: "Punchy contrast, deep blacks", promptHint: "high contrast color grade, punchy saturated colors with crushed deep blacks and bright highlights" },
|
|
38
|
+
{ id: "vibrant", label: "Vibrant", category: "palette", description: "Highly saturated colors", promptHint: "vibrant saturated color palette, bold rich colors with high saturation throughout" },
|
|
39
|
+
|
|
40
|
+
// Film emulation (13)
|
|
41
|
+
{ id: "kodak-portra", label: "Kodak Portra", category: "film-emulation", description: "Soft skin tones, fine grain", promptHint: "Kodak Portra film stock emulation, soft natural skin tones with fine grain and gentle pastel color rendering" },
|
|
42
|
+
{ id: "kodak-ektar", label: "Kodak Ektar", category: "film-emulation", description: "Saturated, fine grain", promptHint: "Kodak Ektar film stock emulation, ultra-saturated colors with fine grain and high color contrast" },
|
|
43
|
+
{ id: "kodak-vision3", label: "Kodak Vision3", category: "film-emulation", description: "Cinema motion picture stock", promptHint: "Kodak Vision3 motion picture film emulation, cinematic warm color rendering with smooth highlight rolloff" },
|
|
44
|
+
{ id: "fuji-pro-400h", label: "Fuji Pro 400H", category: "film-emulation", description: "Pastel greens and skies", promptHint: "Fuji Pro 400H film stock emulation, soft pastel greens and creamy blue skies with gentle warm skin tones" },
|
|
45
|
+
{ id: "cinestill-800t", label: "Cinestill 800T", category: "film-emulation", description: "Tungsten film with red halation", promptHint: "Cinestill 800T film stock emulation, tungsten-balanced color with characteristic red halation around highlights" },
|
|
46
|
+
{ id: "bleach-bypass", label: "Bleach Bypass", category: "film-emulation", description: "High contrast, desaturated", promptHint: "bleach bypass processing, high contrast with desaturated colors and silver-retention metallic look" },
|
|
47
|
+
{ id: "technicolor", label: "Technicolor 3-strip", category: "film-emulation", description: "Vivid retro Technicolor", promptHint: "Technicolor 3-strip emulation, vivid saturated red/green/blue color separation with classic Hollywood golden-age look" },
|
|
48
|
+
{ id: "two-strip-technicolor", label: "Two-Strip Technicolor", category: "film-emulation", description: "1920s-30s red-blue Technicolor", promptHint: "two-strip Technicolor emulation, archaic 1920s and 1930s red-and-blue-only color process with limited green range, dusty rose reds against cyan blues, period-piece early-Hollywood feel distinct from later three-strip" },
|
|
49
|
+
{ id: "eastman-color", label: "Eastman Color", category: "film-emulation", description: "1950s/60s warm faded stock", promptHint: "Eastman Color film stock emulation, mid-century 1950s and 1960s motion-picture color with slightly faded warm tonality, gentle red shift, soft contrast and the muted-pastel quality of aged Hollywood prints" },
|
|
50
|
+
{ id: "hand-tinted", label: "Hand-Tinted", category: "film-emulation", description: "B&W with hand-painted color", promptHint: "hand-tinted photograph aesthetic, base black-and-white image with hand-painted color accents applied selectively to lips, cheeks, garments and props, painterly translucent washes of pigment over the monochrome plate" },
|
|
51
|
+
{ id: "agfa-orwo", label: "Agfa / ORWO", category: "film-emulation", description: "Eastern European cool greens", promptHint: "Agfa or ORWO film stock emulation, Eastern European film with cool muted greens, amber-leaning skin tones, slightly desaturated mids and a distinctive socialist-era documentary feel" },
|
|
52
|
+
{ id: "day-for-night", label: "Day-for-Night", category: "film-emulation", description: "Daylight graded as night", promptHint: "day-for-night color grading, daylight footage graded with deep blue tones and crushed shadows to simulate moonlit night" },
|
|
53
|
+
{ id: "cross-processed", label: "Cross-Processed", category: "film-emulation", description: "Color shifts from xpro", promptHint: "cross-processed film look, slide film developed in print chemistry causing surreal color shifts and pushed contrast" },
|
|
54
|
+
{ id: "kodachrome-64", label: "Kodachrome 64", category: "film-emulation", description: "Saturated reds, golden warmth", promptHint: "graded with a Kodachrome 64 film palette, saturated reds and amber highlights with rich blue shadows, the classic National Geographic warmth and vintage slide-film signature with deep tonal density" },
|
|
55
|
+
{ id: "ektachrome-100", label: "Ektachrome 100", category: "film-emulation", description: "Cool clean blues, slide clarity", promptHint: "Ektachrome 100 slide film emulation, clean cool blues with a subtle magenta cast, crisp transparency-film clarity and natural daylight color rendition with fine grain and a slightly cyan-leaning neutral tonality" },
|
|
56
|
+
{ id: "kodak-tri-x-400", label: "Kodak Tri-X 400 (B&W)", category: "film-emulation", description: "Pushed-grain B&W reportage", promptHint: "Kodak Tri-X 400 black-and-white film emulation, pushed-grain monochrome with gritty high contrast, deep blacks and bright highlights, classic 35mm street-photography and reportage feel with visible silver grain texture" },
|
|
57
|
+
{ id: "aerochrome", label: "Aerochrome / Color Infrared", category: "film-emulation", description: "Surreal pink-magenta foliage", promptHint: "Aerochrome color infrared film emulation, surreal false-color landscape where vegetation glows in vivid pink and magenta, blue skies stay deep, and foliage appears otherworldly hot-pink and crimson — distinctive infrared-sensitive emulsion signature" },
|
|
58
|
+
{ id: "fuji-instax", label: "Fuji Instax / Instant Film", category: "film-emulation", description: "Soft pastel instant-film", promptHint: "Fuji Instax instant film emulation, soft pastel midtones with a slight cool blue cast, gentle low-contrast rendering, square-format Polaroid-alternative aesthetic with creamy whites and dreamy diffuse color" },
|
|
59
|
+
{ id: "cinestill-50d", label: "Cinestill 50D", category: "film-emulation", description: "Daylight cinema stock", promptHint: "Cinestill 50D daylight-balanced cinema film emulation, controlled cool blues with creamy skin tones and fine grain, Christopher Doyle and Wong Kar-wai daylight-cinema aesthetic with smooth highlight rolloff and natural color separation" },
|
|
60
|
+
{ id: "expired-film", label: "Expired Film / Light-struck", category: "film-emulation", description: "Color shifts and light leaks", promptHint: "expired film and light-struck aesthetic, unpredictable color shifts with overexposed magenta and amber casts, visible light leaks and fogged edges, found-film degradation feel with elevated grain and unstable shifting hues" },
|
|
61
|
+
|
|
62
|
+
// Social-preset (modern social-video aesthetics — distinct from analog film emulations)
|
|
63
|
+
{ id: "instagram-warm", label: "Instagram Warm", category: "social-preset", description: "Valencia-style warm filter", promptHint: "Instagram-style warm filter aesthetic, slightly faded warm highlights with creamy mid-tones, Valencia-preset feel" },
|
|
64
|
+
{ id: "tiktok-saturated", label: "TikTok Saturated", category: "social-preset", description: "Bright punchy social palette", promptHint: "TikTok-style oversaturated bright palette, punchy reds and blues with high contrast and vivid skin tones" },
|
|
65
|
+
{ id: "youtube-vlog-flat", label: "YouTube Vlog Flat", category: "social-preset", description: "Clean vlog flat grade", promptHint: "YouTube vlog clean flat color grade, neutral natural color rendition with even skin tones and pleasant ambient" },
|
|
66
|
+
{ id: "iphone-hdr", label: "iPhone HDR", category: "social-preset", description: "Computational HDR look", promptHint: "iPhone computational HDR look with extended highlight range, lifted shadows, and slightly hyperreal local-contrast enhancement" },
|
|
67
|
+
{ id: "y2k-saturated", label: "Y2K Saturated", category: "social-preset", description: "Early-2000s digital pop", promptHint: "Y2K early-2000s digital saturation aesthetic, electric magenta and cyan punch, glossy compact-camera color, candy-bright primaries with a slightly crunchy CCD-sensor digital sharpness" },
|
|
68
|
+
{ id: "mtv-90s-vhs", label: "MTV 90s VHS", category: "social-preset", description: "Oversaturated 90s VHS chroma", promptHint: "MTV 1990s VHS aesthetic, oversaturated cast with chroma bleed and color smearing, blown-out reds and electric blues, lo-fi tape-era saturation distinct from cleaner film emulations" },
|
|
69
|
+
{ id: "polaroid-faded", label: "Polaroid Faded", category: "social-preset", description: "Magenta-tinted faded Polaroid", promptHint: "faded vintage Polaroid aesthetic, washed-out magenta and pink color cast, lifted milky shadows, yellowed highlights and the soft instant-film degradation of an aged SX-70 print, distinct from Kodak Portra negative-film emulation" },
|
|
70
|
+
{ id: "lifestyle-warm-magazine", label: "Lifestyle Warm Magazine", category: "social-preset", description: "Modern warm editorial grade", promptHint: "modern lifestyle magazine warm-leaning grade, creamy honeyed highlights, gently warmed skin tones, soft golden mids and clean neutral shadows, contemporary editorial commercial aesthetic for fashion and food photography" },
|
|
71
|
+
] as const
|
|
72
|
+
|
|
73
|
+
export const COLOR_LOOK_CATEGORY_ORDER: ReadonlyArray<ColorLookCategory> = [
|
|
74
|
+
"palette",
|
|
75
|
+
"film-emulation",
|
|
76
|
+
"social-preset",
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
export const COLOR_LOOK_CATEGORY_LABELS: Record<ColorLookCategory, string> = {
|
|
80
|
+
palette: "Palette",
|
|
81
|
+
"film-emulation": "Film Emulation",
|
|
82
|
+
"social-preset": "Social Preset",
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const colorLookById = new Map<string, ColorLook>(COLOR_LOOKS.map((c) => [c.id, c]))
|
|
86
|
+
|
|
87
|
+
export function getColorLook(id: string | undefined | null): ColorLook | undefined {
|
|
88
|
+
if (!id) return undefined
|
|
89
|
+
return colorLookById.get(id)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function getColorLookLabel(id: string | undefined | null, fallback?: string): string {
|
|
93
|
+
const c = getColorLook(id)
|
|
94
|
+
if (c) return c.label
|
|
95
|
+
if (fallback !== undefined) return fallback
|
|
96
|
+
return (id ?? "").replace(/-/g, " ").replace(/\b\w/g, (ch) => ch.toUpperCase())
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function getColorLookPromptHint(id: string | undefined | null): string {
|
|
100
|
+
return getColorLook(id)?.promptHint ?? ""
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export const COLOR_LOOK_IDS: ReadonlyArray<string> = COLOR_LOOKS.map((c) => c.id)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical catalog of Composition Effects choices.
|
|
3
|
+
*
|
|
4
|
+
* Composition Effects describe a "compositional trick" applied to the subject
|
|
5
|
+
* — how the subject interacts with the canvas/frame, what material it's made
|
|
6
|
+
* of, or what compositional gimmick frames it. This is distinct from the post-
|
|
7
|
+
* processing image grade (Post-Process Effects) and from the artistic style
|
|
8
|
+
* (Style): an "exploding particles" composition effect can be applied to an
|
|
9
|
+
* oil painting style or a photorealistic style equally well.
|
|
10
|
+
*
|
|
11
|
+
* Single-pick — only one composition trick is applied per consumer. Pure
|
|
12
|
+
* prompt text, zero credits, zero API calls.
|
|
13
|
+
*
|
|
14
|
+
* Shared between picker UI and prompt-hint injection in the frontend DAG
|
|
15
|
+
* executor and the backend orchestrator.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export interface CompositionEffect {
|
|
19
|
+
readonly id: string
|
|
20
|
+
readonly label: string
|
|
21
|
+
readonly description: string
|
|
22
|
+
readonly promptHint: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const COMPOSITION_EFFECTS: ReadonlyArray<CompositionEffect> = [
|
|
26
|
+
{ id: "bursting-through-frame", label: "Bursting Through Frame", description: "3D paper-tear breaking the frame", promptHint: "the subject bursting forward through a torn paper frame in a 3D paper-tear effect, head and shoulders breaking the plane of the canvas with ragged paper edges curling outward" },
|
|
27
|
+
{ id: "breaking-out-of-frame", label: "Breaking Out of Frame", description: "Limb extends past canvas border", promptHint: "the subject's hand or limb extending past the canvas border, breaking the fourth wall and reaching beyond the frame's edge into the viewer's space" },
|
|
28
|
+
{ id: "pixel-disintegration", label: "Pixel Disintegration", description: "Subject dissolving into particles", promptHint: "the subject pixelating and dissolving into floating geometric particles drifting outward, ordered chaos with crisp pixel-cube fragments scattering away from the silhouette" },
|
|
29
|
+
{ id: "smoke-sculpture", label: "Smoke Sculpture", description: "Subject formed from swirling smoke", promptHint: "the subject formed entirely of swirling smoke, ethereal greyscale mass holding human shape with wispy tendrils trailing off and dissolving at the edges" },
|
|
30
|
+
{ id: "liquid-sculpture", label: "Liquid Sculpture", description: "Subject formed from flowing liquid", promptHint: "the subject formed entirely of flowing water and liquid, ripples and reflections traveling through the form with droplets suspended around the silhouette" },
|
|
31
|
+
{ id: "shattering-glass", label: "Shattering Glass", description: "Frozen glass shards mid-flight", promptHint: "the subject framed behind shattering glass with fragments mid-flight, motion frozen at the moment of impact, splintered cracks radiating outward and shards catching the light" },
|
|
32
|
+
{ id: "emerging-from-background", label: "Emerging From Background", description: "Half-emerging from a textured surface", promptHint: "the subject half-emerging out of a textured background, partially integrated into the surface as if pushing through wet plaster or relief sculpture, body and background sharing material" },
|
|
33
|
+
{ id: "fragmented-mosaic", label: "Fragmented Mosaic", description: "Portrait built from mosaic tiles", promptHint: "the subject's portrait composed of small mosaic tiles, fragmented yet unmistakably recognizable with grout lines between each ceramic-like fragment forming the larger image" },
|
|
34
|
+
{ id: "glitch-distortion", label: "Glitch Distortion", description: "RGB-shift digital corruption", promptHint: "the subject distorted by digital glitch artifacts with RGB channel separation, scanline tearing and datamoshed compression bands cutting horizontally across the figure" },
|
|
35
|
+
{ id: "doubled-mirror", label: "Doubled Mirror", description: "Mirror-reflected duplication", promptHint: "the subject duplicated in mirror reflections, multiplied identity with two or more echoed versions of the figure stitched along an invisible mirror seam" },
|
|
36
|
+
{ id: "floating-fragments", label: "Floating Fragments", description: "Body partially drifting away", promptHint: "the subject's body partially floating away in fragments, broken pieces of the figure detaching and drifting upward like windborne paper, leaving a partially dissolved silhouette" },
|
|
37
|
+
{ id: "silhouette-outline", label: "Silhouette Outline", description: "Clean black silhouette on flat BG", promptHint: "the subject reduced to a clean black silhouette outline against a flat single-color background, no internal detail, pure shape language" },
|
|
38
|
+
{ id: "exploding-particles", label: "Exploding Particles", description: "Outline scattering into particles", promptHint: "the subject's outline exploding outward into a cloud of fine particles, dust and motes scattering radially around a partially intact core figure" },
|
|
39
|
+
{ id: "3x3-grid-collage", label: "3x3 Grid Collage", description: "Contact-sheet 9-pose montage", promptHint: "the subject shown in a 3x3 grid of varied poses and expressions arranged as a contact-sheet collage, nine clean panels with consistent lighting and slight pose variation in each cell" },
|
|
40
|
+
{ id: "matte-painting", label: "Matte Painting", description: "Composite matte-painted background blended with live action, classic VFX", promptHint: "the subject composited against a matte-painted background blended seamlessly with live action, classic VFX matte-painting integration with hand-painted environment extension behind the figure" },
|
|
41
|
+
{ id: "double-exposure", label: "Double Exposure", description: "Two layered photographic exposures fused into one image", promptHint: "two layered photographic exposures fused into one image, the subject's silhouette filled with a secondary scene and translucent overlapping forms in classic darkroom double-exposure technique" },
|
|
42
|
+
{ id: "multiple-exposure", label: "Multiple Exposure", description: "Three or more exposures stacked, kaleidoscopic layering", promptHint: "three or more photographic exposures stacked into a single frame, kaleidoscopic layering of repeated subject positions with translucent overlapping silhouettes echoing across the canvas" },
|
|
43
|
+
{ id: "in-camera-effects", label: "In-Camera Effects", description: "Practical in-camera optical effects, no post-production", promptHint: "practical in-camera optical effects with no post-production trickery, real-world prisms, mirrors and lens-mounted gels creating the visual treatment directly at capture" },
|
|
44
|
+
{ id: "prism-flares", label: "Prism Flares", description: "Crystal prism refracted light flares splitting into spectral bands", promptHint: "crystal prism refracted light flares splitting into spectral bands across the frame, rainbow chromatic streaks fanning outward from highlights with prismatic color separation" },
|
|
45
|
+
] as const
|
|
46
|
+
|
|
47
|
+
const compositionEffectById = new Map<string, CompositionEffect>(
|
|
48
|
+
COMPOSITION_EFFECTS.map((c) => [c.id, c]),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
export function getCompositionEffect(id: string | undefined | null): CompositionEffect | undefined {
|
|
52
|
+
if (!id) return undefined
|
|
53
|
+
return compositionEffectById.get(id)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function getCompositionEffectLabel(id: string | undefined | null, fallback?: string): string {
|
|
57
|
+
const c = getCompositionEffect(id)
|
|
58
|
+
if (c) return c.label
|
|
59
|
+
if (fallback !== undefined) return fallback
|
|
60
|
+
return (id ?? "").replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function getCompositionEffectPromptHint(id: string | undefined | null): string {
|
|
64
|
+
return getCompositionEffect(id)?.promptHint ?? ""
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const COMPOSITION_EFFECT_IDS: ReadonlyArray<string> = COMPOSITION_EFFECTS.map((c) => c.id)
|