@treasuryspatial/prompt-ui-kit 0.1.15 → 0.1.21
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/FeedbackPanel.d.ts +20 -1
- package/dist/FeedbackPanel.d.ts.map +1 -1
- package/dist/FeedbackPanel.js +204 -95
- package/dist/FullscreenImage.d.ts +12 -1
- package/dist/FullscreenImage.d.ts.map +1 -1
- package/dist/FullscreenImage.js +319 -41
- package/dist/GalleryThumbCard.d.ts +2 -1
- package/dist/GalleryThumbCard.d.ts.map +1 -1
- package/dist/GalleryThumbCard.js +121 -3
- package/dist/ImageReferenceStrip.d.ts +9 -0
- package/dist/ImageReferenceStrip.d.ts.map +1 -0
- package/dist/ImageReferenceStrip.js +47 -0
- package/dist/PromptDebugPanel.d.ts +1 -2
- package/dist/PromptDebugPanel.d.ts.map +1 -1
- package/dist/PromptDebugPanel.js +74 -2
- package/dist/RenderHistoryPanel.d.ts +6 -1
- package/dist/RenderHistoryPanel.d.ts.map +1 -1
- package/dist/RenderHistoryPanel.js +55 -55
- package/dist/RenderImageStage.d.ts +10 -0
- package/dist/RenderImageStage.d.ts.map +1 -0
- package/dist/RenderImageStage.js +90 -0
- package/dist/RenderLightboxModal.d.ts +4 -2
- package/dist/RenderLightboxModal.d.ts.map +1 -1
- package/dist/RenderLightboxModal.js +54 -18
- package/dist/RenderPanel.d.ts +17 -16
- package/dist/RenderPanel.d.ts.map +1 -1
- package/dist/RenderPanel.js +178 -204
- package/dist/createRenderHistoryActions.d.ts +11 -0
- package/dist/createRenderHistoryActions.d.ts.map +1 -0
- package/dist/createRenderHistoryActions.js +63 -0
- package/dist/imageDetailPanels.d.ts +14 -0
- package/dist/imageDetailPanels.d.ts.map +1 -0
- package/dist/imageDetailPanels.js +128 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/useRenderImageFlow.d.ts +2 -2
- package/dist/useRenderImageFlow.d.ts.map +1 -1
- package/dist/useRenderImageFlow.js +1 -1
- package/dist/useRenderLightbox.d.ts +14 -2
- package/dist/useRenderLightbox.d.ts.map +1 -1
- package/dist/useRenderLightbox.js +333 -34
- package/package.json +3 -3
package/dist/RenderPanel.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useMemo, useState } from 'react';
|
|
4
|
-
|
|
4
|
+
import { createUiAudio, playUiAudio, resolveOptionSource } from '@treasuryspatial/render-kit';
|
|
5
|
+
import FullscreenImage from './FullscreenImage.js';
|
|
6
|
+
export default function RenderPanel({ isImagineMode, activeTab, promptPack, promptFieldBindings, locationOptions, timeOptions, imageStyleOptions: _imageStyleOptions, styleOptions: _styleOptions, renderLocation, onLocationChange, renderTimeOfDay, onTimeOfDayChange, renderImageStyle, onImageStyleChange, renderStyle, onStyleChange, renderPrompt, onRenderPromptChange, hasPromptBlocks, renderToggles, eraToggleRules, toggleLabels: _toggleLabels, onToggleChange, renderBusy, renderHasGenerated, renderOutputImage, renderProvider = 'gemini', renderProviderToggleEnabled = false, onRenderProviderChange, hasRenderInteractionContext = false, onCaptureRender, renderButtonLabel = 'capture + render', adaptPrompt, onAdaptPromptChange, onAdaptRender, renderFeatureEnabled, onRenderFeatureEnabledChange, renderReferenceMode, onRenderReferenceModeChange, renderReferenceImages, adaptFeatureEnabled, onAdaptFeatureEnabledChange, adaptReferenceMode, onAdaptReferenceModeChange, adaptReferenceImages, styleReferenceLimit, onRenderReferenceImagesAdd, onRenderReferenceImageRemove, onAdaptReferenceImagesAdd, onAdaptReferenceImageRemove, renderError, renderStatus, renderPromptHistory, adaptPromptHistory, fullPromptHistory, blockedDesigners = [], featureRoofType, onFeatureRoofTypeChange, featureRoofscape, onFeatureRoofscapeChange, featureRoofMaterials, onFeatureRoofMaterialsChange, featureMassingHeight, onFeatureMassingHeightChange, featureMassingPerimeter, onFeatureMassingPerimeterChange, featureMassingForm, onFeatureMassingFormChange, featureMassingDiversity, onFeatureMassingDiversityChange, featureMassingDimensions, onFeatureMassingDimensionsChange, featureBuildingProgram, onFeatureBuildingProgramChange, featureCourtyardProgram, onFeatureCourtyardProgramChange, featureMaterialsPrimary, onFeatureMaterialsPrimaryChange, featureMaterialsGround, onFeatureMaterialsGroundChange, featureMaterialsUpper, onFeatureMaterialsUpperChange, featureFacadeVariation, onFeatureFacadeVariationChange, featureFacadeBays, onFeatureFacadeBaysChange, featurePublicRealmStreet, onFeaturePublicRealmStreetChange, cameraProfile, onCameraProfileChange, cameraVariation, onCameraVariationChange, imageFormat, onImageFormatChange, canCreateImageSet, onCreateImageSet, imageSetBusy, renderLimitRemaining, adaptOpen, onAdaptOpenChange, }) {
|
|
5
7
|
const PROMPT_PACK = promptPack;
|
|
6
8
|
const [renderDropActive, setRenderDropActive] = useState(false);
|
|
7
9
|
const [adaptDropActive, setAdaptDropActive] = useState(false);
|
|
@@ -20,22 +22,61 @@ export default function RenderPanel({ isImagineMode, activeTab, promptPack, prom
|
|
|
20
22
|
const [styleRequestOpen, setStyleRequestOpen] = useState(false);
|
|
21
23
|
const [styleRequestValue, setStyleRequestValue] = useState('');
|
|
22
24
|
const [styleRequestStatus, setStyleRequestStatus] = useState('idle');
|
|
25
|
+
const [activeReferenceImage, setActiveReferenceImage] = useState(null);
|
|
23
26
|
const styleOptions = useMemo(() => _styleOptions ?? [], [_styleOptions]);
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const audio = new Audio(src);
|
|
28
|
-
audio.volume = volume;
|
|
29
|
-
return audio;
|
|
30
|
-
}, []);
|
|
31
|
-
const renderClickSound = useMemo(() => createAudio('/sfx/render-start.wav'), [createAudio]);
|
|
32
|
-
const adaptClickSound = useMemo(() => createAudio('/sfx/adapt-chime.wav'), [createAudio]);
|
|
33
|
-
const promptSelectSound = useMemo(() => createAudio('/sfx/prompt-select.wav', 0.25), [createAudio]);
|
|
27
|
+
const renderClickSound = useMemo(() => createUiAudio('/sfx/render-start.wav', { volume: 0.35 }), []);
|
|
28
|
+
const adaptClickSound = useMemo(() => createUiAudio('/sfx/adapt-chime.wav', { volume: 0.35 }), []);
|
|
29
|
+
const promptSelectSound = useMemo(() => createUiAudio('/sfx/prompt-select.wav', { volume: 0.25 }), []);
|
|
34
30
|
const packPanels = useMemo(() => PROMPT_PACK.ui?.panels ?? [], [PROMPT_PACK]);
|
|
31
|
+
const defaultVariationValue = PROMPT_PACK.mode === 'design' ? 'deterministic' : 'variation';
|
|
35
32
|
const [panelOpen, setPanelOpen] = useState(() => (PROMPT_PACK.ui?.panels ?? []).reduce((acc, panel) => {
|
|
36
33
|
acc[panel.id] = true;
|
|
37
34
|
return acc;
|
|
38
35
|
}, {}));
|
|
36
|
+
const normalizePromptLabel = (value) => (value || '')
|
|
37
|
+
.trim()
|
|
38
|
+
.toLowerCase()
|
|
39
|
+
.replace(/\s+/g, ' ');
|
|
40
|
+
const shouldShowGroupLabel = (panel, group) => {
|
|
41
|
+
const groupFields = group.fields
|
|
42
|
+
.map((fieldId) => PROMPT_PACK.fields[fieldId])
|
|
43
|
+
.filter(Boolean);
|
|
44
|
+
if (groupFields.length !== 1)
|
|
45
|
+
return true;
|
|
46
|
+
const field = groupFields[0];
|
|
47
|
+
const normalizedGroupLabel = normalizePromptLabel(group.label);
|
|
48
|
+
const normalizedFieldLabel = normalizePromptLabel(field.label ?? field.id);
|
|
49
|
+
const normalizedPanelLabel = normalizePromptLabel(panel.label);
|
|
50
|
+
if (!normalizedGroupLabel)
|
|
51
|
+
return false;
|
|
52
|
+
if (normalizedGroupLabel === normalizedFieldLabel)
|
|
53
|
+
return false;
|
|
54
|
+
if (normalizedGroupLabel === normalizedPanelLabel)
|
|
55
|
+
return false;
|
|
56
|
+
return true;
|
|
57
|
+
};
|
|
58
|
+
const shouldSuppressFieldLabel = (panel, group, fieldId) => {
|
|
59
|
+
const groupFields = group.fields
|
|
60
|
+
.map((candidateId) => PROMPT_PACK.fields[candidateId])
|
|
61
|
+
.filter(Boolean);
|
|
62
|
+
if (groupFields.length !== 1)
|
|
63
|
+
return false;
|
|
64
|
+
const field = groupFields[0];
|
|
65
|
+
if (field.id !== fieldId)
|
|
66
|
+
return false;
|
|
67
|
+
const normalizedGroupLabel = normalizePromptLabel(group.label);
|
|
68
|
+
const normalizedFieldLabel = normalizePromptLabel(field.label ?? field.id);
|
|
69
|
+
if (!normalizedGroupLabel)
|
|
70
|
+
return false;
|
|
71
|
+
return normalizedGroupLabel === normalizedFieldLabel;
|
|
72
|
+
};
|
|
73
|
+
const getCollapsedPanelGroup = (panel) => {
|
|
74
|
+
if ((panel.fields?.length ?? 0) > 0)
|
|
75
|
+
return null;
|
|
76
|
+
if ((panel.groups?.length ?? 0) !== 1)
|
|
77
|
+
return null;
|
|
78
|
+
return panel.groups?.[0] ?? null;
|
|
79
|
+
};
|
|
39
80
|
useEffect(() => {
|
|
40
81
|
if (!packPanels.length)
|
|
41
82
|
return;
|
|
@@ -49,7 +90,6 @@ export default function RenderPanel({ isImagineMode, activeTab, promptPack, prom
|
|
|
49
90
|
return next;
|
|
50
91
|
});
|
|
51
92
|
}, [packPanels]);
|
|
52
|
-
const InfoBadge = (_) => null;
|
|
53
93
|
const downloadTextFile = (filename, contents, mime = 'text/plain') => {
|
|
54
94
|
const blob = new Blob([contents], { type: mime });
|
|
55
95
|
const url = URL.createObjectURL(blob);
|
|
@@ -72,10 +112,12 @@ export default function RenderPanel({ isImagineMode, activeTab, promptPack, prom
|
|
|
72
112
|
}
|
|
73
113
|
};
|
|
74
114
|
const promptSectionOrder = [
|
|
75
|
-
{ tag: '
|
|
115
|
+
{ tag: 'mode_instruction', label: 'Mode instruction' },
|
|
116
|
+
{ tag: 'camera_setup', label: 'Camera setup' },
|
|
117
|
+
{ tag: 'image_format', label: 'Image format' },
|
|
76
118
|
{ tag: 'form', label: 'Form' },
|
|
77
|
-
{ tag: '
|
|
78
|
-
{ tag: '
|
|
119
|
+
{ tag: 'image_style', label: 'Image style' },
|
|
120
|
+
{ tag: 'scene_style', label: 'Scene style' },
|
|
79
121
|
{ tag: 'program', label: 'Program' },
|
|
80
122
|
{ tag: 'context', label: 'Context' },
|
|
81
123
|
];
|
|
@@ -95,7 +137,7 @@ export default function RenderPanel({ isImagineMode, activeTab, promptPack, prom
|
|
|
95
137
|
sections.push({ label, content });
|
|
96
138
|
}
|
|
97
139
|
});
|
|
98
|
-
const userPrompt = parseTagContent(prompt.prompt, 'user_prompt');
|
|
140
|
+
const userPrompt = parseTagContent(prompt.prompt, 'user_request') || parseTagContent(prompt.prompt, 'user_prompt');
|
|
99
141
|
if (userPrompt) {
|
|
100
142
|
sections.push({ label: 'User prompt', content: userPrompt });
|
|
101
143
|
}
|
|
@@ -134,90 +176,18 @@ export default function RenderPanel({ isImagineMode, activeTab, promptPack, prom
|
|
|
134
176
|
if (field.optionSource === 'render-kit:time-of-day') {
|
|
135
177
|
return timeOptions.map((value) => ({ value, label: value.replace(/_/g, ' ') }));
|
|
136
178
|
}
|
|
179
|
+
if (field.optionSource) {
|
|
180
|
+
const local = PROMPT_PACK.optionSources?.[field.optionSource];
|
|
181
|
+
if (local?.length)
|
|
182
|
+
return local;
|
|
183
|
+
const resolved = resolveOptionSource(field.optionSource);
|
|
184
|
+
if (resolved?.length)
|
|
185
|
+
return resolved;
|
|
186
|
+
}
|
|
137
187
|
return [];
|
|
138
188
|
};
|
|
139
|
-
const packFieldBindings = useMemo(() => promptFieldBindings ??
|
|
140
|
-
|
|
141
|
-
'form.perimeter': { value: featureMassingPerimeter, set: onFeatureMassingPerimeterChange },
|
|
142
|
-
'form.geometry': { value: featureMassingForm, set: onFeatureMassingFormChange },
|
|
143
|
-
'form.diversity': { value: featureMassingDiversity, set: onFeatureMassingDiversityChange },
|
|
144
|
-
'form.height': { value: featureMassingHeight, set: onFeatureMassingHeightChange },
|
|
145
|
-
'form.dimensions': { value: featureMassingDimensions, set: onFeatureMassingDimensionsChange },
|
|
146
|
-
'view.viewpoint': { value: viewpointPreset, set: onViewpointPresetChange },
|
|
147
|
-
'view.variation': { value: viewVariationMode, set: onViewVariationModeChange },
|
|
148
|
-
'view.composition': { value: viewComposition, set: onViewCompositionChange },
|
|
149
|
-
'style.roofType': { value: featureRoofType, set: onFeatureRoofTypeChange },
|
|
150
|
-
'style.roofscape': { value: featureRoofscape, set: onFeatureRoofscapeChange },
|
|
151
|
-
'style.roofMaterials': { value: featureRoofMaterials, set: onFeatureRoofMaterialsChange },
|
|
152
|
-
'style.facadePrimary': { value: featureMaterialsPrimary, set: onFeatureMaterialsPrimaryChange },
|
|
153
|
-
'style.facadeGround': { value: featureMaterialsGround, set: onFeatureMaterialsGroundChange },
|
|
154
|
-
'style.facadeUpper': { value: featureMaterialsUpper, set: onFeatureMaterialsUpperChange },
|
|
155
|
-
'style.facadeVariation': { value: featureFacadeVariation, set: onFeatureFacadeVariationChange },
|
|
156
|
-
'style.facadeBays': { value: featureFacadeBays, set: onFeatureFacadeBaysChange },
|
|
157
|
-
'program.building': { value: featureBuildingProgram, set: onFeatureBuildingProgramChange },
|
|
158
|
-
'program.courtyard': { value: featureCourtyardProgram, set: onFeatureCourtyardProgramChange },
|
|
159
|
-
'program.street': { value: featurePublicRealmStreet, set: onFeaturePublicRealmStreetChange },
|
|
160
|
-
'toggle.landscaping': { value: renderToggles.landscaping, set: (next) => setToggleValue('landscaping', next) },
|
|
161
|
-
'toggle.people': { value: renderToggles.people, set: (next) => setToggleValue('people', next) },
|
|
162
|
-
'toggle.bicycles': { value: renderToggles.bicycles, set: (next) => setToggleValue('bicycles', next) },
|
|
163
|
-
'toggle.cars': { value: renderToggles.cars, set: (next) => setToggleValue('cars', next) },
|
|
164
|
-
'toggle.trams': { value: renderToggles.trams, set: (next) => setToggleValue('trams', next) },
|
|
165
|
-
'toggle.tech': { value: renderToggles.tech, set: (next) => setToggleValue('tech', next) },
|
|
166
|
-
'context.location': { value: renderLocation, set: onLocationChange },
|
|
167
|
-
'context.timeOfDay': { value: renderTimeOfDay, set: onTimeOfDayChange },
|
|
168
|
-
'context.imageStyle': { value: renderImageStyle, set: onImageStyleChange },
|
|
169
|
-
'context.styleReference': { value: renderStyle, set: onStyleChange },
|
|
170
|
-
}), [
|
|
171
|
-
promptFieldBindings,
|
|
172
|
-
featureMassingPerimeter,
|
|
173
|
-
onFeatureMassingPerimeterChange,
|
|
174
|
-
featureMassingForm,
|
|
175
|
-
onFeatureMassingFormChange,
|
|
176
|
-
featureMassingDiversity,
|
|
177
|
-
onFeatureMassingDiversityChange,
|
|
178
|
-
featureMassingHeight,
|
|
179
|
-
onFeatureMassingHeightChange,
|
|
180
|
-
featureMassingDimensions,
|
|
181
|
-
onFeatureMassingDimensionsChange,
|
|
182
|
-
viewpointPreset,
|
|
183
|
-
onViewpointPresetChange,
|
|
184
|
-
viewVariationMode,
|
|
185
|
-
onViewVariationModeChange,
|
|
186
|
-
viewComposition,
|
|
187
|
-
onViewCompositionChange,
|
|
188
|
-
featureRoofType,
|
|
189
|
-
onFeatureRoofTypeChange,
|
|
190
|
-
featureRoofscape,
|
|
191
|
-
onFeatureRoofscapeChange,
|
|
192
|
-
featureRoofMaterials,
|
|
193
|
-
onFeatureRoofMaterialsChange,
|
|
194
|
-
featureMaterialsPrimary,
|
|
195
|
-
onFeatureMaterialsPrimaryChange,
|
|
196
|
-
featureMaterialsGround,
|
|
197
|
-
onFeatureMaterialsGroundChange,
|
|
198
|
-
featureMaterialsUpper,
|
|
199
|
-
onFeatureMaterialsUpperChange,
|
|
200
|
-
featureFacadeVariation,
|
|
201
|
-
onFeatureFacadeVariationChange,
|
|
202
|
-
featureFacadeBays,
|
|
203
|
-
onFeatureFacadeBaysChange,
|
|
204
|
-
featureBuildingProgram,
|
|
205
|
-
onFeatureBuildingProgramChange,
|
|
206
|
-
featureCourtyardProgram,
|
|
207
|
-
onFeatureCourtyardProgramChange,
|
|
208
|
-
featurePublicRealmStreet,
|
|
209
|
-
onFeaturePublicRealmStreetChange,
|
|
210
|
-
renderToggles,
|
|
211
|
-
renderLocation,
|
|
212
|
-
onLocationChange,
|
|
213
|
-
renderTimeOfDay,
|
|
214
|
-
onTimeOfDayChange,
|
|
215
|
-
renderImageStyle,
|
|
216
|
-
onImageStyleChange,
|
|
217
|
-
renderStyle,
|
|
218
|
-
onStyleChange,
|
|
219
|
-
]);
|
|
220
|
-
const renderPackField = (fieldId) => {
|
|
189
|
+
const packFieldBindings = useMemo(() => promptFieldBindings ?? {}, [promptFieldBindings]);
|
|
190
|
+
const renderPackField = (fieldId, fieldOptions = {}) => {
|
|
221
191
|
const field = PROMPT_PACK.fields[fieldId];
|
|
222
192
|
const binding = packFieldBindings[fieldId];
|
|
223
193
|
if (!field || !binding)
|
|
@@ -225,40 +195,53 @@ export default function RenderPanel({ isImagineMode, activeTab, promptPack, prom
|
|
|
225
195
|
const options = resolvePackOptions(field);
|
|
226
196
|
const label = field.label ?? field.id;
|
|
227
197
|
const description = field.description ?? '';
|
|
198
|
+
const showLabel = !fieldOptions.suppressLabel;
|
|
228
199
|
if (field.type === 'toggle' && field.ui === 'chip') {
|
|
229
200
|
return null;
|
|
230
201
|
}
|
|
231
|
-
if (field.id
|
|
202
|
+
if (field.id.endsWith('styleReference')) {
|
|
232
203
|
const value = typeof binding.value === 'string' ? binding.value : '';
|
|
233
|
-
|
|
204
|
+
const styleFieldOptions = options.length > 0
|
|
205
|
+
? options
|
|
206
|
+
: styleOptions.map((style) => ({
|
|
207
|
+
value: style,
|
|
208
|
+
label: style,
|
|
209
|
+
detail: 'Licensed Treasury style reference.',
|
|
210
|
+
}));
|
|
211
|
+
const selectedStyleOption = styleFieldOptions.find((option) => option.value === value);
|
|
212
|
+
const detail = selectedStyleOption
|
|
213
|
+
? ('detail' in selectedStyleOption ? selectedStyleOption.detail : undefined) ??
|
|
214
|
+
('meta' in selectedStyleOption ? selectedStyleOption.meta?.detail : undefined)
|
|
215
|
+
: undefined;
|
|
216
|
+
return (_jsxs("div", { className: "panel-field", children: [showLabel ? (_jsx("label", { className: fieldLabelClass, title: "Optional licensed designer style reference.", children: label })) : null, description ? _jsx("div", { className: fieldDescriptionClass, children: description }) : null, _jsxs("select", { value: value, onChange: (event) => {
|
|
234
217
|
playPromptSelect();
|
|
235
218
|
binding.set(event.target.value);
|
|
236
|
-
}, className: "
|
|
219
|
+
}, className: "cfg-select", children: [_jsx("option", { value: "", children: "none" }), styleFieldOptions.map((option) => (_jsx("option", { value: option.value, children: option.label }, String(option.value))))] }), detail ? _jsx("div", { className: fieldDescriptionClass, children: String(detail) }) : null, _jsxs("div", { className: utilityRowClass, children: [_jsx("button", { type: "button", onClick: () => setStyleRequestOpen((prev) => !prev), className: utilityButtonClass, children: styleRequestOpen ? 'hide style request' : 'request a style' }), styleRequestStatus === 'sending' && (_jsx("span", { className: "text-[10px] lowercase viewer-ui-kit-text-muted", children: "sending\u2026" })), styleRequestStatus === 'sent' && (_jsx("span", { className: "text-[10px] lowercase viewer-ui-kit-text-muted", children: "sent" })), styleRequestStatus === 'error' && (_jsx("span", { className: "text-[10px] lowercase viewer-ui-kit-text-error", children: "error" }))] }), styleRequestOpen && (_jsxs("div", { className: `${subCardClass} text-[11px] viewer-ui-kit-text`, children: [_jsx("textarea", { rows: 2, value: styleRequestValue, onChange: (event) => setStyleRequestValue(event.target.value), className: "cfg-textarea", placeholder: "designer, studio, or reference name" }), _jsx("button", { type: "button", onClick: () => submitStyleRequest(), disabled: !styleRequestValue.trim() || styleRequestStatus === 'sending', className: "cfg-button cfg-button--secondary", children: "send request" })] }))] }, fieldId));
|
|
237
220
|
}
|
|
238
221
|
if (field.type === 'toggle') {
|
|
239
222
|
const active = Boolean(binding.value);
|
|
240
223
|
const toggleKey = field.id.startsWith('toggle.') ? field.id.replace('toggle.', '') : null;
|
|
241
224
|
const disabled = toggleKey ? !eraToggleRules[toggleKey] : false;
|
|
242
|
-
return (_jsxs("div", { className: "
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
? 'viewer-ui-kit-button viewer-ui-kit-button-primary viewer-ui-kit-border'
|
|
249
|
-
: 'viewer-ui-kit-surface viewer-ui-kit-text-muted viewer-ui-kit-border-subtle'} ${disabled ? 'opacity-50 cursor-not-allowed' : ''}`, children: [_jsx("span", { children: label }), _jsx("span", { className: "text-[10px] uppercase tracking-[0.2em]", children: active ? 'on' : 'off' })] }), description ? (_jsx("div", { className: "text-[10px] lowercase viewer-ui-kit-text-muted", children: description })) : null, disabled ? (_jsx("div", { className: "text-[10px] lowercase viewer-ui-kit-text-muted", children: "not available for the current era" })) : null] }, fieldId));
|
|
225
|
+
return (_jsxs("div", { className: "panel-field panel-field--toggle", children: [showLabel ? _jsx("label", { className: fieldLabelClass, children: label }) : null, _jsx("div", { className: "cfg-toggle-group cfg-toggle-group--single", children: _jsx("button", { type: "button", onClick: () => {
|
|
226
|
+
if (disabled)
|
|
227
|
+
return;
|
|
228
|
+
playPromptSelect();
|
|
229
|
+
binding.set(!active);
|
|
230
|
+
}, className: disabled ? 'cfg-toggle opacity-50 cursor-not-allowed' : 'cfg-toggle', "data-active": active, children: active ? 'on' : 'off' }) }), description ? _jsx("div", { className: fieldDescriptionClass, children: description }) : null, disabled ? (_jsx("div", { className: fieldDescriptionClass, children: "not available for the current era" })) : null] }, fieldId));
|
|
250
231
|
}
|
|
251
232
|
if (field.type === 'multi') {
|
|
252
233
|
const list = Array.isArray(binding.value) ? binding.value : [];
|
|
253
|
-
return (_jsxs("div", { className: "
|
|
234
|
+
return (_jsxs("div", { className: "panel-field", children: [showLabel ? _jsx("label", { className: fieldLabelClass, children: label }) : null, description ? _jsx("div", { className: fieldDescriptionClass, children: description }) : null, _jsx("div", { className: "panel-chip-row", children: options.map((option) => (_jsx("button", { type: "button", onClick: () => {
|
|
254
235
|
playPromptSelect();
|
|
255
236
|
toggleList(list, option.value, (next) => binding.set(next));
|
|
256
|
-
}, className:
|
|
237
|
+
}, className: "cfg-toggle", "data-active": list.includes(option.value), title: option.detail ?? option.meta?.detail?.toString() ?? option.label, children: option.label }, `${fieldId}-${option.value}`))) })] }, fieldId));
|
|
257
238
|
}
|
|
258
239
|
if (field.type === 'select') {
|
|
259
240
|
const value = typeof binding.value === 'string' ? binding.value : '';
|
|
260
241
|
const hasNone = options.some((option) => option.value === 'none');
|
|
261
|
-
const
|
|
242
|
+
const isCameraVariationField = field.id === 'camera.variation';
|
|
243
|
+
const isCameraProfileField = field.id === 'camera.profile';
|
|
244
|
+
const showEmpty = !hasNone && !isCameraVariationField;
|
|
262
245
|
const detail = options.find((option) => option.value === value)?.detail ?? options.find((option) => option.value === value)?.meta?.detail;
|
|
263
246
|
const groupOrder = ['Overview', 'Interior', 'Exterior'];
|
|
264
247
|
const groupedOptions = options.reduce((acc, option) => {
|
|
@@ -270,26 +253,32 @@ export default function RenderPanel({ isImagineMode, activeTab, promptPack, prom
|
|
|
270
253
|
acc[group].push(option);
|
|
271
254
|
return acc;
|
|
272
255
|
}, {});
|
|
273
|
-
const hasGroups =
|
|
274
|
-
|
|
275
|
-
return (_jsxs("div", { className: "space-y-2", children: [_jsx("label", { className: "block text-[11px] lowercase viewer-ui-kit-text-muted", children: label }), description ? _jsx("div", { className: "text-[10px] lowercase viewer-ui-kit-text-muted", children: description }) : null, _jsxs("select", { value: value, onChange: (event) => {
|
|
256
|
+
const hasGroups = isCameraProfileField && Object.keys(groupedOptions).length > 0;
|
|
257
|
+
return (_jsxs("div", { className: "panel-field", children: [showLabel ? _jsx("label", { className: fieldLabelClass, children: label }) : null, description ? _jsx("div", { className: fieldDescriptionClass, children: description }) : null, _jsxs("select", { value: value, onChange: (event) => {
|
|
276
258
|
playPromptSelect();
|
|
277
259
|
binding.set(event.target.value);
|
|
278
|
-
}, className:
|
|
260
|
+
}, className: isCameraProfileField ? 'cfg-select normal-case' : 'cfg-select lowercase', children: [showEmpty && _jsx("option", { value: "", children: "none" }), hasGroups
|
|
279
261
|
? groupOrder
|
|
280
262
|
.filter((group) => groupedOptions[group]?.length)
|
|
281
263
|
.map((group) => (_jsx("optgroup", { label: group, children: groupedOptions[group].map((option) => (_jsx("option", { value: option.value, children: option.label }, `${fieldId}-${option.value}`))) }, `${fieldId}-${group}`)))
|
|
282
|
-
: options.map((option) => (_jsx("option", { value: option.value, children: option.label }, `${fieldId}-${option.value}`)))] }), detail ? _jsx("div", { className:
|
|
264
|
+
: options.map((option) => (_jsx("option", { value: option.value, children: option.label }, `${fieldId}-${option.value}`)))] }), detail ? _jsx("div", { className: fieldDescriptionClass, children: detail }) : null] }, fieldId));
|
|
283
265
|
}
|
|
284
266
|
if (field.type === 'text') {
|
|
285
267
|
const value = typeof binding.value === 'string' ? binding.value : '';
|
|
286
|
-
return (_jsxs("div", { className: "
|
|
268
|
+
return (_jsxs("div", { className: "panel-field", children: [showLabel ? _jsx("label", { className: fieldLabelClass, children: label }) : null, description ? _jsx("div", { className: fieldDescriptionClass, children: description }) : null, _jsx("input", { type: "text", value: value, onChange: (event) => binding.set(event.target.value), className: "cfg-input" })] }, fieldId));
|
|
287
269
|
}
|
|
288
270
|
return null;
|
|
289
271
|
};
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
|
|
272
|
+
const utilityButtonClass = 'panel-utility-button';
|
|
273
|
+
const fieldLabelClass = 'panel-field-label-text';
|
|
274
|
+
const fieldDescriptionClass = 'panel-field-help';
|
|
275
|
+
const subCardClass = 'panel-inline-card';
|
|
276
|
+
const utilityRowClass = 'panel-utility-row';
|
|
277
|
+
const utilityMetaClass = 'panel-utility-meta';
|
|
278
|
+
const sectionStackClass = 'panel-section-stack';
|
|
279
|
+
const sectionGroupActionsClass = 'panel-section-group-actions';
|
|
280
|
+
const sectionGroupActionsStackClass = 'panel-section-group-actions panel-section-group-actions--stack';
|
|
281
|
+
const sectionNoteClass = 'panel-section-note';
|
|
293
282
|
const renderToggleChip = (fieldId) => {
|
|
294
283
|
const field = PROMPT_PACK.fields[fieldId];
|
|
295
284
|
const binding = packFieldBindings[fieldId];
|
|
@@ -303,7 +292,7 @@ export default function RenderPanel({ isImagineMode, activeTab, promptPack, prom
|
|
|
303
292
|
return;
|
|
304
293
|
playPromptSelect();
|
|
305
294
|
binding.set(!active);
|
|
306
|
-
}, className:
|
|
295
|
+
}, className: disabled ? 'cfg-toggle opacity-50 cursor-not-allowed' : 'cfg-toggle', "data-active": active, title: field.description ?? field.label ?? field.id, children: field.label ?? field.id }, fieldId));
|
|
307
296
|
};
|
|
308
297
|
const handleRenderKeyDown = (event) => {
|
|
309
298
|
if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {
|
|
@@ -319,24 +308,13 @@ export default function RenderPanel({ isImagineMode, activeTab, promptPack, prom
|
|
|
319
308
|
handleAdaptRender();
|
|
320
309
|
}
|
|
321
310
|
};
|
|
322
|
-
const
|
|
323
|
-
if (!audio)
|
|
324
|
-
return;
|
|
325
|
-
try {
|
|
326
|
-
audio.currentTime = 0;
|
|
327
|
-
void audio.play();
|
|
328
|
-
}
|
|
329
|
-
catch {
|
|
330
|
-
// Ignore audio playback errors.
|
|
331
|
-
}
|
|
332
|
-
};
|
|
333
|
-
const playPromptSelect = () => playSound(promptSelectSound);
|
|
311
|
+
const playPromptSelect = () => playUiAudio(promptSelectSound);
|
|
334
312
|
const handleCaptureRender = () => {
|
|
335
|
-
|
|
313
|
+
playUiAudio(renderClickSound);
|
|
336
314
|
onCaptureRender();
|
|
337
315
|
};
|
|
338
316
|
const handleAdaptRender = () => {
|
|
339
|
-
|
|
317
|
+
playUiAudio(adaptClickSound);
|
|
340
318
|
onAdaptRender();
|
|
341
319
|
};
|
|
342
320
|
const handleRenderDragEnter = (event) => {
|
|
@@ -450,17 +428,13 @@ export default function RenderPanel({ isImagineMode, activeTab, promptPack, prom
|
|
|
450
428
|
const resolvedTab = activeTab ?? 'all';
|
|
451
429
|
const showRender = resolvedTab === 'render' || resolvedTab === 'all';
|
|
452
430
|
const showPresets = resolvedTab === 'presets' || resolvedTab === 'all';
|
|
453
|
-
const showContext = resolvedTab === 'context' || resolvedTab === 'all' ||
|
|
454
|
-
const promptPlaceholder =
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
: hasPromptScaffold
|
|
461
|
-
? 'Optional: add a prompt to refine the render, or rely on the prompt blocks and context below.'
|
|
462
|
-
: 'Add a prompt (see user guide), and/or use the prompt blocks and viewpoint/context below.';
|
|
463
|
-
const adaptPlaceholder = 'Describe changes to the last render';
|
|
431
|
+
const showContext = resolvedTab === 'context' || resolvedTab === 'all' || resolvedTab === 'render';
|
|
432
|
+
const promptPlaceholder = 'render prompt';
|
|
433
|
+
const adaptPlaceholder = 'adapt prompt';
|
|
434
|
+
const providerToggle = renderProviderToggleEnabled ? (_jsx("div", { className: sectionGroupActionsClass, role: "group", "aria-label": "Render provider", children: ['gemini', 'openai-responses'].map((provider) => {
|
|
435
|
+
const active = renderProvider === provider;
|
|
436
|
+
return (_jsx("button", { type: "button", onClick: () => onRenderProviderChange?.(provider), disabled: renderBusy || !onRenderProviderChange, className: `cfg-button ${active ? 'cfg-button--primary' : 'cfg-button--secondary'}`, "aria-pressed": active, children: provider === 'gemini' ? 'gemini' : 'openai' }, provider));
|
|
437
|
+
}) })) : null;
|
|
464
438
|
const getPanelFieldIds = (panel) => {
|
|
465
439
|
const groupFields = panel.groups?.flatMap((group) => group.fields) ?? [];
|
|
466
440
|
return [...(panel.fields ?? []), ...groupFields];
|
|
@@ -480,8 +454,8 @@ export default function RenderPanel({ isImagineMode, activeTab, promptPack, prom
|
|
|
480
454
|
binding.set(false);
|
|
481
455
|
return;
|
|
482
456
|
}
|
|
483
|
-
if (field.id === '
|
|
484
|
-
binding.set(
|
|
457
|
+
if (field.id === 'camera.variation') {
|
|
458
|
+
binding.set(defaultVariationValue);
|
|
485
459
|
return;
|
|
486
460
|
}
|
|
487
461
|
const options = resolvePackOptions(field);
|
|
@@ -515,60 +489,60 @@ export default function RenderPanel({ isImagineMode, activeTab, promptPack, prom
|
|
|
515
489
|
// ignore copy failures
|
|
516
490
|
}
|
|
517
491
|
};
|
|
518
|
-
const
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
.
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
const next = !adaptFeatureOpen;
|
|
544
|
-
setAdaptFeatureOpen(next);
|
|
545
|
-
onAdaptFeatureEnabledChange(next);
|
|
546
|
-
}, adaptReferenceImages, canAddAdaptRefs, adaptDropActive, onAdaptReferenceImagesAdd, onAdaptReferenceImageRemove, handleAdaptDragEnter, handleAdaptDragOver, handleAdaptDragLeave, handleAdaptDrop, adaptReferenceMode, onAdaptReferenceModeChange, 'adapt', isImagineMode) })] })] })] })), showContext && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "panel-section space-y-2", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("div", { className: "text-[16px] font-semibold tracking-[0.01em] viewer-ui-kit-text-strong", children: "prompt blocks" }), _jsx("div", { className: "flex items-center gap-2", children: _jsx("button", { type: "button", onClick: resetCourtyardFeatures, className: "rounded-full border viewer-ui-kit-border-subtle px-3 py-1 text-[9px] uppercase tracking-[0.24em] viewer-ui-kit-text-muted viewer-ui-kit-text-hover", children: "reset blocks" }) })] }), showTaskBlockToggle && (_jsx("div", { className: "pt-3", children: _jsxs("button", { type: "button", onClick: () => onTaskBlockEnabledChange?.(!taskBlockEnabled), className: `flex w-full items-center justify-between rounded border px-3 py-2 text-[11px] lowercase transition ${taskBlockEnabled
|
|
547
|
-
? 'viewer-ui-kit-button viewer-ui-kit-button-primary viewer-ui-kit-border'
|
|
548
|
-
: 'viewer-ui-kit-surface viewer-ui-kit-text-muted viewer-ui-kit-border-subtle'}`, children: [_jsx("span", { children: "task prompt" }), _jsx("span", { className: "text-[10px] uppercase tracking-[0.2em]", children: taskBlockEnabled ? 'on' : 'off' })] }) }))] }), _jsx(_Fragment, { children: packPanels.map((panel) => {
|
|
492
|
+
const renderPromptHistoryList = (items, kind, emptyLabel) => {
|
|
493
|
+
if (items.length === 0) {
|
|
494
|
+
return _jsx("div", { className: "panel-field-help", children: emptyLabel });
|
|
495
|
+
}
|
|
496
|
+
return (_jsx("div", { className: sectionStackClass, children: items.map((item, index) => {
|
|
497
|
+
const key = `${kind}-${index}`;
|
|
498
|
+
return (_jsx("div", { className: `${subCardClass} text-[11px] viewer-ui-kit-text`, children: _jsxs("div", { className: utilityRowClass, style: { alignItems: 'flex-start', justifyContent: 'space-between' }, children: [_jsx("div", { className: "whitespace-pre-wrap", children: item }), _jsx("button", { type: "button", onClick: () => copyToClipboard(key, item), className: utilityButtonClass, children: copiedKey === key ? 'copied' : 'copy' })] }) }, `${key}-${item}`));
|
|
499
|
+
}) }));
|
|
500
|
+
};
|
|
501
|
+
const renderFeatureTransferToggle = (open, onToggle) => (_jsx("button", { type: "button", onClick: onToggle, className: utilityButtonClass, children: open ? 'hide references' : 'references' }));
|
|
502
|
+
const renderFeatureTransferPanel = (open, images, canAddRefs, dropActive, onAdd, onRemove, onDragEnter, onDragOver, onDragLeave, onDrop, mode, onModeChange, contextLabel, allowStructure) => open ? (_jsxs("div", { className: subCardClass, children: [_jsx("div", { className: "panel-reference-mode-row", children: allowStructure ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", onClick: () => onModeChange('structure'), className: "cfg-toggle", "data-active": mode === 'structure', children: "structure" }), _jsx("button", { type: "button", onClick: () => onModeChange('style'), className: "cfg-toggle", "data-active": mode === 'style', children: "style transfer" })] })) : (_jsx("div", { className: "panel-reference-mode-chip", children: "style transfer" })) }), _jsxs("div", { className: "panel-reference-upload", "data-drop-active": dropActive ? 'true' : 'false', "data-disabled": !canAddRefs ? 'true' : 'false', onDragEnter: onDragEnter, onDragOver: onDragOver, onDragLeave: onDragLeave, onDrop: onDrop, title: "Drop reference images here or click to upload.", children: [_jsx("span", { className: "panel-reference-upload-label", children: "reference images" }), _jsx("span", { className: "panel-reference-upload-meta", children: "drop images here or click to upload" }), _jsxs("span", { className: "panel-reference-upload-meta", children: ["max ", styleReferenceLimit] }), _jsx("input", { type: "file", accept: "image/*", multiple: true, "aria-label": `${contextLabel} reference image upload`, onChange: (e) => {
|
|
503
|
+
onAdd(e.target.files);
|
|
504
|
+
e.currentTarget.value = '';
|
|
505
|
+
}, disabled: !canAddRefs, className: "panel-reference-upload-input" })] }), images.length > 0 ? (_jsx("div", { className: "panel-reference-grid", children: images
|
|
506
|
+
.filter((image) => Boolean(image.url))
|
|
507
|
+
.map((image) => (_jsxs("div", { className: "panel-reference-thumb", children: [_jsx("button", { type: "button", onClick: () => setActiveReferenceImage({ name: image.name, url: image.url }), className: "panel-reference-thumb-open", title: "Open reference image", children: _jsx("img", { src: image.url, alt: image.name, className: "panel-reference-thumb-image" }) }), _jsx("button", { type: "button", onClick: () => onRemove(image.id), className: "panel-reference-thumb-remove", title: "Remove reference image", children: "remove" }), _jsx("div", { className: "panel-reference-thumb-name", title: image.name, children: image.name })] }, image.id))) })) : (_jsx("div", { className: "panel-reference-empty", children: "no references yet" }))] })) : null;
|
|
508
|
+
return (_jsxs("div", { className: "viewer-ui-panel-renderer viewer-ui-panel-renderer--sectioned viewer-ui-render-panel space-y-6", children: [showRender && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "panel-section", children: [_jsx("div", { className: "panel-section-header", children: _jsx("h3", { children: "render" }) }), _jsxs("div", { className: sectionStackClass, children: [_jsx("div", { className: "panel-section-group", children: _jsxs("div", { className: "panel-section-fields", children: [providerToggle, _jsx("textarea", { value: renderPrompt, onChange: (e) => onRenderPromptChange(e.target.value), onKeyDown: handleRenderKeyDown, rows: 3, className: "cfg-textarea", placeholder: promptPlaceholder, "aria-label": "Render prompt" }), _jsxs("div", { className: sectionGroupActionsStackClass, children: [_jsxs("div", { className: sectionGroupActionsClass, children: [_jsx("button", { type: "button", onClick: handleCaptureRender, disabled: renderBusy, className: "cfg-button cfg-button--primary", children: renderBusy ? 'rendering…' : renderButtonLabel }), canCreateImageSet ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", onClick: onCreateImageSet, disabled: renderBusy || imageSetBusy, className: "cfg-button cfg-button--secondary", children: imageSetBusy ? 'creating image set…' : 'create image set' }), _jsxs("span", { className: utilityMetaClass, children: [renderLimitRemaining, " renders remaining"] })] })) : null] }), renderStatus ? _jsx("div", { className: sectionNoteClass, children: renderStatus }) : null, renderError ? (_jsxs("div", { className: `${subCardClass} space-y-2`, children: [_jsx("div", { className: "text-xs viewer-ui-kit-text-error", children: renderError }), blockedDesigners.length > 0 ? (_jsxs("div", { className: fieldDescriptionClass, children: ["licensable:", ' ', blockedDesigners.map((term, index) => (_jsxs("span", { children: [_jsx("button", { type: "button", onClick: () => submitBlockedRequest(term), title: "Request licensing from Treasury", className: "underline decoration-dotted underline-offset-2 hover:text-[var(--viewer-ui-color-text-strong)]", children: term }), index < blockedDesigners.length - 1 ? ', ' : ''] }, `${term}-${index}`)))] })) : null, blockedRequestStatus === 'sending' ? (_jsxs("div", { className: fieldDescriptionClass, children: ["requesting license for ", blockedRequestTerm, "\u2026"] })) : null, blockedRequestStatus === 'sent' ? (_jsx("div", { className: fieldDescriptionClass, children: "thanks \u2014 your licensing request was sent." })) : null, blockedRequestStatus === 'error' ? (_jsx("div", { className: "text-[10px] viewer-ui-kit-text-error", children: "licensing request failed \u2014 try again." })) : null] })) : null] })] }) }), _jsxs("div", { className: "panel-section-group", children: [_jsxs("div", { className: sectionGroupActionsClass, children: [_jsx("button", { type: "button", onClick: () => setShowRenderPrompts((prev) => !prev), className: utilityButtonClass, children: showRenderPrompts ? 'hide prompt history' : 'prompt history' }), showRenderPrompts && renderPromptHistory.length > 0 ? (_jsxs("span", { className: utilityMetaClass, children: [renderPromptHistory.length, " saved"] })) : null, renderFeatureTransferToggle(renderFeatureOpen, () => {
|
|
509
|
+
const next = !renderFeatureOpen;
|
|
510
|
+
setRenderFeatureOpen(next);
|
|
511
|
+
onRenderFeatureEnabledChange(next);
|
|
512
|
+
})] }), showRenderPrompts ? renderPromptHistoryList(renderPromptHistory, 'render', 'no prompts yet') : null, renderFeatureTransferPanel(renderFeatureOpen, renderReferenceImages, canAddRenderRefs, renderDropActive, onRenderReferenceImagesAdd, onRenderReferenceImageRemove, handleRenderDragEnter, handleRenderDragOver, handleRenderDragLeave, handleRenderDrop, renderReferenceMode, onRenderReferenceModeChange, 'render', isImagineMode)] })] })] }), _jsxs("div", { className: "panel-section", children: [_jsx("div", { className: "panel-section-header", children: _jsx("h3", { children: "adapt" }) }), _jsxs("div", { className: sectionStackClass, children: [_jsx("div", { className: "panel-section-group", children: _jsxs("div", { className: "panel-section-fields", children: [_jsx("textarea", { value: adaptPrompt, onChange: (e) => onAdaptPromptChange(e.target.value), onKeyDown: handleAdaptKeyDown, rows: 3, className: "cfg-textarea", placeholder: adaptPlaceholder, "aria-label": "Adapt prompt", disabled: !renderOutputImage }), _jsx("div", { className: sectionGroupActionsClass, children: _jsx("button", { type: "button", onClick: handleAdaptRender, disabled: renderBusy || !renderOutputImage || !hasRenderInteractionContext, className: "cfg-button cfg-button--secondary", children: renderBusy ? 'adapting…' : 'adapt image' }) }), !renderOutputImage ? (_jsx("div", { className: fieldDescriptionClass, children: "render an image before adapting." })) : !hasRenderInteractionContext ? (_jsx("div", { className: fieldDescriptionClass, children: "this image has no provider interaction id; render again before adapting." })) : (_jsx("div", { className: fieldDescriptionClass, children: "adapts the current generated interaction." })), renderBusy && renderStatus ? _jsx("div", { className: sectionNoteClass, children: renderStatus }) : null, renderError ? _jsx("div", { className: "text-xs viewer-ui-kit-text-error", children: renderError }) : null] }) }), _jsxs("div", { className: "panel-section-group", children: [_jsxs("div", { className: sectionGroupActionsClass, children: [_jsx("button", { type: "button", onClick: () => setShowAdaptPrompts((prev) => !prev), className: utilityButtonClass, children: showAdaptPrompts ? 'hide prompt history' : 'prompt history' }), showAdaptPrompts && adaptPromptHistory.length > 0 ? (_jsxs("span", { className: utilityMetaClass, children: [adaptPromptHistory.length, " saved"] })) : null, renderFeatureTransferToggle(adaptFeatureOpen, () => {
|
|
513
|
+
const next = !adaptFeatureOpen;
|
|
514
|
+
setAdaptFeatureOpen(next);
|
|
515
|
+
onAdaptFeatureEnabledChange(next);
|
|
516
|
+
})] }), showAdaptPrompts ? renderPromptHistoryList(adaptPromptHistory, 'adapt', 'no prompts yet') : null, renderFeatureTransferPanel(adaptFeatureOpen, adaptReferenceImages, canAddAdaptRefs, adaptDropActive, onAdaptReferenceImagesAdd, onAdaptReferenceImageRemove, handleAdaptDragEnter, handleAdaptDragOver, handleAdaptDragLeave, handleAdaptDrop, adaptReferenceMode, onAdaptReferenceModeChange, 'adapt', isImagineMode)] })] })] })] })), showContext && (_jsxs(_Fragment, { children: [_jsx("div", { className: "panel-section", children: _jsxs("div", { className: "panel-section-header", children: [_jsx("h3", { children: "prompt blocks" }), _jsx("div", { className: `${utilityRowClass} justify-end`, children: _jsx("button", { type: "button", onClick: resetCourtyardFeatures, className: utilityButtonClass, children: "reset current blocks" }) })] }) }), _jsx(_Fragment, { children: packPanels.map((panel) => {
|
|
549
517
|
const open = panelOpen[panel.id] ?? true;
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
return
|
|
560
|
-
})
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
518
|
+
const collapsedGroup = getCollapsedPanelGroup(panel);
|
|
519
|
+
const collapsedGroupKey = collapsedGroup ? (collapsedGroup.id ?? collapsedGroup.label) : null;
|
|
520
|
+
const collapsedGroupLabel = collapsedGroup ? normalizePromptLabel(collapsedGroup.label) : '';
|
|
521
|
+
const collapsedIntoPanelHeader = Boolean(collapsedGroup) && collapsedGroupLabel !== normalizePromptLabel(panel.label);
|
|
522
|
+
const panelDescription = panel.description?.trim() || '';
|
|
523
|
+
const panelSubLabel = collapsedIntoPanelHeader && collapsedGroup ? collapsedGroup.label : '';
|
|
524
|
+
return (_jsxs("section", { className: "panel-section", "data-panel-id": panel.id, children: [_jsxs("div", { className: "panel-section-header", children: [_jsxs("div", { children: [_jsx("h3", { children: panel.label }), panelSubLabel ? _jsx("div", { className: fieldDescriptionClass, children: panelSubLabel }) : null, panelDescription ? _jsx("div", { className: fieldDescriptionClass, children: panelDescription }) : null] }), _jsx("button", { type: "button", onClick: () => setPanelOpen((prev) => ({ ...prev, [panel.id]: !open })), className: utilityButtonClass, children: open ? 'hide' : 'show' })] }), !open ? (null) : (_jsx("div", { className: "panel-section-fields", children: panel.groups?.length ? (_jsx(_Fragment, { children: panel.groups.map((group) => {
|
|
525
|
+
const groupToggleFields = group.fields.filter((fieldId) => {
|
|
526
|
+
const field = PROMPT_PACK.fields[fieldId];
|
|
527
|
+
return field?.type === 'toggle' && field.ui === 'chip';
|
|
528
|
+
});
|
|
529
|
+
const groupFields = group.fields.filter((fieldId) => {
|
|
530
|
+
const field = PROMPT_PACK.fields[fieldId];
|
|
531
|
+
return !(field?.type === 'toggle' && field.ui === 'chip');
|
|
532
|
+
});
|
|
533
|
+
const showGroupLabel = shouldShowGroupLabel(panel, group);
|
|
534
|
+
const collapseGroupHeading = Boolean(collapsedGroupKey) &&
|
|
535
|
+
collapsedIntoPanelHeader &&
|
|
536
|
+
collapsedGroupKey === (group.id ?? group.label);
|
|
537
|
+
return (_jsxs("div", { className: "panel-section-group", "data-group-id": group.id ?? group.label, children: [showGroupLabel && !collapseGroupHeading ? _jsx("h4", { children: group.label }) : null, group.description && !collapseGroupHeading ? (_jsx("div", { className: fieldDescriptionClass, children: group.description })) : null, _jsx("div", { className: "panel-section-fields", children: groupFields.map((fieldId) => renderPackField(fieldId, {
|
|
538
|
+
suppressLabel: showGroupLabel && shouldSuppressFieldLabel(panel, group, fieldId),
|
|
539
|
+
})) }), groupToggleFields.length > 0 ? (_jsx("div", { className: "flex flex-wrap gap-2 pt-1", children: groupToggleFields.map((fieldId) => renderToggleChip(fieldId)) })) : null] }, group.id ?? group.label));
|
|
540
|
+
}) })) : (_jsx("div", { className: "panel-section-fields", children: panel.fields?.map((fieldId) => renderPackField(fieldId)) })) }))] }, panel.id));
|
|
541
|
+
}) })] })), showPresets && (_jsxs(_Fragment, { children: [_jsxs("section", { className: "panel-section", "data-panel-id": "render-history", children: [_jsx("div", { className: "panel-section-header", children: _jsx("h3", { children: "render prompt history" }) }), renderPromptHistoryList(renderPromptHistory, 'render-history', 'no render prompts yet')] }), _jsxs("section", { className: "panel-section", "data-panel-id": "adapt-history", children: [_jsx("div", { className: "panel-section-header", children: _jsx("h3", { children: "adapt prompt history" }) }), renderPromptHistoryList(adaptPromptHistory, 'adapt-history', 'no adapt prompts yet')] })] })), showPresets && (_jsxs("section", { className: "panel-section", "data-panel-id": "full-prompt-log", children: [_jsx("div", { className: "panel-section-header", children: _jsx("h3", { children: "full prompt log" }) }), _jsxs("div", { className: "panel-section-fields", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("button", { type: "button", onClick: () => setFullPromptOpen((prev) => !prev), className: utilityButtonClass, children: fullPromptOpen ? 'hide prompt log' : 'show prompt log' }), _jsxs("span", { className: "panel-field-help", children: [fullPromptHistory.length, " total"] })] }), fullPromptOpen && fullPromptHistory.length === 0 && (_jsx("div", { className: "panel-field-help", children: "no full prompts yet" })), fullPromptOpen && fullPromptHistory.length > 0 && (_jsxs("div", { className: "panel-section-fields", children: [_jsxs("div", { className: "flex items-center justify-between gap-2 text-[10px] lowercase viewer-ui-kit-text-muted", children: [_jsxs("div", { children: ["prompt #", activeFullPrompt?.seq ?? fullPromptHistory.length, " of ", totalPromptCount] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "button", onClick: () => setActiveFullPromptIndex((prev) => Math.min(fullPromptHistory.length - 1, prev + 1)), className: utilityButtonClass, disabled: activeFullPromptIndex >= fullPromptHistory.length - 1, children: "prev" }), _jsx("button", { type: "button", onClick: () => setActiveFullPromptIndex((prev) => Math.max(0, prev - 1)), className: utilityButtonClass, disabled: activeFullPromptIndex === 0, children: "next" })] })] }), fullPromptHistory.map((item, index) => {
|
|
542
|
+
if (index !== activeFullPromptIndex)
|
|
543
|
+
return null;
|
|
544
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
545
|
+
const sections = formatPromptSections(item);
|
|
546
|
+
return (_jsxs("div", { className: "rounded-[18px] border viewer-ui-kit-border-subtle viewer-ui-kit-surface px-4 py-4 text-[10px] viewer-ui-kit-text space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between text-[10px] uppercase tracking-[0.2em] viewer-ui-kit-text-subtle", children: [_jsxs("span", { children: [item.kind, " \u00B7 #", item.seq] }), _jsx("span", { children: new Date(item.ts).toLocaleTimeString() })] }), _jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsx("div", { className: "space-y-3", children: sections.length === 0 ? (_jsx("div", { className: "whitespace-pre-wrap", children: item.prompt })) : (sections.map((section) => (_jsxs("div", { className: "space-y-1", children: [_jsx("div", { className: "text-[11px] font-semibold viewer-ui-kit-text-strong", children: section.label }), _jsx("div", { className: "whitespace-pre-wrap leading-relaxed", children: section.content })] }, `${section.label}-${index}`)))) }), _jsxs("div", { className: "shrink-0 flex flex-col gap-1", children: [_jsx("button", { type: "button", onClick: () => handleCopyPrompt(item.prompt, index), className: utilityButtonClass, children: copiedPromptIndex === index ? 'copied' : 'copy' }), _jsx("button", { type: "button", onClick: () => downloadTextFile(`prompt-${stamp}-${item.seq}.txt`, item.prompt), className: utilityButtonClass, children: "download" })] })] })] }, `full-${index}`));
|
|
547
|
+
})] }))] })] })), _jsx(FullscreenImage, { open: Boolean(activeReferenceImage), src: activeReferenceImage?.url || '', alt: activeReferenceImage?.name || 'reference image', title: activeReferenceImage?.name || 'reference image', modeLabel: "reference", onClose: () => setActiveReferenceImage(null) })] }));
|
|
574
548
|
}
|