@nodaro/prompts 1.7.3 → 1.8.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/dist/index.cjs +5443 -4295
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1202 -61
- package/dist/index.d.ts +1202 -61
- package/dist/index.js +5357 -4297
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/b7-person-pack-e2e.test.ts +37 -0
- package/src/__tests__/catalog-funnel-ratchet.test.ts +97 -0
- package/src/__tests__/catalog-packs.test.ts +130 -0
- package/src/__tests__/catalog-sidecar-coverage.test.ts +27 -0
- package/src/__tests__/catalog-terms.test.ts +162 -0
- package/src/__tests__/character-default-role.test.ts +3 -2
- package/src/__tests__/content-free-contract.test.ts +45 -0
- package/src/__tests__/dod-replace-pack-acceptance.test.ts +41 -0
- package/src/__tests__/fixtures/parameter-hint-golden.json +2959 -0
- package/src/__tests__/fixtures/person-sector-pack.ts +27 -0
- package/src/__tests__/i18n-entry-completeness.test.ts +5 -2
- package/src/__tests__/parameter-hint-mode.test.ts +385 -0
- package/src/__tests__/parameter-prompt-hint-pack-fallback.test.ts +25 -0
- package/src/__tests__/person-packs.test.ts +166 -0
- package/src/__tests__/project-all-catalogs.test.ts +26 -0
- package/src/__tests__/prompt-builder.test.ts +53 -0
- package/src/__tests__/provider-prompt-doctrine.test.ts +18 -0
- package/src/__tests__/registered-catalogs-funnel.test.ts +30 -0
- package/src/__tests__/registered-catalogs-guard.test.ts +11 -0
- package/src/__tests__/term.test.ts +104 -0
- package/src/__tests__/transitions.test.ts +8 -5
- package/src/__tests__/upstream-immutability.test.ts +23 -0
- package/src/action-fx.ts +67 -17
- package/src/aesthetic.ts +54 -6
- package/src/atmosphere.ts +64 -23
- package/src/backdrop.ts +44 -30
- package/src/camera-format.ts +33 -11
- package/src/camera-motions.ts +89 -0
- package/src/catalog-packs.ts +125 -0
- package/src/catalog-sidecar-coverage.ts +36 -0
- package/src/character-fx.ts +112 -39
- package/src/color-look.ts +44 -27
- package/src/composition-effects.ts +21 -7
- package/src/era.ts +24 -0
- package/src/exposure-settings.ts +76 -18
- package/src/framing.ts +102 -10
- package/src/held-prop.ts +125 -63
- package/src/identity-lock.ts +12 -5
- package/src/image-reference-doctrine.ts +55 -0
- package/src/index.ts +5 -0
- package/src/instrumentation.ts +148 -57
- package/src/lens.ts +31 -15
- package/src/lighting.ts +120 -59
- package/src/loop-subject.ts +27 -1
- package/src/materials.ts +123 -69
- package/src/mood.ts +123 -51
- package/src/music-genre.ts +171 -67
- package/src/music-mood.ts +85 -17
- package/src/parameter-prompt-hint.ts +168 -56
- package/src/person-packs.ts +182 -0
- package/src/person.ts +506 -408
- package/src/photo-genre.ts +37 -22
- package/src/photographer.ts +138 -1
- package/src/picker-catalogs.ts +86 -40
- package/src/pose.ts +105 -40
- package/src/post-process-effects.ts +51 -8
- package/src/prompt-builder.ts +16 -1
- package/src/provider-prompt-doctrine.ts +12 -5
- package/src/render-quality.ts +25 -7
- package/src/setting.ts +30 -14
- package/src/style.ts +33 -15
- package/src/styling.ts +155 -94
- package/src/temporal.ts +80 -18
- package/src/term.ts +155 -0
- package/src/transitions.ts +73 -26
- package/src/voice-character.ts +190 -90
- package/src/voice-delivery.ts +83 -12
package/src/character-fx.ts
CHANGED
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
* null input is treated like undefined (falsy short-circuit → returns "")
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
import { resolveTerm, type PickerHintMode } from "./term.js"
|
|
22
|
+
|
|
21
23
|
export type CharacterFxCategory =
|
|
22
24
|
| "transformation"
|
|
23
25
|
| "power"
|
|
@@ -31,6 +33,8 @@ export interface CharacterFx {
|
|
|
31
33
|
readonly category: CharacterFxCategory
|
|
32
34
|
readonly description: string
|
|
33
35
|
readonly promptHint: string
|
|
36
|
+
/** Optional authored compact term (see `term.ts` for the convention). */
|
|
37
|
+
readonly term?: string
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
export type CharacterFxPosition = "auto" | "start" | "middle" | "end" | "full"
|
|
@@ -51,37 +55,48 @@ export const CHARACTER_FX: ReadonlyArray<CharacterFx> = [
|
|
|
51
55
|
{ id: "auto", label: "Auto", category: "transformation", description: "Let the model choose", promptHint: "" },
|
|
52
56
|
{ id: "none", label: "None", category: "transformation", description: "No character effect", promptHint: "" },
|
|
53
57
|
{ 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"
|
|
58
|
+
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",
|
|
59
|
+
term: "werewolf transformation" },
|
|
55
60
|
{ 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"
|
|
61
|
+
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",
|
|
62
|
+
term: "vampire transformation" },
|
|
57
63
|
{ id: "cyborg", label: "Cyborg Reveal", category: "transformation", description: "Skin peels back revealing cybernetics",
|
|
58
64
|
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
65
|
{ id: "ghost-form", label: "Ghost Form", category: "transformation", description: "Body becomes translucent / ethereal",
|
|
60
66
|
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
67
|
{ 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"
|
|
68
|
+
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",
|
|
69
|
+
term: "stone petrification" },
|
|
63
70
|
{ 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)"
|
|
71
|
+
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)",
|
|
72
|
+
term: "liquid metal morph" },
|
|
65
73
|
{ 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"
|
|
74
|
+
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",
|
|
75
|
+
term: "animal transformation" },
|
|
67
76
|
{ 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"
|
|
77
|
+
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",
|
|
78
|
+
term: "gorilla transformation" },
|
|
69
79
|
{ 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"
|
|
80
|
+
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",
|
|
81
|
+
term: "magical aura transformation" },
|
|
71
82
|
{ id: "gas-form", label: "Gas Transformation", category: "transformation", description: "Body dissipates into gaseous form",
|
|
72
83
|
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
84
|
{ 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"
|
|
85
|
+
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",
|
|
86
|
+
term: "skin crystallizing into diamond" },
|
|
75
87
|
{ 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)"
|
|
88
|
+
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)",
|
|
89
|
+
term: "black suit and sunglasses materializing" },
|
|
77
90
|
|
|
78
91
|
// ============================================================================
|
|
79
92
|
// POWER — 12 entries — subject demonstrates a fantastical ability
|
|
80
93
|
// ============================================================================
|
|
81
94
|
{ 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"
|
|
95
|
+
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",
|
|
96
|
+
term: "fire breathing" },
|
|
83
97
|
{ 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"
|
|
98
|
+
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",
|
|
99
|
+
term: "ice breath" },
|
|
85
100
|
{ id: "air-bending", label: "Air Bending", category: "power", description: "Manipulates a swirling vortex of air",
|
|
86
101
|
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
102
|
{ id: "water-bending", label: "Water Bending", category: "power", description: "Manipulates flowing water with gestures",
|
|
@@ -89,7 +104,8 @@ export const CHARACTER_FX: ReadonlyArray<CharacterFx> = [
|
|
|
89
104
|
{ id: "earth-bending", label: "Earth Bending", category: "power", description: "Raises stone slabs from the ground",
|
|
90
105
|
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
106
|
{ 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"
|
|
107
|
+
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",
|
|
108
|
+
term: "electric arcs from the hands" },
|
|
93
109
|
{ id: "levitation", label: "Levitation", category: "power", description: "Rises off the ground, body horizontal or vertical",
|
|
94
110
|
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
111
|
{ id: "telekinesis", label: "Telekinesis", category: "power", description: "Nearby objects float and orbit",
|
|
@@ -97,51 +113,66 @@ export const CHARACTER_FX: ReadonlyArray<CharacterFx> = [
|
|
|
97
113
|
{ id: "invisibility", label: "Invisibility", category: "power", description: "Body fades to transparent / refractive",
|
|
98
114
|
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
115
|
{ 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"
|
|
116
|
+
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",
|
|
117
|
+
term: "superhero flight takeoff" },
|
|
101
118
|
{ id: "super-speed", label: "Super Speed", category: "power", description: "Blurs into super-fast motion",
|
|
102
119
|
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
120
|
{ 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"
|
|
121
|
+
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",
|
|
122
|
+
term: "soul leaving the body" },
|
|
105
123
|
|
|
106
124
|
// ============================================================================
|
|
107
125
|
// BODY-MOD — 9 entries — parts of the subject change / emerge / leave
|
|
108
126
|
// ============================================================================
|
|
109
127
|
{ 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"
|
|
128
|
+
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",
|
|
129
|
+
term: "wings unfurling from the back" },
|
|
111
130
|
{ 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"
|
|
131
|
+
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",
|
|
132
|
+
term: "horns growing from the head" },
|
|
113
133
|
{ 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"
|
|
134
|
+
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",
|
|
135
|
+
term: "tail growing from the spine" },
|
|
115
136
|
{ 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"
|
|
137
|
+
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",
|
|
138
|
+
term: "tentacles writhing from the back" },
|
|
117
139
|
{ 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"
|
|
140
|
+
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",
|
|
141
|
+
term: "extra eyes opening on the face" },
|
|
119
142
|
{ 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"
|
|
143
|
+
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",
|
|
144
|
+
term: "stylized head explosion" },
|
|
121
145
|
{ 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"
|
|
146
|
+
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",
|
|
147
|
+
term: "stylized head detachment" },
|
|
123
148
|
{ 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"
|
|
149
|
+
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",
|
|
150
|
+
term: "spiders crawling from the mouth" },
|
|
125
151
|
{ 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"
|
|
152
|
+
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",
|
|
153
|
+
term: "skin rippling with movement underneath" },
|
|
127
154
|
|
|
128
155
|
// ============================================================================
|
|
129
156
|
// FACE-EXPRESSION — 8 entries — face contorts / mask / eyes change
|
|
130
157
|
// ============================================================================
|
|
131
158
|
{ 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"
|
|
159
|
+
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",
|
|
160
|
+
term: "contorted horror expression" },
|
|
133
161
|
{ id: "oni-mask", label: "Oni Mask", category: "face-expression", description: "Demon mask materializes over face",
|
|
134
162
|
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
163
|
{ id: "glowing-eyes", label: "Glowing Eyes", category: "face-expression", description: "Eyes ignite with internal light",
|
|
136
164
|
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
165
|
{ 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"
|
|
166
|
+
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",
|
|
167
|
+
term: "flowers blooming from the eyes" },
|
|
139
168
|
{ 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"
|
|
169
|
+
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",
|
|
170
|
+
term: "flowers blooming from the mouth" },
|
|
141
171
|
{ id: "x-ray", label: "X-Ray Reveal", category: "face-expression", description: "Body becomes X-ray visible skeleton",
|
|
142
172
|
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
173
|
{ 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"
|
|
174
|
+
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",
|
|
175
|
+
term: "sunglasses snapping onto the face" },
|
|
145
176
|
{ id: "visor-x", label: "Cyber Visor", category: "face-expression", description: "Sci-fi cyber visor materializes",
|
|
146
177
|
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
178
|
|
|
@@ -153,9 +184,11 @@ export const CHARACTER_FX: ReadonlyArray<CharacterFx> = [
|
|
|
153
184
|
{ id: "money-rain", label: "Money Rain", category: "aura-ambient", description: "Currency rains around subject",
|
|
154
185
|
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
186
|
{ 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"
|
|
187
|
+
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",
|
|
188
|
+
term: "brightly coloured rain" },
|
|
157
189
|
{ 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"
|
|
190
|
+
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",
|
|
191
|
+
term: "golden halo and divine glow" },
|
|
159
192
|
{ id: "fire-aura", label: "Fire Aura", category: "aura-ambient", description: "Flames lick around subject's body",
|
|
160
193
|
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
194
|
{ id: "frost-aura", label: "Frost Aura", category: "aura-ambient", description: "Frost and ice radiate from subject",
|
|
@@ -163,19 +196,25 @@ export const CHARACTER_FX: ReadonlyArray<CharacterFx> = [
|
|
|
163
196
|
{ id: "shadow-aura", label: "Shadow Aura", category: "aura-ambient", description: "Dark shadow tendrils swirl around subject",
|
|
164
197
|
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
198
|
{ 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"
|
|
199
|
+
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",
|
|
200
|
+
term: "crackling electric aura" },
|
|
167
201
|
{ id: "sparkles-around", label: "Magical Sparkles", category: "aura-ambient", description: "Magical sparkles orbit the subject",
|
|
168
202
|
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
203
|
{ 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"
|
|
204
|
+
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",
|
|
205
|
+
term: "tiny glowing fairies" },
|
|
171
206
|
{ 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"
|
|
207
|
+
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",
|
|
208
|
+
term: "objects orbiting in mid-air" },
|
|
173
209
|
{ 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"
|
|
210
|
+
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",
|
|
211
|
+
term: "cherry blossom petals drifting" },
|
|
175
212
|
{ 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"
|
|
213
|
+
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",
|
|
214
|
+
term: "glowing motion trails" },
|
|
177
215
|
{ 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"
|
|
216
|
+
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",
|
|
217
|
+
term: "glowing animated tattoos" },
|
|
179
218
|
]
|
|
180
219
|
|
|
181
220
|
export const CHARACTER_FX_CATEGORY_ORDER: ReadonlyArray<CharacterFxCategory> = [
|
|
@@ -210,6 +249,17 @@ export function getCharacterFxPromptHint(id: string | undefined | null): string
|
|
|
210
249
|
return getCharacterFx(id)?.promptHint ?? ""
|
|
211
250
|
}
|
|
212
251
|
|
|
252
|
+
/**
|
|
253
|
+
* Compact counterpart of `getCharacterFxPromptHint`: the short professional
|
|
254
|
+
* term this effect injects in compact hint mode ("werewolf transformation"
|
|
255
|
+
* where the hint is the full shot description). Same lookup and same
|
|
256
|
+
* empty-string-on-miss behavior — including the no-op "auto"/"none" entries,
|
|
257
|
+
* which inject nothing at either detail level.
|
|
258
|
+
*/
|
|
259
|
+
export function getCharacterFxTerm(id: string | undefined | null): string {
|
|
260
|
+
return resolveTerm(getCharacterFx(id))
|
|
261
|
+
}
|
|
262
|
+
|
|
213
263
|
export const CHARACTER_FX_IDS: ReadonlyArray<string> = CHARACTER_FX.map((c) => c.id)
|
|
214
264
|
|
|
215
265
|
// ---------------------------------------------------------------------------
|
|
@@ -245,25 +295,48 @@ const INTENSITY_CLAUSES: Record<Exclude<CharacterFxIntensity, "auto">, string> =
|
|
|
245
295
|
*
|
|
246
296
|
* Substitution: each base hint has every `"the subject"` occurrence
|
|
247
297
|
* rewritten to the target name BEFORE the join. Empty targetHints leaves
|
|
248
|
-
* "the subject" intact in the prompt.
|
|
298
|
+
* "the subject" intact in the prompt. In compact hint mode the base is a bare
|
|
299
|
+
* `term` with no "the subject" to rewrite, so the target is named by an
|
|
300
|
+
* explicit `"{target}: {effects}"` prefix instead — the character is named in
|
|
301
|
+
* both modes.
|
|
302
|
+
*
|
|
303
|
+
* @param mode `"compact"` builds the base from each effect's short
|
|
304
|
+
* professional `term` instead of its full shot description. The ", and "
|
|
305
|
+
* multi-pick join and the position/duration/intensity clauses are emitted
|
|
306
|
+
* identically in both modes. The TARGET is not: no `term` contains the
|
|
307
|
+
* words "the subject" (a term names the effect, not a sentence about a
|
|
308
|
+
* subject), so compact mode names the target with an explicit
|
|
309
|
+
* `"{target}: {effects}"` prefix instead of substituting into the base.
|
|
310
|
+
* Either way the wired character is always named.
|
|
249
311
|
*/
|
|
250
312
|
export function composeCharacterFxHintFromConnections(
|
|
251
313
|
effectId: string | ReadonlyArray<string> | undefined,
|
|
252
314
|
targetHints: ReadonlyArray<string>,
|
|
253
315
|
timing?: CharacterFxTiming,
|
|
316
|
+
mode: PickerHintMode = "full",
|
|
254
317
|
): string {
|
|
255
318
|
const ids = Array.isArray(effectId)
|
|
256
319
|
? Array.from(new Set(effectId)).slice(0, 2)
|
|
257
320
|
: effectId ? [effectId] : []
|
|
258
|
-
|
|
321
|
+
// The base fragment swaps in compact mode; the multi-pick join and the
|
|
322
|
+
// timing clauses below are identical either way. The TARGET has to be
|
|
323
|
+
// carried differently per mode: the full hints are sentences built around
|
|
324
|
+
// the words "the subject", so a name substitutes INTO them, while a term is
|
|
325
|
+
// a bare effect name with nothing to substitute into — naming the target
|
|
326
|
+
// there means prefixing it. Skipping that is how the wired character's name
|
|
327
|
+
// silently disappeared from every compact fragment.
|
|
328
|
+
const resolveBase = mode === "compact" ? getCharacterFxTerm : getCharacterFxPromptHint
|
|
329
|
+
const baseHints = ids.map(resolveBase).filter((h) => h.length > 0)
|
|
259
330
|
if (baseHints.length === 0) return ""
|
|
260
331
|
|
|
261
332
|
const targetClause = targetHints.filter((h) => h && h.length > 0).join(" and ")
|
|
262
|
-
const substituted = targetClause
|
|
333
|
+
const substituted = targetClause && mode !== "compact"
|
|
263
334
|
? baseHints.map((b) => b.replace(/\bthe subject\b/g, targetClause))
|
|
264
335
|
: baseHints
|
|
265
336
|
|
|
266
|
-
const
|
|
337
|
+
const joined = substituted.join(", and ")
|
|
338
|
+
const combinedBase =
|
|
339
|
+
targetClause && mode === "compact" ? `${targetClause}: ${joined}` : joined
|
|
267
340
|
const parts: string[] = [combinedBase]
|
|
268
341
|
|
|
269
342
|
if (timing?.position && timing.position !== "auto") parts.push(POSITION_CLAUSES [timing.position])
|
package/src/color-look.ts
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
* frontend DAG executor and the backend orchestrator.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
import { resolveTerm } from "./term.js"
|
|
15
|
+
|
|
14
16
|
export type ColorLookCategory = "palette" | "film-emulation" | "social-preset"
|
|
15
17
|
|
|
16
18
|
export interface ColorLook {
|
|
@@ -19,23 +21,33 @@ export interface ColorLook {
|
|
|
19
21
|
readonly category: ColorLookCategory
|
|
20
22
|
readonly description: string
|
|
21
23
|
readonly promptHint: string
|
|
24
|
+
/**
|
|
25
|
+
* Compact professional form injected in COMPACT hint mode ("warm color
|
|
26
|
+
* grade" where `promptHint` is the full sentence). Authored only where the
|
|
27
|
+
* lowercased label is not already what a colorist would write — e.g. bare
|
|
28
|
+
* grade adjectives ("Warm", "Sepia"), UI compounds ("Teal & Orange",
|
|
29
|
+
* "Agfa / ORWO"), annotated stock names ("Kodak Tri-X 400 (B&W)") and
|
|
30
|
+
* stacked modifiers with no head noun ("MTV 90s VHS"). See `term.ts`;
|
|
31
|
+
* resolve via `resolveTerm`.
|
|
32
|
+
*/
|
|
33
|
+
readonly term?: string
|
|
22
34
|
}
|
|
23
35
|
|
|
24
36
|
export const COLOR_LOOKS: ReadonlyArray<ColorLook> = [
|
|
25
37
|
// 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" },
|
|
38
|
+
{ 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", term: "warm color grade" },
|
|
39
|
+
{ 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", term: "cool color grade" },
|
|
40
|
+
{ 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", term: "teal and orange grade" },
|
|
29
41
|
{ 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
42
|
{ 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" },
|
|
43
|
+
{ 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", term: "faded matte grade" },
|
|
44
|
+
{ 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", term: "flat ungraded log footage" },
|
|
45
|
+
{ id: "desaturated", label: "Desaturated", category: "palette", description: "Low saturation, muted", promptHint: "desaturated color grading, muted low-saturation tones throughout, almost monochromatic feel", term: "desaturated color grade" },
|
|
46
|
+
{ 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", term: "black and white" },
|
|
47
|
+
{ id: "sepia", label: "Sepia", category: "palette", description: "Vintage brown tone", promptHint: "sepia toned image, warm brown vintage monochrome with classic photographic feel", term: "sepia tone" },
|
|
48
|
+
{ id: "pastel", label: "Pastel", category: "palette", description: "Soft, low-contrast pastels", promptHint: "pastel color palette, soft low-contrast pastel hues with light airy tones", term: "pastel color palette" },
|
|
49
|
+
{ 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", term: "high contrast color grade" },
|
|
50
|
+
{ id: "vibrant", label: "Vibrant", category: "palette", description: "Highly saturated colors", promptHint: "vibrant saturated color palette, bold rich colors with high saturation throughout", term: "vibrant saturated color palette" },
|
|
39
51
|
|
|
40
52
|
// Film emulation (13)
|
|
41
53
|
{ 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" },
|
|
@@ -44,30 +56,30 @@ export const COLOR_LOOKS: ReadonlyArray<ColorLook> = [
|
|
|
44
56
|
{ 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
57
|
{ 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
58
|
{ 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" },
|
|
59
|
+
{ 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", term: "three-strip technicolor" },
|
|
48
60
|
{ 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
61
|
{ 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" },
|
|
62
|
+
{ 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", term: "hand-tinted black-and-white photograph" },
|
|
63
|
+
{ 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", term: "orwo film stock" },
|
|
64
|
+
{ 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", term: "day-for-night grade" },
|
|
65
|
+
{ 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", term: "cross-processed film look" },
|
|
54
66
|
{ 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
67
|
{ 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" },
|
|
68
|
+
{ 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", term: "kodak tri-x 400 black-and-white film" },
|
|
69
|
+
{ 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", term: "aerochrome color infrared film" },
|
|
70
|
+
{ 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", term: "fuji instax instant film" },
|
|
59
71
|
{ 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" },
|
|
72
|
+
{ 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", term: "expired light-struck film" },
|
|
61
73
|
|
|
62
74
|
// 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" },
|
|
75
|
+
{ 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", term: "warm instagram filter" },
|
|
76
|
+
{ 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", term: "saturated tiktok look" },
|
|
77
|
+
{ 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", term: "flat youtube vlog grade" },
|
|
66
78
|
{ 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" },
|
|
79
|
+
{ 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", term: "saturated y2k digital color" },
|
|
80
|
+
{ 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", term: "90s mtv vhs look" },
|
|
81
|
+
{ 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", term: "faded polaroid look" },
|
|
82
|
+
{ 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", term: "warm lifestyle magazine grade" },
|
|
71
83
|
] as const
|
|
72
84
|
|
|
73
85
|
export const COLOR_LOOK_CATEGORY_ORDER: ReadonlyArray<ColorLookCategory> = [
|
|
@@ -100,4 +112,9 @@ export function getColorLookPromptHint(id: string | undefined | null): string {
|
|
|
100
112
|
return getColorLook(id)?.promptHint ?? ""
|
|
101
113
|
}
|
|
102
114
|
|
|
115
|
+
/** Compact sibling of `getColorLookPromptHint` — the short colorist term. */
|
|
116
|
+
export function getColorLookTerm(id: string | undefined | null): string {
|
|
117
|
+
return resolveTerm(getColorLook(id))
|
|
118
|
+
}
|
|
119
|
+
|
|
103
120
|
export const COLOR_LOOK_IDS: ReadonlyArray<string> = COLOR_LOOKS.map((c) => c.id)
|
|
@@ -15,26 +15,35 @@
|
|
|
15
15
|
* executor and the backend orchestrator.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
+
import { resolveTerm } from "./term.js"
|
|
19
|
+
|
|
18
20
|
export interface CompositionEffect {
|
|
19
21
|
readonly id: string
|
|
20
22
|
readonly label: string
|
|
21
23
|
readonly description: string
|
|
22
24
|
readonly promptHint: string
|
|
25
|
+
/**
|
|
26
|
+
* Optional authored compact term (see `term.ts`). Authored only where the
|
|
27
|
+
* lowercased label is not the phrase a retoucher / VFX artist would write in
|
|
28
|
+
* a prompt — "Doubled Mirror" reads as a doubled mirror, not as a mirrored
|
|
29
|
+
* duplicate of the subject. Everywhere else the label IS the term.
|
|
30
|
+
*/
|
|
31
|
+
readonly term?: string
|
|
23
32
|
}
|
|
24
33
|
|
|
25
34
|
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" },
|
|
35
|
+
{ 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", term: "3d pop-out through a torn paper frame" },
|
|
36
|
+
{ 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", term: "out-of-bounds effect, limb past the frame" },
|
|
28
37
|
{ 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
38
|
{ 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
39
|
{ 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
40
|
{ 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" },
|
|
41
|
+
{ 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", term: "subject emerging from a textured surface" },
|
|
33
42
|
{ 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" },
|
|
43
|
+
{ 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", term: "rgb-shift glitch distortion, scanline tearing" },
|
|
44
|
+
{ 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", term: "mirrored duplication of the subject" },
|
|
45
|
+
{ 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", term: "body fragmenting into drifting pieces" },
|
|
46
|
+
{ 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", term: "flat black silhouette on a solid background" },
|
|
38
47
|
{ 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
48
|
{ 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
49
|
{ 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" },
|
|
@@ -64,4 +73,9 @@ export function getCompositionEffectPromptHint(id: string | undefined | null): s
|
|
|
64
73
|
return getCompositionEffect(id)?.promptHint ?? ""
|
|
65
74
|
}
|
|
66
75
|
|
|
76
|
+
/** The compact professional term for a composition effect (see `term.ts`). */
|
|
77
|
+
export function getCompositionEffectTerm(id: string | undefined | null): string {
|
|
78
|
+
return resolveTerm(getCompositionEffect(id))
|
|
79
|
+
}
|
|
80
|
+
|
|
67
81
|
export const COMPOSITION_EFFECT_IDS: ReadonlyArray<string> = COMPOSITION_EFFECTS.map((c) => c.id)
|
package/src/era.ts
CHANGED
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
* orchestrator.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
+
import { resolveTerm } from "./term.js"
|
|
21
|
+
|
|
20
22
|
export type EraCategory = "decade-20c" | "pre-modern" | "speculative"
|
|
21
23
|
|
|
22
24
|
export interface Era {
|
|
@@ -25,6 +27,16 @@ export interface Era {
|
|
|
25
27
|
readonly category: EraCategory
|
|
26
28
|
readonly description: string
|
|
27
29
|
readonly promptHint: string
|
|
30
|
+
/**
|
|
31
|
+
* Compact period name for prompt injection, authored only where the
|
|
32
|
+
* lowercased label is not what a period stylist would write: UI compounds
|
|
33
|
+
* ("1950s Diner / Pin-up"), annotated labels ("Fin-de-siècle (1895-1905)"),
|
|
34
|
+
* and decade names whose word order reads as a menu entry rather than an era
|
|
35
|
+
* ("Atomic Age 50s", "Pre-War Roaring"). Proper era names — medieval,
|
|
36
|
+
* renaissance, victorian, dieselpunk — need nothing; the label already IS
|
|
37
|
+
* the term.
|
|
38
|
+
*/
|
|
39
|
+
readonly term?: string
|
|
28
40
|
}
|
|
29
41
|
|
|
30
42
|
export const ERAS: ReadonlyArray<Era> = [
|
|
@@ -58,6 +70,7 @@ export const ERAS: ReadonlyArray<Era> = [
|
|
|
58
70
|
label: "1950s Diner / Pin-up",
|
|
59
71
|
category: "decade-20c",
|
|
60
72
|
description: "Chrome diners and bouffant pin-ups",
|
|
73
|
+
term: "1950s diner pin-up",
|
|
61
74
|
promptHint:
|
|
62
75
|
"set in the 1950s diner pin-up era — full circle skirts, cropped denim, leather jackets and bouffant hair in chrome diners and drive-ins, with saturated Kodachrome reds and turquoise",
|
|
63
76
|
},
|
|
@@ -66,6 +79,7 @@ export const ERAS: ReadonlyArray<Era> = [
|
|
|
66
79
|
label: "Atomic Age 50s",
|
|
67
80
|
category: "decade-20c",
|
|
68
81
|
description: "1950s sci-fi futurism and Cold War anxiety",
|
|
82
|
+
term: "1950s atomic age",
|
|
69
83
|
promptHint:
|
|
70
84
|
"set in the 1950s atomic-age era — ranch-style suburban homes, atomic starburst ornaments, finned appliances, B-movie sci-fi posters and Cold War civil-defense propaganda, with bright pulpy Technicolor saturation and hard mid-century optimism shot through with quiet nuclear dread",
|
|
71
85
|
},
|
|
@@ -98,6 +112,7 @@ export const ERAS: ReadonlyArray<Era> = [
|
|
|
98
112
|
label: "1990s Mall",
|
|
99
113
|
category: "decade-20c",
|
|
100
114
|
description: "Mall-rat grunge-and-pop nineties",
|
|
115
|
+
term: "1990s mall culture",
|
|
101
116
|
promptHint:
|
|
102
117
|
"set in the 1990s mall era — denim and crop tops, slip dresses, chokers and platform sneakers under fluorescent food-court lighting, with slight VHS-grain and a warm disposable-camera flash cast",
|
|
103
118
|
},
|
|
@@ -106,6 +121,7 @@ export const ERAS: ReadonlyArray<Era> = [
|
|
|
106
121
|
label: "2000s Tabloid / Y2K",
|
|
107
122
|
category: "decade-20c",
|
|
108
123
|
description: "Paparazzi-flash low-rise tabloid",
|
|
124
|
+
term: "2000s tabloid y2k",
|
|
109
125
|
promptHint:
|
|
110
126
|
"set in the 2000s tabloid Y2K era — low-rise jeans, butterfly tops, trucker hats and chrome flip phones outside celebrity nightclubs, with harsh paparazzi flash, deep blacks and faint chromatic gloss",
|
|
111
127
|
},
|
|
@@ -114,6 +130,7 @@ export const ERAS: ReadonlyArray<Era> = [
|
|
|
114
130
|
label: "Gen Z 2020s",
|
|
115
131
|
category: "decade-20c",
|
|
116
132
|
description: "Phone-first TikTok-coded current era",
|
|
133
|
+
term: "2020s gen z",
|
|
117
134
|
promptHint:
|
|
118
135
|
"set in the Gen Z 2020s era — phone-first vertical composition, TikTok-coded styling with baggy denim, Y2K nostalgia revivals, claw clips and oversized headphones, micro-trend churn and the saturated front-camera glow of contemporary social-media aesthetics",
|
|
119
136
|
},
|
|
@@ -188,6 +205,7 @@ export const ERAS: ReadonlyArray<Era> = [
|
|
|
188
205
|
label: "Fin-de-siècle (1895-1905)",
|
|
189
206
|
category: "pre-modern",
|
|
190
207
|
description: "Turn-of-century Belle Epoque elegance",
|
|
208
|
+
term: "fin-de-siècle 1900s",
|
|
191
209
|
promptHint:
|
|
192
210
|
"set in the fin-de-siècle turn-of-century era — art-nouveau curves, gaslight glow, corseted high-collared gowns, top hats and cane-and-cloak in proto-modern Belle Epoque Paris and Vienna, with warm gas-flame amber color and soft sepia halation",
|
|
193
211
|
},
|
|
@@ -196,6 +214,7 @@ export const ERAS: ReadonlyArray<Era> = [
|
|
|
196
214
|
label: "Pre-War Roaring",
|
|
197
215
|
category: "pre-modern",
|
|
198
216
|
description: "Late-1910s art-nouveau cusp",
|
|
217
|
+
term: "late-1910s pre-war",
|
|
199
218
|
promptHint:
|
|
200
219
|
"set in the late-1910s pre-war era — art-nouveau drapery, chignon hair, lace collars and cane-and-cloak in gas-lit Paris cafes, with sepia-bronze monochrome and soft halation",
|
|
201
220
|
},
|
|
@@ -277,6 +296,11 @@ export function getEraPromptHint(id: string | undefined | null): string {
|
|
|
277
296
|
return getEra(id)?.promptHint ?? ""
|
|
278
297
|
}
|
|
279
298
|
|
|
299
|
+
/** Compact counterpart of `getEraPromptHint` — the short period name. */
|
|
300
|
+
export function getEraTerm(id: string | undefined | null): string {
|
|
301
|
+
return resolveTerm(getEra(id))
|
|
302
|
+
}
|
|
303
|
+
|
|
280
304
|
export const ERA_IDS: ReadonlyArray<string> = ERAS.map((e) => e.id)
|
|
281
305
|
|
|
282
306
|
export const ERA_CATEGORY_LABELS: Readonly<Record<EraCategory, string>> = {
|