@nodaro/prompts 1.7.2 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +5453 -4271
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1221 -63
- package/dist/index.d.ts +1221 -63
- package/dist/index.js +5366 -4273
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- 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__/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 +100 -0
- 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 +6 -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/picker-wiring.ts +1 -1
- 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 +1 -2
- package/src/render-quality.ts +25 -7
- package/src/setting.ts +30 -14
- package/src/style-presets.ts +1 -1
- package/src/style.ts +33 -15
- package/src/styling.ts +155 -94
- package/src/surround-fill.ts +67 -0
- 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/lighting.ts
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* frontend DAG executor and the backend orchestrator.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import { resolveTerm, type PickerHintMode } from "./term.js"
|
|
14
|
+
|
|
13
15
|
export type LightingCategory =
|
|
14
16
|
| "time-of-day"
|
|
15
17
|
| "style"
|
|
@@ -23,93 +25,102 @@ export interface Lighting {
|
|
|
23
25
|
readonly category: LightingCategory
|
|
24
26
|
readonly description: string
|
|
25
27
|
readonly promptHint: string
|
|
28
|
+
/**
|
|
29
|
+
* Compact professional term injected in compact hint mode (see `term.ts`).
|
|
30
|
+
*
|
|
31
|
+
* Lighting labels are bare MODIFIERS — "Short", "Broad", "Loop", "Split",
|
|
32
|
+
* "Hard" mean nothing on their own and collide head-on with common English
|
|
33
|
+
* words, so nearly every entry here authors the trade phrasing that carries
|
|
34
|
+
* its category noun ("short lighting", "1:4 lighting ratio").
|
|
35
|
+
*/
|
|
36
|
+
readonly term?: string
|
|
26
37
|
}
|
|
27
38
|
|
|
28
39
|
export const LIGHTINGS: ReadonlyArray<Lighting> = [
|
|
29
40
|
// Time of day (15)
|
|
30
|
-
{ id: "dawn", label: "Dawn", category: "time-of-day", description: "Pre-sunrise pale glow", promptHint: "dawn lighting, the pre-sunrise pale glow with deep blue ambient tones transitioning to soft pink and orange at the horizon, low contrast, cool ambient" },
|
|
31
|
-
{ id: "sunrise", label: "Sunrise", category: "time-of-day", description: "Warm low sun, long shadows", promptHint: "sunrise lighting, warm low-angle sun with long shadows and soft golden tones" },
|
|
32
|
-
{ id: "morning", label: "Morning", category: "time-of-day", description: "Bright fresh morning light", promptHint: "morning lighting, bright fresh ambient daylight with soft directional sun, warm white tones and clean shadows" },
|
|
33
|
-
{ id: "noon", label: "Noon", category: "time-of-day", description: "Harsh overhead midday sun", promptHint: "midday noon lighting, harsh overhead sun with high contrast and strong vertical shadows" },
|
|
34
|
-
{ id: "harsh-midday", label: "Harsh Midday", category: "time-of-day", description: "Bleached white-sun zenith", promptHint: "harsh midday white-sun lighting, sun directly overhead at zenith, blown-out white highlights and short hard shadows pooled directly beneath the subject" },
|
|
35
|
-
{ id: "afternoon", label: "Afternoon", category: "time-of-day", description: "Warm late afternoon glow", promptHint: "afternoon lighting, warm directional late-afternoon sun with elongated shadows, saturated amber tones leading into golden hour" },
|
|
36
|
-
{ id: "overcast", label: "Overcast", category: "time-of-day", description: "Soft diffused daylight", promptHint: "overcast daylight, soft diffused light from a uniformly cloudy sky with no harsh shadows" },
|
|
41
|
+
{ id: "dawn", label: "Dawn", category: "time-of-day", description: "Pre-sunrise pale glow", promptHint: "dawn lighting, the pre-sunrise pale glow with deep blue ambient tones transitioning to soft pink and orange at the horizon, low contrast, cool ambient", term: "dawn lighting" },
|
|
42
|
+
{ id: "sunrise", label: "Sunrise", category: "time-of-day", description: "Warm low sun, long shadows", promptHint: "sunrise lighting, warm low-angle sun with long shadows and soft golden tones", term: "sunrise lighting" },
|
|
43
|
+
{ id: "morning", label: "Morning", category: "time-of-day", description: "Bright fresh morning light", promptHint: "morning lighting, bright fresh ambient daylight with soft directional sun, warm white tones and clean shadows", term: "morning lighting" },
|
|
44
|
+
{ id: "noon", label: "Noon", category: "time-of-day", description: "Harsh overhead midday sun", promptHint: "midday noon lighting, harsh overhead sun with high contrast and strong vertical shadows", term: "overhead noon sun" },
|
|
45
|
+
{ id: "harsh-midday", label: "Harsh Midday", category: "time-of-day", description: "Bleached white-sun zenith", promptHint: "harsh midday white-sun lighting, sun directly overhead at zenith, blown-out white highlights and short hard shadows pooled directly beneath the subject", term: "harsh midday sun" },
|
|
46
|
+
{ id: "afternoon", label: "Afternoon", category: "time-of-day", description: "Warm late afternoon glow", promptHint: "afternoon lighting, warm directional late-afternoon sun with elongated shadows, saturated amber tones leading into golden hour", term: "afternoon lighting" },
|
|
47
|
+
{ id: "overcast", label: "Overcast", category: "time-of-day", description: "Soft diffused daylight", promptHint: "overcast daylight, soft diffused light from a uniformly cloudy sky with no harsh shadows", term: "overcast daylight" },
|
|
37
48
|
{ id: "golden-hour", label: "Golden Hour", category: "time-of-day", description: "Warm sunset glow", promptHint: "golden hour lighting, warm sunset glow with soft directional sunlight and saturated golden tones" },
|
|
38
|
-
{ id: "dusk", label: "Dusk", category: "time-of-day", description: "Post-sunset fading light", promptHint: "dusk lighting, the post-sunset fading light with deepening blue sky, residual warm horizon glow, and rising ambient cool tones" },
|
|
49
|
+
{ id: "dusk", label: "Dusk", category: "time-of-day", description: "Post-sunset fading light", promptHint: "dusk lighting, the post-sunset fading light with deepening blue sky, residual warm horizon glow, and rising ambient cool tones", term: "dusk lighting" },
|
|
39
50
|
{ id: "blue-hour", label: "Blue Hour", category: "time-of-day", description: "Cool dusk twilight", promptHint: "blue hour twilight lighting, cool desaturated tones just after sunset with soft ambient light" },
|
|
40
|
-
{ id: "twilight", label: "Twilight", category: "time-of-day", description: "Between blue hour and night", promptHint: "twilight lighting, the transitional dusk between blue hour and full night, deep indigo sky with the last residual ambient glow on the horizon and emerging artificial city lights" },
|
|
41
|
-
{ id: "night", label: "Night", category: "time-of-day", description: "Deep night, low ambient", promptHint: "night lighting, deep dark scene with minimal ambient illumination and high contrast highlights" },
|
|
42
|
-
{ id: "midnight", label: "Midnight", category: "time-of-day", description: "Deepest night, near-black sky", promptHint: "midnight lighting, the deepest part of night with a near-black sky, minimal ambient illumination, scattered cool moonlight or starlight as the only natural source" },
|
|
43
|
-
{ id: "moonlight", label: "Moonlight", category: "time-of-day", description: "Cool blue moonlit scene", promptHint: "moonlight, cool blue ambient illumination with soft directional moonlit highlights and deep shadows" },
|
|
44
|
-
{ id: "neon-night", label: "Neon Night", category: "time-of-day", description: "Saturated neon city night", promptHint: "neon night lighting, saturated magenta and cyan neon glow against deep night ambient, urban cyberpunk feel" },
|
|
51
|
+
{ id: "twilight", label: "Twilight", category: "time-of-day", description: "Between blue hour and night", promptHint: "twilight lighting, the transitional dusk between blue hour and full night, deep indigo sky with the last residual ambient glow on the horizon and emerging artificial city lights", term: "twilight lighting" },
|
|
52
|
+
{ id: "night", label: "Night", category: "time-of-day", description: "Deep night, low ambient", promptHint: "night lighting, deep dark scene with minimal ambient illumination and high contrast highlights", term: "night lighting" },
|
|
53
|
+
{ id: "midnight", label: "Midnight", category: "time-of-day", description: "Deepest night, near-black sky", promptHint: "midnight lighting, the deepest part of night with a near-black sky, minimal ambient illumination, scattered cool moonlight or starlight as the only natural source", term: "midnight lighting" },
|
|
54
|
+
{ id: "moonlight", label: "Moonlight", category: "time-of-day", description: "Cool blue moonlit scene", promptHint: "moonlight, cool blue ambient illumination with soft directional moonlit highlights and deep shadows", term: "cool blue moonlight" },
|
|
55
|
+
{ id: "neon-night", label: "Neon Night", category: "time-of-day", description: "Saturated neon city night", promptHint: "neon night lighting, saturated magenta and cyan neon glow against deep night ambient, urban cyberpunk feel", term: "neon night lighting" },
|
|
45
56
|
|
|
46
57
|
// Style (31)
|
|
47
|
-
{ id: "three-point", label: "Three-Point", category: "style", description: "Classic key + fill + back", promptHint: "three-point lighting setup, balanced key light with fill and rim back-light, classical studio look" },
|
|
48
|
-
{ id: "rembrandt", label: "Rembrandt", category: "style", description: "Triangle of light on cheek", promptHint: "Rembrandt lighting, distinctive triangle of light on the shadow-side cheek, painterly chiaroscuro" },
|
|
49
|
-
{ id: "chiaroscuro", label: "Chiaroscuro", category: "style", description: "Strong light/dark contrast", promptHint: "chiaroscuro lighting, dramatic strong contrast between deep shadows and bright highlights" },
|
|
50
|
-
{ id: "silhouette", label: "Silhouette", category: "style", description: "Subject as pure shape", promptHint: "silhouette lighting, subject rendered as a pure dark shape against a much brighter background" },
|
|
51
|
-
{ id: "high-key", label: "High-Key", category: "style", description: "Bright, low-contrast", promptHint: "high-key lighting, bright low-contrast scene with minimal shadows and a light overall tone" },
|
|
52
|
-
{ id: "low-key", label: "Low-Key", category: "style", description: "Dark, high-contrast", promptHint: "low-key lighting, dark high-contrast scene with deep shadows and selective highlights" },
|
|
53
|
-
{ id: "split", label: "Split", category: "style", description: "Half-lit half-shadow face", promptHint: "split lighting, light hitting only one half of the face with the other half in deep shadow" },
|
|
58
|
+
{ id: "three-point", label: "Three-Point", category: "style", description: "Classic key + fill + back", promptHint: "three-point lighting setup, balanced key light with fill and rim back-light, classical studio look", term: "three-point lighting" },
|
|
59
|
+
{ id: "rembrandt", label: "Rembrandt", category: "style", description: "Triangle of light on cheek", promptHint: "Rembrandt lighting, distinctive triangle of light on the shadow-side cheek, painterly chiaroscuro", term: "rembrandt lighting" },
|
|
60
|
+
{ id: "chiaroscuro", label: "Chiaroscuro", category: "style", description: "Strong light/dark contrast", promptHint: "chiaroscuro lighting, dramatic strong contrast between deep shadows and bright highlights", term: "chiaroscuro lighting" },
|
|
61
|
+
{ id: "silhouette", label: "Silhouette", category: "style", description: "Subject as pure shape", promptHint: "silhouette lighting, subject rendered as a pure dark shape against a much brighter background", term: "silhouette lighting" },
|
|
62
|
+
{ id: "high-key", label: "High-Key", category: "style", description: "Bright, low-contrast", promptHint: "high-key lighting, bright low-contrast scene with minimal shadows and a light overall tone", term: "high-key lighting" },
|
|
63
|
+
{ id: "low-key", label: "Low-Key", category: "style", description: "Dark, high-contrast", promptHint: "low-key lighting, dark high-contrast scene with deep shadows and selective highlights", term: "low-key lighting" },
|
|
64
|
+
{ id: "split", label: "Split", category: "style", description: "Half-lit half-shadow face", promptHint: "split lighting, light hitting only one half of the face with the other half in deep shadow", term: "split lighting" },
|
|
54
65
|
// Classical portrait lighting setups
|
|
55
|
-
{ id: "butterfly", label: "Butterfly", category: "style", description: "Glamour, nose-shadow butterfly", promptHint: "butterfly portrait lighting, key light placed directly above and slightly in front of the subject casting a small symmetrical butterfly-shaped shadow under the nose, classic Hollywood glamour with even illumination across both cheeks" },
|
|
56
|
-
{ id: "loop", label: "Loop", category: "style", description: "Most natural portrait setup", promptHint: "loop portrait lighting, key light slightly to one side and above eye level casting a small loop-shaped nose shadow on the cheek that does not touch the shadow side, the most natural and flattering classical portrait setup" },
|
|
57
|
-
{ id: "broad", label: "Broad", category: "style", description: "Wider face, friendly key", promptHint: "broad portrait lighting, key light striking the side of the face turned toward the camera so the larger lit cheek dominates the frame, makes the face appear wider and more open with a friendly approachable feel" },
|
|
58
|
-
{ id: "short", label: "Short", category: "style", description: "Slimming, dramatic key", promptHint: "short portrait lighting, key light striking the side of the face turned away from the camera so the larger plane of the face falls into shadow, slims the face and adds dramatic dimension favored in editorial and male portraiture" },
|
|
59
|
-
{ id: "hatchet", label: "Hatchet", category: "style", description: "Overhead skim, deep side shadow", promptHint: "hatchet portrait lighting, hard overhead light skimming the face from one side and leaving the opposite side in deep unrelieved shadow, theatrical and severe with a sharply divided contour" },
|
|
60
|
-
{ id: "clamshell", label: "Clamshell", category: "style", description: "Beauty key + bottom reflector", promptHint: "clamshell beauty lighting, soft key light above the subject paired with a reflector or fill below the chin sandwiching the face evenly between two light sources, glossy commercial beauty look with twin catchlights and minimal shadow under the jaw" },
|
|
61
|
-
{ id: "hard", label: "Hard", category: "style", description: "Sharp-edged shadows", promptHint: "hard lighting, sharp-edged crisp shadows from an undiffused direct light source" },
|
|
62
|
-
{ id: "soft", label: "Soft", category: "style", description: "Diffused gentle light", promptHint: "soft diffused lighting, gentle wraparound light with smooth shadow transitions" },
|
|
63
|
-
{ id: "practical", label: "Practical", category: "style", description: "In-scene visible lights", promptHint: "practical lighting, illumination from visible in-scene sources (lamps, windows, screens, candles)" },
|
|
66
|
+
{ id: "butterfly", label: "Butterfly", category: "style", description: "Glamour, nose-shadow butterfly", promptHint: "butterfly portrait lighting, key light placed directly above and slightly in front of the subject casting a small symmetrical butterfly-shaped shadow under the nose, classic Hollywood glamour with even illumination across both cheeks", term: "butterfly lighting" },
|
|
67
|
+
{ id: "loop", label: "Loop", category: "style", description: "Most natural portrait setup", promptHint: "loop portrait lighting, key light slightly to one side and above eye level casting a small loop-shaped nose shadow on the cheek that does not touch the shadow side, the most natural and flattering classical portrait setup", term: "loop lighting" },
|
|
68
|
+
{ id: "broad", label: "Broad", category: "style", description: "Wider face, friendly key", promptHint: "broad portrait lighting, key light striking the side of the face turned toward the camera so the larger lit cheek dominates the frame, makes the face appear wider and more open with a friendly approachable feel", term: "broad lighting" },
|
|
69
|
+
{ id: "short", label: "Short", category: "style", description: "Slimming, dramatic key", promptHint: "short portrait lighting, key light striking the side of the face turned away from the camera so the larger plane of the face falls into shadow, slims the face and adds dramatic dimension favored in editorial and male portraiture", term: "short lighting" },
|
|
70
|
+
{ id: "hatchet", label: "Hatchet", category: "style", description: "Overhead skim, deep side shadow", promptHint: "hatchet portrait lighting, hard overhead light skimming the face from one side and leaving the opposite side in deep unrelieved shadow, theatrical and severe with a sharply divided contour", term: "hatchet lighting" },
|
|
71
|
+
{ id: "clamshell", label: "Clamshell", category: "style", description: "Beauty key + bottom reflector", promptHint: "clamshell beauty lighting, soft key light above the subject paired with a reflector or fill below the chin sandwiching the face evenly between two light sources, glossy commercial beauty look with twin catchlights and minimal shadow under the jaw", term: "clamshell lighting" },
|
|
72
|
+
{ id: "hard", label: "Hard", category: "style", description: "Sharp-edged shadows", promptHint: "hard lighting, sharp-edged crisp shadows from an undiffused direct light source", term: "hard light" },
|
|
73
|
+
{ id: "soft", label: "Soft", category: "style", description: "Diffused gentle light", promptHint: "soft diffused lighting, gentle wraparound light with smooth shadow transitions", term: "soft diffused light" },
|
|
74
|
+
{ id: "practical", label: "Practical", category: "style", description: "In-scene visible lights", promptHint: "practical lighting, illumination from visible in-scene sources (lamps, windows, screens, candles)", term: "practical lighting" },
|
|
64
75
|
// Modern social-video lighting styles
|
|
65
76
|
{ id: "ring-light", label: "Ring Light", category: "style", description: "Beauty/vlog ring catchlight", promptHint: "ring light setup, even frontal illumination with the unmistakable circular catchlight in the eyes typical of beauty and vlog content" },
|
|
66
77
|
{ id: "phone-screen-glow", label: "Phone Screen Glow", category: "style", description: "Cool screen underlight", promptHint: "phone screen glow lighting, cool blue underlighting from a phone screen casting upward onto the subject's face" },
|
|
67
|
-
{ id: "selfie-natural", label: "Selfie Natural", category: "style", description: "Window-light selfie", promptHint: "window-light selfie aesthetic, soft natural daylight from a single window with casual handheld framing" },
|
|
68
|
-
{ id: "natural", label: "Natural", category: "style", description: "Available ambient light", promptHint: "natural lighting, available ambient light with no artificial setup, organic and unpolished" },
|
|
69
|
-
{ id: "volumetric", label: "Volumetric", category: "style", description: "Visible light beams in haze", promptHint: "volumetric lighting, visible god-ray light beams cutting through hazy atmosphere with strong directional shafts" },
|
|
70
|
-
{ id: "noir", label: "Noir", category: "style", description: "High-contrast B&W film noir", promptHint: "film noir lighting, high-contrast black-and-white aesthetic with hard chiaroscuro shadows, venetian-blind slat shadows, and crushed deep blacks" },
|
|
78
|
+
{ id: "selfie-natural", label: "Selfie Natural", category: "style", description: "Window-light selfie", promptHint: "window-light selfie aesthetic, soft natural daylight from a single window with casual handheld framing", term: "natural window-light selfie" },
|
|
79
|
+
{ id: "natural", label: "Natural", category: "style", description: "Available ambient light", promptHint: "natural lighting, available ambient light with no artificial setup, organic and unpolished", term: "natural available light" },
|
|
80
|
+
{ id: "volumetric", label: "Volumetric", category: "style", description: "Visible light beams in haze", promptHint: "volumetric lighting, visible god-ray light beams cutting through hazy atmosphere with strong directional shafts", term: "volumetric lighting" },
|
|
81
|
+
{ id: "noir", label: "Noir", category: "style", description: "High-contrast B&W film noir", promptHint: "film noir lighting, high-contrast black-and-white aesthetic with hard chiaroscuro shadows, venetian-blind slat shadows, and crushed deep blacks", term: "film noir lighting" },
|
|
71
82
|
// Flash & camera-flash styles
|
|
72
83
|
{ id: "on-camera-flash", label: "On-Camera Flash", category: "style", description: "Paparazzi/iPhone direct flash", promptHint: "on-camera flash lighting, harsh direct frontal flash with blown-out highlights on skin, hard shadow falloff behind the subject and a darkened background, paparazzi and iPhone-flash signature" },
|
|
73
|
-
{ id: "mirror-bounce-flash", label: "Mirror-Bounce Flash", category: "style", description: "Mirror-selfie flash bounce", promptHint: "mirror-selfie flash lighting, yellowish uneven LED-or-flash bouncing off the mirror surface with a hot flare spot, partially obscured face by the phone, classic mirror-selfie aesthetic" },
|
|
84
|
+
{ id: "mirror-bounce-flash", label: "Mirror-Bounce Flash", category: "style", description: "Mirror-selfie flash bounce", promptHint: "mirror-selfie flash lighting, yellowish uneven LED-or-flash bouncing off the mirror surface with a hot flare spot, partially obscured face by the phone, classic mirror-selfie aesthetic", term: "mirror-selfie flash" },
|
|
74
85
|
{ id: "bounced-flash", label: "Bounced Flash", category: "style", description: "Soft ceiling-bounced fill", promptHint: "bounced flash lighting, on-camera flash redirected off a ceiling or wall to create soft top-down fill with gentle shadows, even skin tones and natural ambient feel" },
|
|
75
|
-
{ id: "softbox-key", label: "Softbox Key", category: "style", description: "Large diffused fashion key", promptHint: "softbox key lighting, large diffused fashion-studio key light producing gentle wraparound illumination, soft falloff and clean even skin rendering" },
|
|
86
|
+
{ id: "softbox-key", label: "Softbox Key", category: "style", description: "Large diffused fashion key", promptHint: "softbox key lighting, large diffused fashion-studio key light producing gentle wraparound illumination, soft falloff and clean even skin rendering", term: "softbox key light" },
|
|
76
87
|
{ id: "beauty-dish", label: "Beauty Dish", category: "style", description: "Hero light, crisp falloff", promptHint: "beauty dish lighting, semi-hard hero light with crisp shadow falloff and a distinctive round catchlight, slightly punchy contour and contrast favored in beauty and editorial portraits" },
|
|
77
88
|
{ id: "gridded-snoot", label: "Gridded Snoot", category: "style", description: "Tight focused pool of light", promptHint: "gridded snoot lighting, tightly focused circular pool of light isolating the subject's face or shoulders against deep surrounding shadow, theatrical and controlled" },
|
|
78
89
|
{ id: "silk-diffusion", label: "Silk Diffusion", category: "style", description: "Silk-softened gentle key", promptHint: "silk diffusion lighting, gentle key light passed through a large silk to soften shadow edges, producing creamy gradients and flattering skin tones" },
|
|
79
|
-
{ id: "kicker-rim", label: "Kicker / Rim Accent", category: "style", description: "Low-side accent separator", promptHint: "kicker rim accent lighting, low side-rear accent light skimming the subject's edge to separate them from a darker background, adds dimension and depth" },
|
|
80
|
-
{ id: "candlelight", label: "Candlelight", category: "style", description: "Warm flickering firelight", promptHint: "candlelight or firelight, warm flickering tungsten glow with soft falloff, low color temperature and gentle dancing shadows on nearby surfaces" },
|
|
81
|
-
{ id: "edison-tungsten", label: "Edison Tungsten", category: "style", description: "Cozy warm globe-bulb glow", promptHint: "Edison-bulb tungsten lighting, warm low-CRI globe-bulb glow with visible filament hot-spots, cozy bar or cafe atmosphere with amber-orange ambient" },
|
|
82
|
-
{ id: "dappled-light", label: "Dappled / Leaf-Filtered", category: "style", description: "Speckled foliage light", promptHint: "dappled leaf-filtered lighting, sunlight broken into a speckled pattern of bright spots and soft shadows as it passes through overhead foliage, organic and painterly" },
|
|
90
|
+
{ id: "kicker-rim", label: "Kicker / Rim Accent", category: "style", description: "Low-side accent separator", promptHint: "kicker rim accent lighting, low side-rear accent light skimming the subject's edge to separate them from a darker background, adds dimension and depth", term: "kicker rim light" },
|
|
91
|
+
{ id: "candlelight", label: "Candlelight", category: "style", description: "Warm flickering firelight", promptHint: "candlelight or firelight, warm flickering tungsten glow with soft falloff, low color temperature and gentle dancing shadows on nearby surfaces", term: "warm flickering candlelight" },
|
|
92
|
+
{ id: "edison-tungsten", label: "Edison Tungsten", category: "style", description: "Cozy warm globe-bulb glow", promptHint: "Edison-bulb tungsten lighting, warm low-CRI globe-bulb glow with visible filament hot-spots, cozy bar or cafe atmosphere with amber-orange ambient", term: "warm edison-bulb tungsten glow" },
|
|
93
|
+
{ id: "dappled-light", label: "Dappled / Leaf-Filtered", category: "style", description: "Speckled foliage light", promptHint: "dappled leaf-filtered lighting, sunlight broken into a speckled pattern of bright spots and soft shadows as it passes through overhead foliage, organic and painterly", term: "dappled leaf-filtered light" },
|
|
83
94
|
{ id: "raking-sidelight", label: "Raking Sidelight", category: "style", description: "Extreme low side, texture", promptHint: "raking sidelight, extreme low-angle side light skimming across the surface to exaggerate texture and microcontour, long parallel shadows reveal every detail" },
|
|
84
95
|
{ id: "stage-spotlight", label: "Stage Spotlight", category: "style", description: "Single hard overhead spot", promptHint: "stage spotlight lighting, single hard overhead theatre spotlight isolating the subject in a circular pool of light against pure black surroundings, dust motes catching the beam" },
|
|
85
96
|
{ id: "underwater-caustics", label: "Underwater Caustics", category: "style", description: "Rippled refracted patterns", promptHint: "underwater caustics lighting, rippled wavy refracted light patterns dancing across the subject and surroundings, cool aquatic blue-green palette with shimmering highlights" },
|
|
86
|
-
{ id: "bioluminescence", label: "Bioluminescence", category: "style", description: "Cool eerie biological glow", promptHint: "bioluminescence lighting, cool eerie cyan-green glow emanating from biological sources, soft self-illuminated highlights against deep ambient darkness, otherworldly atmosphere" },
|
|
97
|
+
{ id: "bioluminescence", label: "Bioluminescence", category: "style", description: "Cool eerie biological glow", promptHint: "bioluminescence lighting, cool eerie cyan-green glow emanating from biological sources, soft self-illuminated highlights against deep ambient darkness, otherworldly atmosphere", term: "bioluminescent glow" },
|
|
87
98
|
|
|
88
99
|
// Direction (8)
|
|
89
|
-
{ id: "front", label: "Front", category: "direction", description: "Light from camera direction", promptHint: "front lighting, light coming from the camera direction, flat even illumination across the subject" },
|
|
90
|
-
{ id: "three-quarter", label: "3/4 Light", category: "direction", description: "Classic portrait key angle", promptHint: "three-quarter light, classic portrait key angle split between front and side at roughly 45 degrees off-camera, sculpts the face with a visible shadow on the far cheek and a defined nose shadow" },
|
|
91
|
-
{ id: "side", label: "Side", category: "direction", description: "Light from one side", promptHint: "side lighting, light coming from the side of the subject, emphasizing texture and form" },
|
|
92
|
-
{ id: "back-rim", label: "Back / Rim", category: "direction", description: "Backlight rim around subject", promptHint: "back-light or rim-light, light coming from behind the subject creating a bright rim around their silhouette" },
|
|
100
|
+
{ id: "front", label: "Front", category: "direction", description: "Light from camera direction", promptHint: "front lighting, light coming from the camera direction, flat even illumination across the subject", term: "front lighting" },
|
|
101
|
+
{ id: "three-quarter", label: "3/4 Light", category: "direction", description: "Classic portrait key angle", promptHint: "three-quarter light, classic portrait key angle split between front and side at roughly 45 degrees off-camera, sculpts the face with a visible shadow on the far cheek and a defined nose shadow", term: "three-quarter key light" },
|
|
102
|
+
{ id: "side", label: "Side", category: "direction", description: "Light from one side", promptHint: "side lighting, light coming from the side of the subject, emphasizing texture and form", term: "side lighting" },
|
|
103
|
+
{ id: "back-rim", label: "Back / Rim", category: "direction", description: "Backlight rim around subject", promptHint: "back-light or rim-light, light coming from behind the subject creating a bright rim around their silhouette", term: "rim backlight" },
|
|
93
104
|
{ id: "silhouette-backlight", label: "Silhouette Backlight", category: "direction", description: "Bright halo, dark subject", promptHint: "silhouette backlight, strong light source directly behind the subject rendering them as a dark shape with a luminous halo edge and bright background bloom, dramatic contour against the sky or window" },
|
|
94
|
-
{ id: "top-overhead", label: "Top / Overhead",category: "direction", description: "Light from directly above", promptHint: "top-down overhead lighting, light coming from directly above the subject creating shadows under the eyes and chin" },
|
|
95
|
-
{ id: "under-uplight", label: "Under / Uplight",category: "direction", description: "Light from below", promptHint: "uplighting from below, light coming from below the subject creating an unsettling theatrical look" },
|
|
96
|
-
{ id: "window", label: "Window", category: "direction", description: "Soft sidelight from window", promptHint: "window lighting, soft directional light from a single window source with natural falloff" },
|
|
105
|
+
{ id: "top-overhead", label: "Top / Overhead",category: "direction", description: "Light from directly above", promptHint: "top-down overhead lighting, light coming from directly above the subject creating shadows under the eyes and chin", term: "overhead top light" },
|
|
106
|
+
{ id: "under-uplight", label: "Under / Uplight",category: "direction", description: "Light from below", promptHint: "uplighting from below, light coming from below the subject creating an unsettling theatrical look", term: "uplighting from below" },
|
|
107
|
+
{ id: "window", label: "Window", category: "direction", description: "Soft sidelight from window", promptHint: "window lighting, soft directional light from a single window source with natural falloff", term: "window light" },
|
|
97
108
|
|
|
98
109
|
// Lighting ratio (6) — relative key-to-shadow brightness
|
|
99
|
-
{ id: "ratio-1-1", label: "1:1", category: "lighting-ratio", description: "Flat, no shadow contrast", promptHint: "1:1 lighting ratio, flat even illumination across the subject with no contrast between key and fill, beauty and catalog look that flattens dimension" },
|
|
100
|
-
{ id: "ratio-1-2", label: "1:2", category: "lighting-ratio", description: "Soft one-stop falloff", promptHint: "1:2 lighting ratio, gentle soft modeling with roughly one stop of falloff from key to shadow side, classic flattering portraiture with mild dimension" },
|
|
101
|
-
{ id: "ratio-1-3", label: "1:3", category: "lighting-ratio", description: "Moderate two-stop contrast", promptHint: "1:3 lighting ratio, moderate contrast with about two stops between the lit and shadow sides, well-defined facial dimension and visible but recovered shadow detail" },
|
|
102
|
-
{ id: "ratio-1-4", label: "1:4", category: "lighting-ratio", description: "Strong editorial contrast", promptHint: "1:4 lighting ratio, strong contrast with deepening shadows on the unlit side, dramatic editorial feel with sculpted form and minimal shadow detail" },
|
|
103
|
-
{ id: "ratio-1-8", label: "1:8", category: "lighting-ratio", description: "Extreme low-key chiaroscuro", promptHint: "1:8 lighting ratio, extreme chiaroscuro with near-black shadow side balanced against a single bright key, classic low-key cinema atmosphere" },
|
|
104
|
-
{ id: "ratio-1-16", label: "1:16", category: "lighting-ratio", description: "Single-source film-noir falloff", promptHint: "1:16 lighting ratio, single-source key against pitch-black shadow side, theatrical film-noir falloff with no fill and crushed unlit detail" },
|
|
110
|
+
{ id: "ratio-1-1", label: "1:1", category: "lighting-ratio", description: "Flat, no shadow contrast", promptHint: "1:1 lighting ratio, flat even illumination across the subject with no contrast between key and fill, beauty and catalog look that flattens dimension", term: "1:1 lighting ratio" },
|
|
111
|
+
{ id: "ratio-1-2", label: "1:2", category: "lighting-ratio", description: "Soft one-stop falloff", promptHint: "1:2 lighting ratio, gentle soft modeling with roughly one stop of falloff from key to shadow side, classic flattering portraiture with mild dimension", term: "1:2 lighting ratio" },
|
|
112
|
+
{ id: "ratio-1-3", label: "1:3", category: "lighting-ratio", description: "Moderate two-stop contrast", promptHint: "1:3 lighting ratio, moderate contrast with about two stops between the lit and shadow sides, well-defined facial dimension and visible but recovered shadow detail", term: "1:3 lighting ratio" },
|
|
113
|
+
{ id: "ratio-1-4", label: "1:4", category: "lighting-ratio", description: "Strong editorial contrast", promptHint: "1:4 lighting ratio, strong contrast with deepening shadows on the unlit side, dramatic editorial feel with sculpted form and minimal shadow detail", term: "1:4 lighting ratio" },
|
|
114
|
+
{ id: "ratio-1-8", label: "1:8", category: "lighting-ratio", description: "Extreme low-key chiaroscuro", promptHint: "1:8 lighting ratio, extreme chiaroscuro with near-black shadow side balanced against a single bright key, classic low-key cinema atmosphere", term: "1:8 lighting ratio" },
|
|
115
|
+
{ id: "ratio-1-16", label: "1:16", category: "lighting-ratio", description: "Single-source film-noir falloff", promptHint: "1:16 lighting ratio, single-source key against pitch-black shadow side, theatrical film-noir falloff with no fill and crushed unlit detail", term: "1:16 lighting ratio" },
|
|
105
116
|
|
|
106
117
|
// Color temperature (6) — Kelvin from warm to cool
|
|
107
|
-
{ id: "temp-2700k", label: "2700K Candle", category: "color-temperature", description: "Deep amber candle/tungsten", promptHint: "2700K warm candle and low-tungsten color temperature, deep amber and orange cast across the scene, intimate and cozy mood with rich golden highlights" },
|
|
108
|
-
{ id: "temp-3200k", label: "3200K Tungsten", category: "color-temperature", description: "Warm yellow interior", promptHint: "3200K tungsten color temperature, warm yellow-orange cast typical of classic incandescent home interiors, lived-in domestic ambient" },
|
|
109
|
-
{ id: "temp-4000k", label: "4000K Mixed", category: "color-temperature", description: "Neutral white", promptHint: "4000K neutral white color temperature, balanced midpoint between warm tungsten and cool daylight, clean office and mixed-source feel without strong color cast" },
|
|
110
|
-
{ id: "temp-5600k", label: "5600K Daylight", category: "color-temperature", description: "Daylight-balanced midday sun", promptHint: "5600K daylight-balanced color temperature, neutral midday white sun with accurate color rendering and no warm or cool bias" },
|
|
111
|
-
{ id: "temp-6500k", label: "6500K Overcast", category: "color-temperature", description: "Slightly cool blue cast", promptHint: "6500K overcast-cool color temperature, slightly blue cast typical of overcast skies and high-noon shadow areas, subtly cool and clinical" },
|
|
112
|
-
{ id: "temp-9000k", label: "9000K Shade", category: "color-temperature", description: "Distinctly cool blue shade", promptHint: "9000K open-shade color temperature, distinctly cool blue cast found in deep shade and cloud-shadowed mountain air, chilled and atmospheric" },
|
|
118
|
+
{ id: "temp-2700k", label: "2700K Candle", category: "color-temperature", description: "Deep amber candle/tungsten", promptHint: "2700K warm candle and low-tungsten color temperature, deep amber and orange cast across the scene, intimate and cozy mood with rich golden highlights", term: "2700k candlelight color temperature" },
|
|
119
|
+
{ id: "temp-3200k", label: "3200K Tungsten", category: "color-temperature", description: "Warm yellow interior", promptHint: "3200K tungsten color temperature, warm yellow-orange cast typical of classic incandescent home interiors, lived-in domestic ambient", term: "3200k tungsten color temperature" },
|
|
120
|
+
{ id: "temp-4000k", label: "4000K Mixed", category: "color-temperature", description: "Neutral white", promptHint: "4000K neutral white color temperature, balanced midpoint between warm tungsten and cool daylight, clean office and mixed-source feel without strong color cast", term: "4000k neutral white color temperature" },
|
|
121
|
+
{ id: "temp-5600k", label: "5600K Daylight", category: "color-temperature", description: "Daylight-balanced midday sun", promptHint: "5600K daylight-balanced color temperature, neutral midday white sun with accurate color rendering and no warm or cool bias", term: "5600k daylight color temperature" },
|
|
122
|
+
{ id: "temp-6500k", label: "6500K Overcast", category: "color-temperature", description: "Slightly cool blue cast", promptHint: "6500K overcast-cool color temperature, slightly blue cast typical of overcast skies and high-noon shadow areas, subtly cool and clinical", term: "6500k overcast color temperature" },
|
|
123
|
+
{ id: "temp-9000k", label: "9000K Shade", category: "color-temperature", description: "Distinctly cool blue shade", promptHint: "9000K open-shade color temperature, distinctly cool blue cast found in deep shade and cloud-shadowed mountain air, chilled and atmospheric", term: "9000k open-shade color temperature" },
|
|
113
124
|
] as const
|
|
114
125
|
|
|
115
126
|
export const LIGHTING_CATEGORY_ORDER: ReadonlyArray<LightingCategory> = [
|
|
@@ -146,6 +157,16 @@ export function getLightingPromptHint(id: string | undefined | null): string {
|
|
|
146
157
|
return getLighting(id)?.promptHint ?? ""
|
|
147
158
|
}
|
|
148
159
|
|
|
160
|
+
/**
|
|
161
|
+
* The COMPACT counterpart of `getLightingPromptHint`: the short professional
|
|
162
|
+
* term ("rembrandt lighting", "1:4 lighting ratio", "rim backlight") a
|
|
163
|
+
* consumer injects instead of the full mechanism description. Same lookup,
|
|
164
|
+
* same empty-string-on-miss behavior.
|
|
165
|
+
*/
|
|
166
|
+
export function getLightingTerm(id: string | undefined | null): string {
|
|
167
|
+
return resolveTerm(getLighting(id))
|
|
168
|
+
}
|
|
169
|
+
|
|
149
170
|
export const LIGHTING_IDS: ReadonlyArray<string> = LIGHTINGS.map((l) => l.id)
|
|
150
171
|
|
|
151
172
|
/**
|
|
@@ -207,7 +228,9 @@ export function buildLightingHints(
|
|
|
207
228
|
lightingRatio?: unknown
|
|
208
229
|
colorTemperature?: unknown
|
|
209
230
|
},
|
|
231
|
+
mode: PickerHintMode = "full",
|
|
210
232
|
): string[] {
|
|
233
|
+
if (mode === "compact") return buildLightingTerms(data)
|
|
211
234
|
const hints: string[] = []
|
|
212
235
|
for (const category of LIGHTING_CATEGORY_ORDER) {
|
|
213
236
|
const field = LIGHTING_FIELD_BY_CATEGORY[category]
|
|
@@ -227,3 +250,41 @@ export function buildLightingHints(
|
|
|
227
250
|
}
|
|
228
251
|
return hints
|
|
229
252
|
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* The COMPACT counterpart of `buildLightingHints`: the same per-category walk
|
|
256
|
+
* in the same canonical order, emitting each selection's short professional
|
|
257
|
+
* term ("dusk lighting", "rembrandt lighting", "1:4 lighting ratio") instead
|
|
258
|
+
* of its full mechanism description.
|
|
259
|
+
*
|
|
260
|
+
* @param data the consumer data record (must include optional timeOfDay /
|
|
261
|
+
* lightingStyle / lightingDirection fields)
|
|
262
|
+
*/
|
|
263
|
+
export function buildLightingTerms(
|
|
264
|
+
data: Record<string, unknown> & {
|
|
265
|
+
timeOfDay?: unknown
|
|
266
|
+
lightingStyle?: unknown
|
|
267
|
+
lightingDirection?: unknown
|
|
268
|
+
lightingRatio?: unknown
|
|
269
|
+
colorTemperature?: unknown
|
|
270
|
+
},
|
|
271
|
+
): string[] {
|
|
272
|
+
const terms: string[] = []
|
|
273
|
+
for (const category of LIGHTING_CATEGORY_ORDER) {
|
|
274
|
+
const field = LIGHTING_FIELD_BY_CATEGORY[category]
|
|
275
|
+
const raw = data[field]
|
|
276
|
+
// lightingStyle accepts string | string[] (multi-pick max 2). Other
|
|
277
|
+
// categories are single-pick and may also tolerate arrays defensively.
|
|
278
|
+
if (typeof raw === "string" && raw.length > 0) {
|
|
279
|
+
const term = getLightingTerm(raw)
|
|
280
|
+
if (term) terms.push(term)
|
|
281
|
+
} else if (Array.isArray(raw)) {
|
|
282
|
+
for (const item of raw) {
|
|
283
|
+
if (typeof item !== "string" || item.length === 0) continue
|
|
284
|
+
const term = getLightingTerm(item)
|
|
285
|
+
if (term) terms.push(term)
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return terms
|
|
290
|
+
}
|
package/src/loop-subject.ts
CHANGED
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
* and lets us refine each library independently.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
import { resolveTerm } from "./term.js"
|
|
22
|
+
|
|
21
23
|
export type LoopSubjectCategory = "realistic" | "abstract"
|
|
22
24
|
|
|
23
25
|
export interface LoopSubject {
|
|
@@ -28,6 +30,11 @@ export interface LoopSubject {
|
|
|
28
30
|
/** Drop-in prompt text for Generate Image. Wired into the prompt input
|
|
29
31
|
* via FieldMappings, same as Setting / Motion / Mood Parameter nodes. */
|
|
30
32
|
readonly promptHint: string
|
|
33
|
+
/** Compact professional term for hint-compact mode (see `term.ts`). Authored
|
|
34
|
+
* only where the lowercased label is not what a professional would write —
|
|
35
|
+
* the "Tunnel — Exciting" style UI compounds and the generic subject
|
|
36
|
+
* labels ("Galaxy", "Underwater Light") that need their trade wording. */
|
|
37
|
+
readonly term?: string
|
|
31
38
|
}
|
|
32
39
|
|
|
33
40
|
export const LOOP_SUBJECT_CATEGORY_ORDER: ReadonlyArray<LoopSubjectCategory> = [
|
|
@@ -48,6 +55,7 @@ export const LOOP_SUBJECTS: ReadonlyArray<LoopSubject> = [
|
|
|
48
55
|
category: "realistic",
|
|
49
56
|
description: "Aurora borealis ribbons over a horizon",
|
|
50
57
|
promptHint: "aurora borealis ribbons in green and violet over a snowy mountain horizon, wide centered framing, low ambient starlight, deep cosmic backdrop, no foreground subject",
|
|
58
|
+
term: "aurora borealis",
|
|
51
59
|
},
|
|
52
60
|
{
|
|
53
61
|
id: "clouds",
|
|
@@ -104,6 +112,7 @@ export const LOOP_SUBJECTS: ReadonlyArray<LoopSubject> = [
|
|
|
104
112
|
category: "realistic",
|
|
105
113
|
description: "Spiral galaxy in deep space",
|
|
106
114
|
promptHint: "spiral galaxy with swirling arms of stars and luminous gas, dust lanes radiating from a bright core, centered radial composition, deep cosmic black background, no perspective depth",
|
|
115
|
+
term: "spiral galaxy",
|
|
107
116
|
},
|
|
108
117
|
{
|
|
109
118
|
id: "nebula",
|
|
@@ -118,6 +127,7 @@ export const LOOP_SUBJECTS: ReadonlyArray<LoopSubject> = [
|
|
|
118
127
|
category: "realistic",
|
|
119
128
|
description: "Light rays through forest canopy",
|
|
120
129
|
promptHint: "golden sunbeams cutting through a tall forest canopy with floating dust motes catching the light, centered vertical composition, deep green ambient tone, no human figures, no foreground subject",
|
|
130
|
+
term: "sunbeams through forest canopy",
|
|
121
131
|
},
|
|
122
132
|
{
|
|
123
133
|
id: "cherry-blossoms",
|
|
@@ -132,6 +142,7 @@ export const LOOP_SUBJECTS: ReadonlyArray<LoopSubject> = [
|
|
|
132
142
|
category: "realistic",
|
|
133
143
|
description: "Sunbeams and bubbles below water",
|
|
134
144
|
promptHint: "sunbeams cutting down through deep blue ocean water with rising silver air bubbles and floating particulate, centered cathedral-light composition, no surface horizon visible, no foreground subject",
|
|
145
|
+
term: "underwater god rays",
|
|
135
146
|
},
|
|
136
147
|
{
|
|
137
148
|
id: "embers",
|
|
@@ -148,6 +159,7 @@ export const LOOP_SUBJECTS: ReadonlyArray<LoopSubject> = [
|
|
|
148
159
|
category: "abstract",
|
|
149
160
|
description: "Fractal neon tunnel with depth",
|
|
150
161
|
promptHint: "infinite fractal tunnel of glowing neon ribbons receding into a vanishing point, centered symmetric composition, deep volumetric light, no foreground subject",
|
|
162
|
+
term: "infinite fractal neon tunnel",
|
|
151
163
|
},
|
|
152
164
|
{
|
|
153
165
|
id: "tunnel-clean",
|
|
@@ -155,6 +167,7 @@ export const LOOP_SUBJECTS: ReadonlyArray<LoopSubject> = [
|
|
|
155
167
|
category: "abstract",
|
|
156
168
|
description: "Periodic tunnel of geometric filaments",
|
|
157
169
|
promptHint: "infinite fractal tunnel of glowing neon geometric filaments, self-similar repeating depth that recurses to infinity, centered symmetric composition, deep volumetric light, dark void background, no foreground subject",
|
|
170
|
+
term: "self-similar geometric neon tunnel",
|
|
158
171
|
},
|
|
159
172
|
{
|
|
160
173
|
id: "kaleidoscope",
|
|
@@ -204,6 +217,7 @@ export const LOOP_SUBJECTS: ReadonlyArray<LoopSubject> = [
|
|
|
204
217
|
category: "abstract",
|
|
205
218
|
description: "Pulsing audio visualizer",
|
|
206
219
|
promptHint: "vertical audio equalizer bars in vibrant neon gradient pulsing at different heights, centered symmetric composition, dark backdrop with soft glow, repeating periodic structure, no foreground subject",
|
|
220
|
+
term: "audio equalizer bars",
|
|
207
221
|
},
|
|
208
222
|
{
|
|
209
223
|
id: "dna-helix",
|
|
@@ -211,6 +225,7 @@ export const LOOP_SUBJECTS: ReadonlyArray<LoopSubject> = [
|
|
|
211
225
|
category: "abstract",
|
|
212
226
|
description: "Rotating double helix",
|
|
213
227
|
promptHint: "glowing neon DNA double helix structure with periodic identical rungs, centered vertical symmetric composition, electric cyan and magenta strands, dark void background, fractal repeating geometry, no foreground subject",
|
|
228
|
+
term: "dna double helix",
|
|
214
229
|
},
|
|
215
230
|
{
|
|
216
231
|
id: "liquid-chrome",
|
|
@@ -260,10 +275,11 @@ export const LOOP_SUBJECTS: ReadonlyArray<LoopSubject> = [
|
|
|
260
275
|
category: "abstract",
|
|
261
276
|
description: "Shifting platonic solids",
|
|
262
277
|
promptHint: "abstract array of glowing neon platonic solid wireframes morphing through self-similar fractal subdivisions, centered radial symmetric composition, deep dark backdrop, electric rim lighting, no foreground subject",
|
|
278
|
+
term: "morphing platonic solid wireframes",
|
|
263
279
|
},
|
|
264
280
|
]
|
|
265
281
|
|
|
266
|
-
export function getLoopSubject(id: string): LoopSubject | undefined {
|
|
282
|
+
export function getLoopSubject(id: string | undefined | null): LoopSubject | undefined {
|
|
267
283
|
return LOOP_SUBJECTS.find((s) => s.id === id)
|
|
268
284
|
}
|
|
269
285
|
|
|
@@ -274,3 +290,13 @@ export function getLoopSubjectLabel(id: string): string {
|
|
|
274
290
|
export function getLoopSubjectPromptHint(id: string): string {
|
|
275
291
|
return getLoopSubject(id)?.promptHint ?? ""
|
|
276
292
|
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Compact professional term for the subject — the short phrase a VJ or
|
|
296
|
+
* cinematographer would write when the consumer wants a term instead of the
|
|
297
|
+
* full scene paragraph. Mirrors `getLoopSubjectPromptHint`'s lookup so the two
|
|
298
|
+
* can never describe different entries.
|
|
299
|
+
*/
|
|
300
|
+
export function getLoopSubjectTerm(id: string | undefined | null): string {
|
|
301
|
+
return resolveTerm(getLoopSubject(id))
|
|
302
|
+
}
|