@nodaro/prompts 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +105 -0
- package/README.md +27 -0
- package/dist/index.cjs +21240 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3599 -0
- package/dist/index.d.ts +3599 -0
- package/dist/index.js +20854 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -0
- package/src/__tests__/__snapshots__/prompt-builder-segments.test.ts.snap +65 -0
- package/src/__tests__/action-fx.test.ts +155 -0
- package/src/__tests__/apply-picker-json.test.ts +50 -0
- package/src/__tests__/assemble-image-input.test.ts +248 -0
- package/src/__tests__/assemble-suno-input.test.ts +283 -0
- package/src/__tests__/brand-tokens.test.ts +81 -0
- package/src/__tests__/build-image-prompt-element-injection.test.ts +118 -0
- package/src/__tests__/build-image-prompt-hybrid-format.test.ts +131 -0
- package/src/__tests__/build-image-prompt-mentions.test.ts +809 -0
- package/src/__tests__/build-image-prompt-reference-cap.test.ts +57 -0
- package/src/__tests__/build-image-prompt-reference-numbering.test.ts +237 -0
- package/src/__tests__/build-image-prompt-reference-order.test.ts +313 -0
- package/src/__tests__/camera-motions-from-connections.test.ts +71 -0
- package/src/__tests__/catalog-gapfill.test.ts +53 -0
- package/src/__tests__/character-convergence-image.test.ts +217 -0
- package/src/__tests__/character-default-role-image.test.ts +167 -0
- package/src/__tests__/character-default-role-video.test.ts +168 -0
- package/src/__tests__/character-default-role.test.ts +70 -0
- package/src/__tests__/character-fx.test.ts +200 -0
- package/src/__tests__/entity-prompts-location.test.ts +97 -0
- package/src/__tests__/entity-prompts.test.ts +240 -0
- package/src/__tests__/expand-extra-refs-role.test.ts +50 -0
- package/src/__tests__/factory-presets.test.ts +1045 -0
- package/src/__tests__/factory-snippets.test.ts +68 -0
- package/src/__tests__/framing-multi.test.ts +71 -0
- package/src/__tests__/framing-vantage.test.ts +39 -0
- package/src/__tests__/i18n-entry-completeness.test.ts +269 -0
- package/src/__tests__/identity-lock.test.ts +46 -0
- package/src/__tests__/instrumentation.test.ts +68 -0
- package/src/__tests__/lighting-multi.test.ts +68 -0
- package/src/__tests__/location-convergence-image.test.ts +124 -0
- package/src/__tests__/mention-lock-flag.test.ts +499 -0
- package/src/__tests__/multi-picker-spec.test.ts +71 -0
- package/src/__tests__/music-genre.test.ts +103 -0
- package/src/__tests__/music-mood.test.ts +87 -0
- package/src/__tests__/object-creature-convergence-image.test.ts +105 -0
- package/src/__tests__/parameter-prompt-hint.test.ts +270 -0
- package/src/__tests__/parameter-registry-sync.test.ts +243 -0
- package/src/__tests__/person-age.test.ts +80 -0
- package/src/__tests__/person-analyzer-invariants.test.ts +47 -0
- package/src/__tests__/person-body-axes.test.ts +67 -0
- package/src/__tests__/person-facial-geometry.test.ts +156 -0
- package/src/__tests__/person-regional-aesthetic.test.ts +161 -0
- package/src/__tests__/person-sections.test.ts +18 -0
- package/src/__tests__/picker-analyzer-registry.test.ts +108 -0
- package/src/__tests__/picker-catalogs-project.test.ts +85 -0
- package/src/__tests__/picker-catalogs.test.ts +53 -0
- package/src/__tests__/picker-limits.test.ts +20 -0
- package/src/__tests__/prompt-builder-segments.test.ts +183 -0
- package/src/__tests__/prompt-builder-structured-fields.test.ts +40 -0
- package/src/__tests__/prompt-builder.test.ts +1773 -0
- package/src/__tests__/prompt-wizard-categories.test.ts +31 -0
- package/src/__tests__/provider-prompt-doctrine.test.ts +49 -0
- package/src/__tests__/resolve-prompt-append.test.ts +58 -0
- package/src/__tests__/resolve-prompt.test.ts +44 -0
- package/src/__tests__/role-picker-shared.test.ts +208 -0
- package/src/__tests__/seedance-2-inputs.test.ts +173 -0
- package/src/__tests__/seedance-extend.test.ts +44 -0
- package/src/__tests__/sound-aggregator.test.ts +350 -0
- package/src/__tests__/style-presets.test.ts +34 -0
- package/src/__tests__/temporal-multi.test.ts +74 -0
- package/src/__tests__/transitions.test.ts +213 -0
- package/src/__tests__/video-reference-features.test.ts +41 -0
- package/src/__tests__/video-reference-leading-refs.test.ts +90 -0
- package/src/__tests__/video-reference-resolver.test.ts +233 -0
- package/src/__tests__/video-reference-roles.test.ts +96 -0
- package/src/__tests__/voice-character.test.ts +48 -0
- package/src/__tests__/voice-delivery.test.ts +41 -0
- package/src/__tests__/wardrobe.test.ts +25 -0
- package/src/action-fx.ts +255 -0
- package/src/aesthetic.ts +435 -0
- package/src/assemble-image-input.ts +236 -0
- package/src/assemble-suno-input.ts +147 -0
- package/src/atmosphere.ts +104 -0
- package/src/backdrop.ts +131 -0
- package/src/brand-tokens.ts +154 -0
- package/src/camera-format.ts +76 -0
- package/src/camera-motions.ts +615 -0
- package/src/character-fx.ts +274 -0
- package/src/color-look.ts +103 -0
- package/src/composition-effects.ts +67 -0
- package/src/entity-prompts.ts +231 -0
- package/src/era.ts +292 -0
- package/src/exposure-settings.ts +142 -0
- package/src/factory-presets/generate-image.ts +1644 -0
- package/src/factory-presets/generate-video.ts +1116 -0
- package/src/factory-presets/index.ts +46 -0
- package/src/factory-presets/lottie-overlay.ts +166 -0
- package/src/factory-presets/motion-graphics.ts +350 -0
- package/src/factory-presets/music.ts +734 -0
- package/src/factory-presets/sfx.ts +136 -0
- package/src/factory-presets/shared-image.ts +207 -0
- package/src/factory-presets/switchx.ts +65 -0
- package/src/factory-presets/text.ts +292 -0
- package/src/factory-presets/types.ts +51 -0
- package/src/factory-presets/video-edit.ts +136 -0
- package/src/factory-presets/voice.ts +172 -0
- package/src/factory-presets.ts +2 -0
- package/src/factory-snippets/catalog.ts +105 -0
- package/src/factory-snippets/index.ts +16 -0
- package/src/factory-snippets/types.ts +33 -0
- package/src/framing.ts +634 -0
- package/src/held-prop.ts +187 -0
- package/src/identity-lock.ts +213 -0
- package/src/index.ts +66 -0
- package/src/instrumentation.ts +337 -0
- package/src/lens.ts +59 -0
- package/src/lighting.ts +229 -0
- package/src/loop-subject.ts +276 -0
- package/src/materials.ts +184 -0
- package/src/mood.ts +186 -0
- package/src/music-genre.ts +662 -0
- package/src/music-mood.ts +137 -0
- package/src/object-asset-presets.ts +81 -0
- package/src/parameter-prompt-hint.ts +281 -0
- package/src/person.ts +1368 -0
- package/src/photo-genre.ts +151 -0
- package/src/photographer.ts +612 -0
- package/src/picker-analyzer-registry.ts +374 -0
- package/src/picker-catalogs.ts +858 -0
- package/src/pose.ts +246 -0
- package/src/post-process-effects.ts +94 -0
- package/src/prompt-builder-structured-fields.ts +116 -0
- package/src/prompt-builder.ts +2964 -0
- package/src/prompt-templates.ts +50 -0
- package/src/prompt-wizard-categories.ts +334 -0
- package/src/provider-prompt-doctrine.ts +85 -0
- package/src/render-quality.ts +89 -0
- package/src/resolve-prompt.ts +120 -0
- package/src/seedance-2-inputs.ts +100 -0
- package/src/setting.ts +130 -0
- package/src/sound-aggregator.ts +241 -0
- package/src/style-presets.ts +162 -0
- package/src/style.ts +99 -0
- package/src/styling.ts +585 -0
- package/src/temporal.ts +151 -0
- package/src/transitions.ts +333 -0
- package/src/video-reference-resolver.ts +823 -0
- package/src/voice-character.ts +237 -0
- package/src/voice-delivery.ts +142 -0
- package/src/wardrobe.ts +179 -0
package/src/materials.ts
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical catalog of material presets ("Material").
|
|
3
|
+
*
|
|
4
|
+
* Material dimension — *what something is made of*. Works universally across
|
|
5
|
+
* subjects (clothing, skin, body) and objects (furniture, vehicles, props,
|
|
6
|
+
* surfaces). The same catalog can describe a silk dress, a chrome sculpture of
|
|
7
|
+
* a person, a leather pillow, or a plastic train.
|
|
8
|
+
*
|
|
9
|
+
* Grammar: every entry's `promptHint` begins with `"made of ..."` — this reads
|
|
10
|
+
* correctly regardless of target ("a dress made of silk", "a human made of
|
|
11
|
+
* glass", "a pillow made of leather", "a train made of plastic").
|
|
12
|
+
*
|
|
13
|
+
* For clothing-specific phrasing ("wearing silk"), see the `fabric` dimension
|
|
14
|
+
* on the Styling node. There is intentional overlap in vocabulary (leather,
|
|
15
|
+
* silk, velvet appear in both) — Material uses the universal `"made of"`
|
|
16
|
+
* grammar, Fabric uses the wardrobe-native `"wearing"` grammar.
|
|
17
|
+
*
|
|
18
|
+
* Shared between the picker UI, the standalone Material parameter node, and
|
|
19
|
+
* the prompt-hint injection on both the frontend DAG executor and the
|
|
20
|
+
* backend orchestrator.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export type MaterialCategory =
|
|
24
|
+
| "fabric"
|
|
25
|
+
| "metal"
|
|
26
|
+
| "stone"
|
|
27
|
+
| "wood"
|
|
28
|
+
| "glass-ceramic"
|
|
29
|
+
| "natural"
|
|
30
|
+
| "exotic"
|
|
31
|
+
|
|
32
|
+
export interface Material {
|
|
33
|
+
readonly id: string
|
|
34
|
+
readonly label: string
|
|
35
|
+
readonly category: MaterialCategory
|
|
36
|
+
readonly description: string
|
|
37
|
+
readonly promptHint: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const MATERIALS: ReadonlyArray<Material> = [
|
|
41
|
+
// -------------------- Fabric --------------------
|
|
42
|
+
{ id: "silk", label: "Silk", category: "fabric", description: "Smooth glossy silk", promptHint: "made of smooth glossy silk with a subtle natural sheen and delicate fluid drape" },
|
|
43
|
+
{ id: "cotton", label: "Cotton", category: "fabric", description: "Soft matte cotton", promptHint: "made of soft matte cotton fabric with a natural woven texture and subtle wrinkles" },
|
|
44
|
+
{ id: "denim", label: "Denim", category: "fabric", description: "Heavy indigo denim", promptHint: "made of heavy indigo denim with visible diagonal weave, worn edges and subtle fading" },
|
|
45
|
+
{ id: "leather", label: "Leather", category: "fabric", description: "Rich supple leather", promptHint: "made of rich supple leather with a soft satin sheen, natural grain and warm brown tones" },
|
|
46
|
+
{ id: "velvet", label: "Velvet", category: "fabric", description: "Plush velvet", promptHint: "made of plush velvet with a deep soft nap, rich saturated color and directional sheen" },
|
|
47
|
+
{ id: "satin", label: "Satin", category: "fabric", description: "Glossy satin", promptHint: "made of glossy satin with a lustrous mirror-like surface and fluid draping folds" },
|
|
48
|
+
{ id: "lace", label: "Lace", category: "fabric", description: "Delicate patterned lace", promptHint: "made of delicate patterned lace with intricate floral openwork and a fine translucent texture" },
|
|
49
|
+
{ id: "wool", label: "Wool", category: "fabric", description: "Warm woven wool", promptHint: "made of warm woven wool with a soft matte surface, visible fibers and a cozy textured feel" },
|
|
50
|
+
{ id: "linen", label: "Linen", category: "fabric", description: "Natural textured linen", promptHint: "made of natural linen with a loose open weave, slight slubs and a slightly wrinkled airy drape" },
|
|
51
|
+
{ id: "tweed", label: "Tweed", category: "fabric", description: "Rustic woven tweed", promptHint: "made of rustic tweed with a flecked multi-color woven texture and a rough heritage feel" },
|
|
52
|
+
{ id: "cashmere", label: "Cashmere", category: "fabric", description: "Luxurious soft cashmere", promptHint: "made of luxurious cashmere with an ultra-soft matte texture and a fine dense weave" },
|
|
53
|
+
{ id: "chiffon", label: "Chiffon", category: "fabric", description: "Sheer flowing chiffon", promptHint: "made of sheer chiffon with a lightweight floating drape, soft translucent layers and a gentle shimmer" },
|
|
54
|
+
{ id: "fur", label: "Fur", category: "fabric", description: "Thick plush fur", promptHint: "made of thick plush fur with long dense strands, natural variation and a soft directional flow" },
|
|
55
|
+
{ id: "suede", label: "Suede", category: "fabric", description: "Soft napped suede", promptHint: "made of soft napped suede with a matte velvety surface, fine fuzzy texture and a warm leather feel" },
|
|
56
|
+
{ id: "mesh", label: "Mesh", category: "fabric", description: "See-through net mesh", promptHint: "made of see-through net mesh with an open woven grid, sheer transparency and an athletic technical feel" },
|
|
57
|
+
{ id: "patent-leather", label: "Patent Leather", category: "fabric", description: "High-gloss patent leather", promptHint: "made of high-gloss patent leather with a mirror-bright reflective surface, deep saturated color and a slick lacquered finish" },
|
|
58
|
+
|
|
59
|
+
// -------------------- Metal --------------------
|
|
60
|
+
{ id: "gold", label: "Gold", category: "metal", description: "Polished gold", promptHint: "made of polished gold with a warm yellow metallic sheen and rich mirror-like reflections" },
|
|
61
|
+
{ id: "silver", label: "Silver", category: "metal", description: "Polished silver", promptHint: "made of polished silver with a cool bright metallic sheen and clean mirror-like reflections" },
|
|
62
|
+
{ id: "bronze", label: "Bronze", category: "metal", description: "Patinaed cast bronze", promptHint: "made of cast bronze with a warm brown-gold metallic surface and a mottled greenish patina in the recesses" },
|
|
63
|
+
{ id: "chrome", label: "Chrome", category: "metal", description: "Hyper-reflective chrome", promptHint: "made of hyper-reflective polished chrome with liquid mirror surfaces and sharp environmental reflections" },
|
|
64
|
+
{ id: "copper", label: "Copper", category: "metal", description: "Warm copper with patina", promptHint: "made of warm copper with a rich rose-orange metallic gleam and touches of blue-green oxidation" },
|
|
65
|
+
{ id: "brass", label: "Brass", category: "metal", description: "Antique brass", promptHint: "made of antique brass with a warm yellow-gold hue, brushed texture and slight tarnish in the crevices" },
|
|
66
|
+
{ id: "steel", label: "Steel", category: "metal", description: "Brushed stainless steel", promptHint: "made of brushed stainless steel with fine directional grain and cool soft reflections" },
|
|
67
|
+
{ id: "iron", label: "Iron", category: "metal", description: "Rough wrought iron", promptHint: "made of rough wrought iron with a dark matte surface, hammered texture and traces of rust" },
|
|
68
|
+
{ id: "platinum", label: "Platinum", category: "metal", description: "Lustrous platinum", promptHint: "made of lustrous platinum with a cool white-grey metallic sheen and premium polished finish" },
|
|
69
|
+
{ id: "titanium", label: "Titanium", category: "metal", description: "Matte industrial titanium", promptHint: "made of matte titanium with a cool silvery-grey surface, subtle anodized tints and an industrial precision finish" },
|
|
70
|
+
|
|
71
|
+
// -------------------- Stone --------------------
|
|
72
|
+
{ id: "marble", label: "Marble", category: "stone", description: "White marble with veins", promptHint: "made of polished white marble with grey-blue veining, a smooth glossy surface and classical elegance" },
|
|
73
|
+
{ id: "granite", label: "Granite", category: "stone", description: "Speckled polished granite", promptHint: "made of polished granite with a speckled grey-black crystalline surface and a cool glossy finish" },
|
|
74
|
+
{ id: "obsidian", label: "Obsidian", category: "stone", description: "Glossy black obsidian", promptHint: "made of polished black obsidian with a deep glassy surface, subtle rainbow flecks and razor-sharp highlights" },
|
|
75
|
+
{ id: "sandstone", label: "Sandstone", category: "stone", description: "Warm layered sandstone", promptHint: "made of warm weathered sandstone with horizontal layered striations, soft ochre tones and a rough grainy surface" },
|
|
76
|
+
{ id: "slate", label: "Slate", category: "stone", description: "Dark flat slate", promptHint: "made of dark slate with flat matte grey-blue surfaces, subtle cleavage lines and a cool sedimentary texture" },
|
|
77
|
+
{ id: "jade", label: "Jade", category: "stone", description: "Translucent green jade", promptHint: "made of polished jade with a translucent green glow, fine internal veining and a smooth waxy surface" },
|
|
78
|
+
{ id: "onyx", label: "Onyx", category: "stone", description: "Banded polished onyx", promptHint: "made of polished onyx with dramatic black-and-white banding, translucent depth and a glossy finish" },
|
|
79
|
+
{ id: "concrete", label: "Concrete", category: "stone", description: "Cast industrial concrete", promptHint: "made of cast concrete with a rough grey surface, visible formwork lines, scattered aggregate and an industrial brutalist feel" },
|
|
80
|
+
{ id: "terrazzo", label: "Terrazzo", category: "stone", description: "Composite terrazzo with chips", promptHint: "made of polished terrazzo with embedded marble and glass chips suspended in a smooth cement matrix, a mid-century speckled surface and a glossy finish" },
|
|
81
|
+
|
|
82
|
+
// -------------------- Wood --------------------
|
|
83
|
+
{ id: "oak", label: "Oak", category: "wood", description: "Rich grained oak", promptHint: "made of rich grained oak with warm honey-brown tones, strong vertical grain lines and a satin finish" },
|
|
84
|
+
{ id: "mahogany", label: "Mahogany", category: "wood", description: "Deep red mahogany", promptHint: "made of polished mahogany with a deep reddish-brown tone, tight swirling grain and a glossy heirloom finish" },
|
|
85
|
+
{ id: "walnut", label: "Walnut", category: "wood", description: "Dark walnut", promptHint: "made of walnut with deep chocolate-brown tones, flowing grain patterns and a soft satin sheen" },
|
|
86
|
+
{ id: "bamboo", label: "Bamboo", category: "wood", description: "Light segmented bamboo", promptHint: "made of pale bamboo with visible horizontal node segments, clean vertical grain and a light natural finish" },
|
|
87
|
+
{ id: "birch", label: "Birch", category: "wood", description: "Pale smooth birch", promptHint: "made of pale birch with fine close grain, a smooth cream-white surface and subtle warmth" },
|
|
88
|
+
{ id: "driftwood", label: "Driftwood", category: "wood", description: "Weathered driftwood", promptHint: "made of weathered driftwood with silver-grey sun-bleached surfaces, smoothed edges and a raw organic texture" },
|
|
89
|
+
|
|
90
|
+
// -------------------- Glass / Ceramic --------------------
|
|
91
|
+
{ id: "glass", label: "Glass", category: "glass-ceramic", description: "Clear transparent glass", promptHint: "made of clear transparent glass with sharp refracted highlights, crisp edge caustics and subtle internal reflections" },
|
|
92
|
+
{ id: "stained-glass", label: "Stained Glass", category: "glass-ceramic", description: "Jewel-toned stained glass", promptHint: "made of stained glass with jewel-toned panels, dark lead caming and vibrant light filtering through saturated color" },
|
|
93
|
+
{ id: "crystal", label: "Crystal", category: "glass-ceramic", description: "Faceted clear crystal", promptHint: "made of faceted clear crystal with sharp prismatic facets, rainbow caustics and brilliant internal reflections" },
|
|
94
|
+
{ id: "porcelain", label: "Porcelain", category: "glass-ceramic", description: "Smooth white porcelain", promptHint: "made of smooth white porcelain with a soft satin glaze, delicate translucency and a fine ceramic finish" },
|
|
95
|
+
{ id: "ceramic-glazed", label: "Glazed Ceramic", category: "glass-ceramic", description: "Earthy glazed ceramic", promptHint: "made of glazed ceramic with warm earth tones, a glossy vitrified surface and subtle kiln-fired variation" },
|
|
96
|
+
{ id: "terracotta", label: "Terracotta", category: "glass-ceramic", description: "Warm unglazed terracotta", promptHint: "made of unglazed terracotta with a warm orange-brown matte surface, fine clay texture and a rustic handmade feel" },
|
|
97
|
+
|
|
98
|
+
// -------------------- Natural / Elemental --------------------
|
|
99
|
+
{ id: "water", label: "Water", category: "natural", description: "Flowing translucent water", promptHint: "made of flowing translucent water with dynamic refractions, moving highlights and rippled internal caustics" },
|
|
100
|
+
{ id: "fire", label: "Fire", category: "natural", description: "Living flame", promptHint: "made of living flame with dancing orange-yellow tongues, glowing ember cores and wisps of drifting smoke" },
|
|
101
|
+
{ id: "ice", label: "Ice", category: "natural", description: "Translucent crystalline ice", promptHint: "made of translucent crystalline ice with internal fractures, cool blue highlights and a frosted glossy surface" },
|
|
102
|
+
{ id: "smoke", label: "Smoke", category: "natural", description: "Drifting ethereal smoke", promptHint: "made of drifting ethereal smoke with soft volumetric wisps, translucent layers and a slow hypnotic flow" },
|
|
103
|
+
{ id: "sand", label: "Sand", category: "natural", description: "Fine granular sand", promptHint: "made of fine granular sand with a soft golden matte surface, subtle grain texture and gentle shifting edges" },
|
|
104
|
+
{ id: "moss", label: "Moss", category: "natural", description: "Lush living moss", promptHint: "made of lush living moss with a soft velvety green surface, fine plant texture and an organic overgrown feel" },
|
|
105
|
+
{ id: "leaves", label: "Leaves", category: "natural", description: "Layered plant leaves", promptHint: "made of layered plant leaves with overlapping green foliage, visible veining and a natural dappled texture" },
|
|
106
|
+
|
|
107
|
+
// -------------------- Exotic / Futuristic --------------------
|
|
108
|
+
{ id: "holographic", label: "Holographic", category: "exotic", description: "Iridescent hologram", promptHint: "made of holographic iridescent material with shifting rainbow sheen, prismatic highlights and a futuristic shimmer" },
|
|
109
|
+
{ id: "liquid-metal", label: "Liquid Metal", category: "exotic", description: "Reflective liquid chrome", promptHint: "made of reflective liquid metal with a flowing mercury-like chrome surface, seamless reflections and metallic pooling highlights" },
|
|
110
|
+
{ id: "neon", label: "Neon Glow", category: "exotic", description: "Glowing neon tubing", promptHint: "made of glowing neon tubing with saturated magenta and cyan light, a soft halo glow and a cybernetic futuristic feel" },
|
|
111
|
+
{ id: "translucent", label: "Translucent Resin", category: "exotic", description: "Frosted glowing resin", promptHint: "made of frosted translucent resin with soft internal glow, milky subsurface scattering and a smooth cast finish" },
|
|
112
|
+
{ id: "subsurface", label: "Subsurface Glow", category: "exotic", description: "Light glows beneath the surface", promptHint: "made of a soft translucent material with pronounced subsurface scattering, light penetrating beneath the surface and glowing warmly from within" },
|
|
113
|
+
{ id: "mirror", label: "Mirror", category: "exotic", description: "Perfect mirror surface", promptHint: "made of perfect mirror surface with flawless reflections, no tint and razor-sharp reflected detail" },
|
|
114
|
+
{ id: "plasma", label: "Plasma", category: "exotic", description: "Glowing electric plasma", promptHint: "made of glowing electric plasma with arcing internal bolts, a radiant violet-pink core and a haze of ionized energy" },
|
|
115
|
+
{ id: "crystal-shard", label: "Crystal Shards", category: "exotic", description: "Shattered glowing crystal", promptHint: "made of fractured glowing crystal shards with sharp prismatic facets, internal luminescence and dynamic rainbow refraction" },
|
|
116
|
+
{ id: "obsidian-glass", label: "Obsidian Glass", category: "exotic", description: "Dark volcanic glass", promptHint: "made of dark obsidian volcanic glass with a glossy black surface, razor-sharp edges and subtle iridescent highlights" },
|
|
117
|
+
{ id: "iridescent", label: "Iridescent", category: "exotic", description: "Color-shifting iridescent surface", promptHint: "made of iridescent rainbow-shifting surface, the kind of color play seen on oil slicks, butterfly wings and mother-of-pearl, with hues that shift as the angle changes" },
|
|
118
|
+
{ id: "mother-of-pearl", label: "Mother-of-Pearl", category: "exotic", description: "Pearlescent inner shell layer", promptHint: "made of mother-of-pearl with a pearlescent cream surface, soft iridescent shimmer and the layered nacre depth seen in inlay work and fine jewelry" },
|
|
119
|
+
{ id: "carbon-fiber", label: "Carbon Fiber", category: "exotic", description: "Woven black carbon-fiber composite", promptHint: "made of woven carbon-fiber composite with a glossy black checkered weave pattern, a hi-tech aerospace feel and subtle directional sheen" },
|
|
120
|
+
{ id: "holographic-film", label: "Holographic Film", category: "exotic", description: "Light-refracting holographic film", promptHint: "made of light-refracting holographic film with a thin reflective sheet surface, prismatic rainbow shimmer and shifting spectral highlights as the angle changes" },
|
|
121
|
+
] as const
|
|
122
|
+
|
|
123
|
+
const materialById = new Map<string, Material>(MATERIALS.map((m) => [m.id, m]))
|
|
124
|
+
|
|
125
|
+
export function getMaterial(id: string | undefined | null): Material | undefined {
|
|
126
|
+
if (!id) return undefined
|
|
127
|
+
return materialById.get(id)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function getMaterialLabel(id: string | undefined | null, fallback?: string): string {
|
|
131
|
+
const m = getMaterial(id)
|
|
132
|
+
if (m) return m.label
|
|
133
|
+
if (fallback !== undefined) return fallback
|
|
134
|
+
return (id ?? "").replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function getMaterialPromptHint(id: string | undefined | null): string {
|
|
138
|
+
return getMaterial(id)?.promptHint ?? ""
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Multi-pick: 1-2 material ids → composite material clause. Single → entry's
|
|
143
|
+
* own promptHint. Two → "made of {A} and {B}" using lowercased entry labels.
|
|
144
|
+
* Covers leather+brass handbag, wood+steel chair, glass+chrome lamp, etc.
|
|
145
|
+
*/
|
|
146
|
+
export function buildMaterialHints(value: unknown): string {
|
|
147
|
+
const ids: string[] = []
|
|
148
|
+
if (typeof value === "string" && value) ids.push(value)
|
|
149
|
+
else if (Array.isArray(value)) {
|
|
150
|
+
for (const v of value) {
|
|
151
|
+
if (typeof v === "string" && v && !ids.includes(v)) ids.push(v)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (ids.length === 0) return ""
|
|
155
|
+
if (ids.length === 1) return getMaterialPromptHint(ids[0])
|
|
156
|
+
const labels = ids
|
|
157
|
+
.slice(0, 2)
|
|
158
|
+
.map((id) => getMaterial(id)?.label?.toLowerCase() ?? "")
|
|
159
|
+
.filter((s): s is string => Boolean(s))
|
|
160
|
+
if (labels.length < 2) return getMaterialPromptHint(ids[0])
|
|
161
|
+
return `made of ${labels[0]} and ${labels[1]}`
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export const MATERIAL_IDS: ReadonlyArray<string> = MATERIALS.map((m) => m.id)
|
|
165
|
+
|
|
166
|
+
export const MATERIAL_CATEGORY_LABELS: Readonly<Record<MaterialCategory, string>> = {
|
|
167
|
+
fabric: "Fabric",
|
|
168
|
+
metal: "Metal",
|
|
169
|
+
stone: "Stone",
|
|
170
|
+
wood: "Wood",
|
|
171
|
+
"glass-ceramic": "Glass / Ceramic",
|
|
172
|
+
natural: "Natural",
|
|
173
|
+
exotic: "Exotic",
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export const MATERIAL_CATEGORY_ORDER: ReadonlyArray<MaterialCategory> = [
|
|
177
|
+
"fabric",
|
|
178
|
+
"metal",
|
|
179
|
+
"stone",
|
|
180
|
+
"wood",
|
|
181
|
+
"glass-ceramic",
|
|
182
|
+
"natural",
|
|
183
|
+
"exotic",
|
|
184
|
+
]
|
package/src/mood.ts
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical catalog of Mood / emotional-state choices.
|
|
3
|
+
*
|
|
4
|
+
* Single-pick parameter node — user picks ONE mood that describes the
|
|
5
|
+
* subject's emotional state. The promptHint captures the natural
|
|
6
|
+
* consequence on face + body language (a happy mood → "with a warm smile
|
|
7
|
+
* and bright eyes", a fierce mood → "with an intense, fierce expression").
|
|
8
|
+
*
|
|
9
|
+
* Separate from:
|
|
10
|
+
* - Tone (the overall content/writing tone — sarcastic, playful, formal)
|
|
11
|
+
* - Atmosphere (what's in the air — fog, rain, dust)
|
|
12
|
+
* - Style (artistic medium — oil painting, photorealistic)
|
|
13
|
+
*
|
|
14
|
+
* Applies to both image and video consumers (mood describes the subject,
|
|
15
|
+
* not video-specific). Not in STILL_IMAGE_EXCLUDE_TYPES.
|
|
16
|
+
*
|
|
17
|
+
* Includes pre/post free-text fields (same pattern as Person) for
|
|
18
|
+
* specifics the catalog can't express ("restrained grief", "crying with
|
|
19
|
+
* relief", etc.).
|
|
20
|
+
*
|
|
21
|
+
* Shared between the picker UI, the standalone Mood parameter node, and
|
|
22
|
+
* the prompt-hint injection on both the frontend DAG executor and the
|
|
23
|
+
* backend orchestrator.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
export type MoodCategory = "positive" | "negative" | "neutral" | "intense"
|
|
27
|
+
|
|
28
|
+
export interface Mood {
|
|
29
|
+
readonly id: string
|
|
30
|
+
readonly label: string
|
|
31
|
+
readonly category: MoodCategory
|
|
32
|
+
readonly description: string
|
|
33
|
+
readonly promptHint: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const MOODS: ReadonlyArray<Mood> = [
|
|
37
|
+
// -------------------- Positive --------------------
|
|
38
|
+
{ id: "happy", label: "Happy", category: "positive", description: "Warm, smiling happiness", promptHint: "with a warm, happy expression and a genuine smile" },
|
|
39
|
+
{ id: "joyful", label: "Joyful", category: "positive", description: "Radiant, unrestrained joy", promptHint: "with a radiant, joyful expression full of delight, the corners of the mouth rising uncontrollably, steps light" },
|
|
40
|
+
{ id: "relieved", label: "Relieved", category: "positive", description: "Tension releasing into calm", promptHint: "with a relieved expression, letting out a long breath, shoulders relaxing completely, a faint long-awaited smile" },
|
|
41
|
+
{ id: "serene", label: "Serene", category: "positive", description: "Calm, peaceful contentment", promptHint: "with a serene, peaceful expression and relaxed posture" },
|
|
42
|
+
{ id: "playful", label: "Playful", category: "positive", description: "Mischievous, playful energy", promptHint: "with a playful, mischievous expression and light energy" },
|
|
43
|
+
{ id: "confident", label: "Confident", category: "positive", description: "Self-assured, confident", promptHint: "with a confident, self-assured expression and poised demeanor" },
|
|
44
|
+
{ id: "loving", label: "Loving", category: "positive", description: "Tender, affectionate", promptHint: "with a tender, loving expression" },
|
|
45
|
+
{ id: "amused", label: "Amused", category: "positive", description: "Subtly amused, smirking", promptHint: "with a subtly amused expression, a faint smirk" },
|
|
46
|
+
{ id: "smirking", label: "Smirking", category: "neutral", description: "Cocky, arrogant amusement", promptHint: "with a cocky, arrogant smirk and one eyebrow slightly raised" },
|
|
47
|
+
{ id: "eccentric", label: "Eccentric", category: "positive", description: "Quirky, unconventional", promptHint: "with a quirky, eccentric expression and offbeat playful energy" },
|
|
48
|
+
{ id: "hopeful", label: "Hopeful", category: "positive", description: "Bright-eyed, optimistic", promptHint: "with a hopeful expression, a soft slight smile and bright, expectant eyes" },
|
|
49
|
+
|
|
50
|
+
// -------------------- Negative --------------------
|
|
51
|
+
{ id: "sad", label: "Sad", category: "negative", description: "Quietly sad, downcast", promptHint: "with a quietly sad, downcast expression, head lowered, shoulders trembling slightly, eyes reddening" },
|
|
52
|
+
{ id: "angry", label: "Angry", category: "negative", description: "Clear anger, tension", promptHint: "with an angry expression, furrowed brow and tight jaw, fists clenched, chest heaving" },
|
|
53
|
+
{ id: "afraid", label: "Afraid", category: "negative", description: "Frightened, wide-eyed", promptHint: "with a frightened expression, wide eyes and tense posture" },
|
|
54
|
+
{ id: "anxious", label: "Anxious", category: "negative", description: "Nervous, worried", promptHint: "with an anxious, worried expression and restless tension, fingers tapping, eyes darting, breath quickening" },
|
|
55
|
+
{ id: "melancholy", label: "Melancholy", category: "negative", description: "Wistful sadness", promptHint: "with a melancholy, wistful expression lost in thought" },
|
|
56
|
+
{ id: "devastated", label: "Devastated", category: "negative", description: "Heartbroken grief", promptHint: "with a devastated, heartbroken expression" },
|
|
57
|
+
{ id: "grieving", label: "Grieving", category: "negative", description: "Deep grief, loss", promptHint: "with a grieving expression of deep loss" },
|
|
58
|
+
{ id: "caught-off-guard", label: "Caught Off Guard", category: "negative", description: "Startled mid-reaction", promptHint: "with a startled, caught-off-guard expression, lips slightly parted mid-reaction" },
|
|
59
|
+
{ id: "aloof", label: "Aloof", category: "negative", description: "Withdrawn, uninterested", promptHint: "with an aloof, withdrawn expression and a gaze pointedly elsewhere" },
|
|
60
|
+
{ id: "vulnerable", label: "Vulnerable", category: "negative", description: "Exposed, defenseless", promptHint: "with a vulnerable, exposed expression, eyes faintly tearful and shoulders soft" },
|
|
61
|
+
{ id: "coy", label: "Coy", category: "negative", description: "Shy, downcast", promptHint: "with a coy, shy expression, downcast eyes, a faint blush and lips lightly pressed" },
|
|
62
|
+
{ id: "bored", label: "Bored", category: "negative", description: "Disinterested, deadpan", promptHint: "with a bored, disinterested expression and a slack, deadpan stare" },
|
|
63
|
+
{ id: "embarrassed", label: "Embarrassed", category: "negative", description: "Blushing, eyes averted", promptHint: "with an embarrassed expression, flushed red cheeks and eyes averted" },
|
|
64
|
+
{ id: "disgusted", label: "Disgusted", category: "negative", description: "Repulsed, recoiling", promptHint: "with a disgusted expression, lip curled and nose wrinkled in distaste" },
|
|
65
|
+
{ id: "bewildered", label: "Bewildered", category: "negative", description: "Confused, lost", promptHint: "with a bewildered, confused expression, brow furrowed and eyes wide" },
|
|
66
|
+
|
|
67
|
+
// -------------------- Neutral / Contemplative --------------------
|
|
68
|
+
{ id: "thoughtful", label: "Thoughtful", category: "neutral", description: "Deep in thought", promptHint: "with a thoughtful, contemplative expression" },
|
|
69
|
+
{ id: "stoic", label: "Stoic", category: "neutral", description: "Impassive, unreadable", promptHint: "with a stoic, impassive expression revealing nothing" },
|
|
70
|
+
{ id: "calm", label: "Calm", category: "neutral", description: "Centered, unreactive", promptHint: "with a calm, centered expression" },
|
|
71
|
+
{ id: "curious", label: "Curious", category: "neutral", description: "Intrigued, alert", promptHint: "with a curious, intrigued expression and alert eyes" },
|
|
72
|
+
{ id: "mysterious", label: "Mysterious", category: "neutral", description: "Inscrutable, enigmatic", promptHint: "with a mysterious, enigmatic expression hard to read" },
|
|
73
|
+
{ id: "dazed", label: "Dazed", category: "neutral", description: "Dreamy, half-present", promptHint: "with a dazed, dreamy expression, eyes slightly out of focus and only half-present" },
|
|
74
|
+
{ id: "sleepy", label: "Sleepy", category: "neutral", description: "Drowsy, heavy-lidded", promptHint: "with a sleepy, drowsy expression, heavy eyelids and a slow, soft blink" },
|
|
75
|
+
{ id: "unbothered", label: "Unbothered", category: "neutral", description: "Calm self-possession", promptHint: "with an unbothered, self-possessed expression and a confident, detached calm" },
|
|
76
|
+
|
|
77
|
+
// -------------------- Intense / Dramatic --------------------
|
|
78
|
+
{ id: "fierce", label: "Fierce", category: "intense", description: "Fierce, commanding", promptHint: "with a fierce, commanding expression and blazing intensity" },
|
|
79
|
+
{ id: "determined", label: "Determined", category: "intense", description: "Resolute, focused will", promptHint: "with a determined, resolute expression and iron focus" },
|
|
80
|
+
{ id: "passionate", label: "Passionate", category: "intense", description: "Burning passion", promptHint: "with a passionate, burning expression full of conviction" },
|
|
81
|
+
{ id: "brooding", label: "Brooding", category: "intense", description: "Dark, brooding melancholy", promptHint: "with a brooding, dark expression and moody introspection" },
|
|
82
|
+
{ id: "seductive", label: "Seductive", category: "intense", description: "Alluring, seductive", promptHint: "with a seductive, alluring expression and lidded gaze" },
|
|
83
|
+
{ id: "defiant", label: "Defiant", category: "intense", description: "Defiant, unyielding", promptHint: "with a defiant, unyielding expression and challenging stance" },
|
|
84
|
+
{ id: "sultry", label: "Sultry", category: "intense", description: "Smoldering, heavy-lidded", promptHint: "with a sultry, smoldering expression, heavy-lidded gaze and lips softly parted" },
|
|
85
|
+
{ id: "smoldering", label: "Smoldering", category: "intense", description: "Coiled, slow-burning intensity", promptHint: "with a smoldering, coiled expression, slow-burning intensity behind half-closed eyes and a still, predatory calm" },
|
|
86
|
+
{ id: "sinister", label: "Sinister", category: "intense", description: "Dark, malicious, threatening", promptHint: "with a sinister expression, a slow crooked smile and eyes glinting with dark malicious intent" },
|
|
87
|
+
{ id: "wiccan-mystical", label: "Wiccan / Mystical", category: "intense", description: "Quietly otherworldly, occult", promptHint: "with a quietly mystical, otherworldly expression, eyes distant and knowing as if reading something the camera cannot see" },
|
|
88
|
+
{ id: "lazy-shy", label: "Lazy Shy", category: "neutral", description: "Drowsy, soft, half-shy", promptHint: "with a soft, drowsy half-shy expression, eyes lowered and barely-there smile, languid and unbothered" },
|
|
89
|
+
{ id: "awe", label: "Awe", category: "intense", description: "Wonder, reverent", promptHint: "with an awestruck expression of wonder, mouth slightly agape and wide-eyed" },
|
|
90
|
+
{ id: "shocked", label: "Shocked", category: "intense", description: "Surprised, mouth open", promptHint: "with a shocked, surprised expression, eyes wide, brows raised and mouth open" },
|
|
91
|
+
|
|
92
|
+
// -------------------- Micro-emotions --------------------
|
|
93
|
+
{ id: "flirty", label: "Flirty", category: "positive", description: "Playful flirtation, lingering smile, sustained eye contact", promptHint: "with a flirty expression, a lingering playful smile and sustained, knowing eye contact with the camera" },
|
|
94
|
+
{ id: "suspicious", label: "Suspicious", category: "negative", description: "Wary distrust, narrowed eyes, side-eye", promptHint: "with a suspicious, wary expression, eyes narrowed in distrust and a sidelong side-eye glance" },
|
|
95
|
+
{ id: "resigned", label: "Resigned", category: "neutral", description: "Quiet acceptance of an unpleasant situation, sigh", promptHint: "with a resigned expression of quiet acceptance, shoulders softly dropped mid-sigh and a tired half-closed gaze" },
|
|
96
|
+
{ id: "conflicted", label: "Conflicted", category: "neutral", description: "Visible internal struggle, brow furrowed, gaze unfocused", promptHint: "with a conflicted expression of visible internal struggle, brow furrowed and gaze unfocused, caught between two impulses" },
|
|
97
|
+
] as const
|
|
98
|
+
|
|
99
|
+
const moodById = new Map<string, Mood>(MOODS.map((m) => [m.id, m]))
|
|
100
|
+
|
|
101
|
+
export function getMood(id: string | undefined | null): Mood | undefined {
|
|
102
|
+
if (!id) return undefined
|
|
103
|
+
return moodById.get(id)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function getMoodLabel(id: string | undefined | null, fallback?: string): string {
|
|
107
|
+
const m = getMood(id)
|
|
108
|
+
if (m) return m.label
|
|
109
|
+
if (fallback !== undefined) return fallback
|
|
110
|
+
return (id ?? "").replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function getMoodPromptHint(id: string | undefined | null): string {
|
|
114
|
+
return getMood(id)?.promptHint ?? ""
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export const MOOD_IDS: ReadonlyArray<string> = MOODS.map((m) => m.id)
|
|
118
|
+
|
|
119
|
+
export const MOOD_CATEGORY_LABELS: Readonly<Record<MoodCategory, string>> = {
|
|
120
|
+
positive: "Positive",
|
|
121
|
+
negative: "Negative",
|
|
122
|
+
neutral: "Neutral",
|
|
123
|
+
intense: "Intense",
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export const MOOD_CATEGORY_ORDER: ReadonlyArray<MoodCategory> = [
|
|
127
|
+
"positive",
|
|
128
|
+
"negative",
|
|
129
|
+
"neutral",
|
|
130
|
+
"intense",
|
|
131
|
+
]
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Shape of Mood parameter data. Single id OR array of up to 2 ids (mixed
|
|
135
|
+
* mood like "smirking + aloof"). Plus optional pre/post free text.
|
|
136
|
+
*/
|
|
137
|
+
export interface MoodValue {
|
|
138
|
+
mood?: string | ReadonlyArray<string>
|
|
139
|
+
preText?: string
|
|
140
|
+
postText?: string
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Combine 1-2 mood ids into a single expression clause. Single → the entry's
|
|
145
|
+
* own promptHint. Two → strip the leading "with a ... expression" template
|
|
146
|
+
* from each and weave them: "with a smirking and aloof expression".
|
|
147
|
+
*/
|
|
148
|
+
function buildMoodHint(value: unknown): string {
|
|
149
|
+
const ids: string[] = []
|
|
150
|
+
if (typeof value === "string" && value) ids.push(value)
|
|
151
|
+
else if (Array.isArray(value)) {
|
|
152
|
+
for (const v of value) {
|
|
153
|
+
if (typeof v === "string" && v && !ids.includes(v)) ids.push(v)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (ids.length === 0) return ""
|
|
157
|
+
if (ids.length === 1) return getMoodPromptHint(ids[0])
|
|
158
|
+
const labels = ids
|
|
159
|
+
.slice(0, 2)
|
|
160
|
+
.map((id) => getMood(id)?.label?.toLowerCase() ?? "")
|
|
161
|
+
.filter((s): s is string => Boolean(s))
|
|
162
|
+
if (labels.length < 2) return getMoodPromptHint(ids[0])
|
|
163
|
+
return `with a ${labels[0]} and ${labels[1]} expression`
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Build prompt hints from MoodData: optional pre-text, the selected mood's
|
|
168
|
+
* hint (single or mixed), optional post-text. Returns array — caller joins
|
|
169
|
+
* with ", ".
|
|
170
|
+
*/
|
|
171
|
+
export function buildMoodHints(
|
|
172
|
+
data: Record<string, unknown> & MoodValue,
|
|
173
|
+
): string[] {
|
|
174
|
+
const hints: string[] = []
|
|
175
|
+
|
|
176
|
+
const pre = typeof data.preText === "string" ? data.preText.trim() : ""
|
|
177
|
+
if (pre) hints.push(pre)
|
|
178
|
+
|
|
179
|
+
const moodHint = buildMoodHint(data.mood)
|
|
180
|
+
if (moodHint) hints.push(moodHint)
|
|
181
|
+
|
|
182
|
+
const post = typeof data.postText === "string" ? data.postText.trim() : ""
|
|
183
|
+
if (post) hints.push(post)
|
|
184
|
+
|
|
185
|
+
return hints
|
|
186
|
+
}
|