use-vibes 0.4.0 → 0.4.3

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.
Files changed (72) hide show
  1. package/README.md +1 -0
  2. package/dist/components/ControlsBar.d.ts +32 -0
  3. package/dist/components/ControlsBar.js +80 -0
  4. package/dist/components/ControlsBar.js.map +1 -0
  5. package/dist/components/ImgGen.css +523 -0
  6. package/dist/components/ImgGen.d.ts +36 -0
  7. package/dist/components/ImgGen.js +206 -0
  8. package/dist/components/ImgGen.js.map +1 -0
  9. package/dist/components/ImgGenUtils/ImgGenDisplay.d.ts +3 -0
  10. package/dist/components/ImgGenUtils/ImgGenDisplay.js +251 -0
  11. package/dist/components/ImgGenUtils/ImgGenDisplay.js.map +1 -0
  12. package/dist/components/ImgGenUtils/ImgGenDisplayPlaceholder.d.ts +3 -0
  13. package/dist/components/ImgGenUtils/ImgGenDisplayPlaceholder.js +115 -0
  14. package/dist/components/ImgGenUtils/ImgGenDisplayPlaceholder.js.map +1 -0
  15. package/dist/components/ImgGenUtils/ImgGenDisplayUtils.d.ts +44 -0
  16. package/dist/components/ImgGenUtils/ImgGenDisplayUtils.js +127 -0
  17. package/dist/components/ImgGenUtils/ImgGenDisplayUtils.js.map +1 -0
  18. package/dist/components/ImgGenUtils/ImgGenError.d.ts +3 -0
  19. package/dist/components/ImgGenUtils/ImgGenError.js +9 -0
  20. package/dist/components/ImgGenUtils/ImgGenError.js.map +1 -0
  21. package/dist/components/ImgGenUtils/ImgGenModal.d.ts +31 -0
  22. package/dist/components/ImgGenUtils/ImgGenModal.js +31 -0
  23. package/dist/components/ImgGenUtils/ImgGenModal.js.map +1 -0
  24. package/dist/components/ImgGenUtils/ImgGenPromptWaiting.d.ts +7 -0
  25. package/dist/components/ImgGenUtils/ImgGenPromptWaiting.js +8 -0
  26. package/dist/components/ImgGenUtils/ImgGenPromptWaiting.js.map +1 -0
  27. package/dist/components/ImgGenUtils/index.d.ts +5 -0
  28. package/dist/components/ImgGenUtils/index.js +8 -0
  29. package/dist/components/ImgGenUtils/index.js.map +1 -0
  30. package/dist/components/ImgGenUtils/overlays/DeleteConfirmationOverlay.d.ts +10 -0
  31. package/dist/components/ImgGenUtils/overlays/DeleteConfirmationOverlay.js +32 -0
  32. package/dist/components/ImgGenUtils/overlays/DeleteConfirmationOverlay.js.map +1 -0
  33. package/dist/components/ImgGenUtils/overlays/ImageOverlay.d.ts +29 -0
  34. package/dist/components/ImgGenUtils/overlays/ImageOverlay.js +11 -0
  35. package/dist/components/ImgGenUtils/overlays/ImageOverlay.js.map +1 -0
  36. package/dist/components/ImgGenUtils/types.d.ts +37 -0
  37. package/dist/components/ImgGenUtils/types.js +2 -0
  38. package/dist/components/ImgGenUtils/types.js.map +1 -0
  39. package/dist/components/ImgGenUtils.d.ts +6 -0
  40. package/dist/components/ImgGenUtils.js +7 -0
  41. package/dist/components/ImgGenUtils.js.map +1 -0
  42. package/dist/components/PromptBar.d.ts +15 -0
  43. package/dist/components/PromptBar.js +23 -0
  44. package/dist/components/PromptBar.js.map +1 -0
  45. package/dist/hooks/image-gen/image-generator.d.ts +14 -0
  46. package/dist/hooks/image-gen/image-generator.js +78 -0
  47. package/dist/hooks/image-gen/image-generator.js.map +1 -0
  48. package/dist/hooks/image-gen/index.d.ts +6 -0
  49. package/dist/hooks/image-gen/index.js +6 -0
  50. package/dist/hooks/image-gen/index.js.map +1 -0
  51. package/dist/hooks/image-gen/types.d.ts +75 -0
  52. package/dist/hooks/image-gen/types.js +2 -0
  53. package/dist/hooks/image-gen/types.js.map +1 -0
  54. package/dist/hooks/image-gen/use-image-gen.d.ts +12 -0
  55. package/dist/hooks/image-gen/use-image-gen.js +573 -0
  56. package/dist/hooks/image-gen/use-image-gen.js.map +1 -0
  57. package/dist/hooks/image-gen/utils.d.ts +61 -0
  58. package/dist/hooks/image-gen/utils.js +241 -0
  59. package/dist/hooks/image-gen/utils.js.map +1 -0
  60. package/dist/hooks/use-image-gen.d.ts +5 -0
  61. package/dist/hooks/use-image-gen.js +7 -0
  62. package/dist/hooks/use-image-gen.js.map +1 -0
  63. package/dist/index.d.ts +5 -0
  64. package/dist/index.js +6 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/style-loader.d.ts +16 -0
  67. package/dist/style-loader.js +43 -0
  68. package/dist/style-loader.js.map +1 -0
  69. package/dist/utils/style-utils.d.ts +51 -0
  70. package/dist/utils/style-utils.js +42 -0
  71. package/dist/utils/style-utils.js.map +1 -0
  72. package/package.json +1 -1
package/README.md CHANGED
@@ -91,6 +91,7 @@ Double-click the prompt text in the overlay to edit it. Press Enter to submit ch
91
91
  ##### Image Regeneration
92
92
 
93
93
  When regenerating images, the component will:
94
+
94
95
  - Use the edited prompt if one has been provided (via `editedPrompt` prop, `onPromptEdit` callback, or direct editing in the UI)
95
96
  - Fall back to the original prompt from the document if no edits were made
96
97
  - Preserve versions under the same document ID to maintain history
@@ -0,0 +1,32 @@
1
+ import * as React from 'react';
2
+ import { ImgGenClasses } from '../utils/style-utils';
3
+ interface ControlsBarProps {
4
+ /** Handle delete confirmation */
5
+ handleDeleteConfirm: () => void;
6
+ handlePrevVersion: () => void;
7
+ handleNextVersion: () => void;
8
+ handleRegen: () => void;
9
+ versionIndex: number;
10
+ totalVersions: number;
11
+ /** Custom CSS classes for styling component parts */
12
+ classes?: ImgGenClasses;
13
+ /** Show control buttons (defaults to true) */
14
+ showControls?: boolean;
15
+ /** Edited prompt for highlighting regenerate button */
16
+ editedPrompt: string | null;
17
+ /** Original prompt text for comparison */
18
+ promptText: string;
19
+ /** Progress value for generation (0-100), shows progress bar when < 100 */
20
+ progress?: number;
21
+ /** Show delete button (defaults to true) */
22
+ showDelete?: boolean;
23
+ /** Whether to flash the version indicator when a new version is added */
24
+ versionFlash?: boolean;
25
+ /** Whether the regeneration is currently in progress */
26
+ isRegenerating?: boolean;
27
+ }
28
+ /**
29
+ * ControlsBar component - Displays controls for deleting, navigating between versions, and regenerating
30
+ */
31
+ export declare function ControlsBar({ handleDeleteConfirm, handlePrevVersion, handleNextVersion, handleRegen, versionIndex, totalVersions, classes, showControls, editedPrompt, promptText, progress, showDelete, versionFlash, isRegenerating, }: ControlsBarProps): React.JSX.Element;
32
+ export {};
@@ -0,0 +1,80 @@
1
+ import * as React from 'react';
2
+ import { combineClasses, defaultClasses } from '../utils/style-utils';
3
+ /**
4
+ * ControlsBar component - Displays controls for deleting, navigating between versions, and regenerating
5
+ */
6
+ export function ControlsBar({ handleDeleteConfirm, handlePrevVersion, handleNextVersion, handleRegen, versionIndex, totalVersions, classes = defaultClasses, showControls = true, editedPrompt, promptText, progress = 100, showDelete = true, versionFlash = false, isRegenerating = false, }) {
7
+ // State for managing delete confirmation
8
+ const [showConfirmation, setShowConfirmation] = React.useState(false);
9
+ // Timer ref for automatic cancellation
10
+ const cancelTimerRef = React.useRef(null);
11
+ // Use external state if provided
12
+ const isConfirming = showConfirmation;
13
+ // Handle delete click
14
+ const onDeleteClick = () => {
15
+ if (isConfirming) {
16
+ // User clicked delete while confirmation is showing - confirm the delete
17
+ handleDeleteConfirm();
18
+ setShowConfirmation(false);
19
+ if (cancelTimerRef.current) {
20
+ window.clearTimeout(cancelTimerRef.current);
21
+ cancelTimerRef.current = null;
22
+ }
23
+ }
24
+ else {
25
+ // Show confirmation
26
+ setShowConfirmation(true);
27
+ // Set timer to auto-hide confirmation after 3 seconds
28
+ cancelTimerRef.current = window.setTimeout(() => {
29
+ setShowConfirmation(false);
30
+ }, 3000);
31
+ }
32
+ };
33
+ // Clean up timer on unmount
34
+ React.useEffect(() => {
35
+ return () => {
36
+ if (cancelTimerRef.current) {
37
+ window.clearTimeout(cancelTimerRef.current);
38
+ }
39
+ };
40
+ }, []);
41
+ return (React.createElement(React.Fragment, null,
42
+ progress < 100 && (React.createElement("div", { className: "imggen-progress", style: {
43
+ width: `${progress}%`,
44
+ position: 'absolute',
45
+ top: 0,
46
+ left: 0,
47
+ height: 'var(--imggen-progress-height)',
48
+ zIndex: 20,
49
+ } })),
50
+ React.createElement("div", { className: combineClasses('imggen-controls', classes.controls) }, showControls ? (React.createElement(React.Fragment, null,
51
+ React.createElement("div", { style: { display: 'flex', gap: '6px', alignItems: 'center', flex: 1 } }, showDelete && (React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '8px' } },
52
+ React.createElement("button", { "aria-label": "Delete image", onClick: onDeleteClick, className: combineClasses('imggen-button imggen-delete-button', classes.button), style: {
53
+ position: 'static',
54
+ width: 'var(--imggen-button-size)',
55
+ height: 'var(--imggen-button-size)',
56
+ backgroundColor: isConfirming ? 'var(--imggen-error-border)' : undefined,
57
+ color: isConfirming ? 'white' : undefined,
58
+ opacity: isConfirming ? 1 : undefined,
59
+ } }, "\u2715"),
60
+ isConfirming && (React.createElement("span", { style: {
61
+ fontSize: 'var(--imggen-font-size)',
62
+ fontWeight: 'bold',
63
+ fontStyle: 'italic',
64
+ whiteSpace: 'nowrap',
65
+ } }, "Confirm delete, are you sure?"))))),
66
+ React.createElement("div", { className: "imggen-control-group" },
67
+ totalVersions > 1 && (React.createElement("button", { "aria-label": "Previous version", disabled: versionIndex === 0, onClick: handlePrevVersion, className: combineClasses('imggen-button', classes.button) }, "\u25C0\uFE0E")),
68
+ totalVersions > 1 && (React.createElement("span", { className: `imggen-version-indicator version-indicator ${versionFlash ? 'imggen-version-flash' : ''}`, "aria-live": "polite" },
69
+ versionIndex + 1,
70
+ " / ",
71
+ totalVersions)),
72
+ totalVersions > 1 && (React.createElement("button", { "aria-label": "Next version", disabled: versionIndex >= totalVersions - 1, onClick: handleNextVersion, className: combineClasses('imggen-button', classes.button) }, "\u25B6\uFE0E")),
73
+ React.createElement("button", { "aria-label": "Regenerate image", onClick: () => {
74
+ handleRegen();
75
+ }, disabled: isRegenerating, className: combineClasses('imggen-button', classes.button, editedPrompt !== null && editedPrompt.trim() !== promptText
76
+ ? 'imggen-button-highlight'
77
+ : '', isRegenerating ? 'imggen-button-disabled' : '') },
78
+ React.createElement("span", { className: isRegenerating ? 'imggen-regen-spinning' : '' }, "\u27F3"))))) : progress < 100 ? (React.createElement("div", { className: "imggen-status-text" }, "Generating...")) : null)));
79
+ }
80
+ //# sourceMappingURL=ControlsBar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ControlsBar.js","sourceRoot":"","sources":["../../src/components/ControlsBar.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,523 @@
1
+ /* ImgGen Component Styling System
2
+ * This file contains all base styles for the ImgGen component hierarchy
3
+ * Uses CSS custom properties to enable easy theming without affecting layout
4
+ */
5
+
6
+ /* ---- CSS Custom Properties (Variables) ---- */
7
+ :root {
8
+ /* Colors */
9
+ --imggen-text-color: #333;
10
+ --imggen-background: #333333;
11
+ --imggen-overlay-bg: rgba(255, 255, 255, 0.5);
12
+ --imggen-accent: #0066cc;
13
+ --imggen-flash: #fe0;
14
+ --imggen-error-bg: rgba(0, 0, 0, 0.7);
15
+ --imggen-error-border: #ff6666;
16
+ --imggen-error-text: #ff6666;
17
+ --imggen-button-bg: rgba(255, 255, 255, 0.7);
18
+ --imggen-error-text-body: #ffffff;
19
+ --imggen-delete-hover-color: #ff3333;
20
+
21
+ /* Dimensions */
22
+ --imggen-border-radius: 8px;
23
+ --imggen-padding: 8px;
24
+ --imggen-button-size: 28px;
25
+ --imggen-progress-height: 8px;
26
+
27
+ /* Typography */
28
+ --imggen-font-size: 14px;
29
+ --imggen-font-weight: bold;
30
+ --imggen-line-height: 1.5;
31
+
32
+ /* Effects */
33
+ --imggen-blur-radius: 4px;
34
+ --imggen-transition-speed: 0.2s;
35
+ --imggen-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
36
+ }
37
+
38
+ /* ---- Core Components ---- */
39
+
40
+ /* Root container */
41
+ .imggen-root {
42
+ position: relative;
43
+ max-width: 100%;
44
+ border-radius: var(--imggen-border-radius);
45
+ overflow: hidden;
46
+ }
47
+
48
+ /* Image container */
49
+ .imggen-container {
50
+ position: relative;
51
+ width: 100%;
52
+ height: 100%;
53
+ }
54
+
55
+ /* Image container with expand button */
56
+ .imggen-image-container {
57
+ position: relative;
58
+ width: 100%;
59
+ overflow: hidden;
60
+ border-radius: var(--imggen-border-radius);
61
+ }
62
+
63
+ /* Expand button in upper left corner */
64
+ .imggen-expand-button {
65
+ position: absolute;
66
+ top: 10px;
67
+ left: 10px;
68
+ z-index: 20;
69
+ background-color: var(--imggen-button-bg);
70
+ border-radius: 50%;
71
+ width: 28px;
72
+ height: 28px;
73
+ display: flex;
74
+ align-items: center;
75
+ justify-content: center;
76
+ border: none;
77
+ cursor: pointer;
78
+ opacity: 0; /* Initially invisible */
79
+ transition: opacity var(--imggen-transition-speed) ease, transform var(--imggen-transition-speed) ease;
80
+ padding: 0;
81
+ color: var(--imggen-text-color);
82
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
83
+ }
84
+
85
+ /* Show button on container hover */
86
+ .imggen-image-container:hover .imggen-expand-button {
87
+ opacity: 0.5;
88
+ }
89
+
90
+ .imggen-expand-button:hover {
91
+ opacity: 1 !important;
92
+ transform: scale(1.1);
93
+ }
94
+
95
+ .imggen-expand-button svg {
96
+ width: 20px;
97
+ height: 20px;
98
+ }
99
+
100
+ @media (hover: none) {
101
+ /* On touch devices, always show the expand button */
102
+ .imggen-expand-button {
103
+ opacity: 0.5 !important;
104
+ }
105
+ }
106
+
107
+ /* The image itself - limited styling since we can't change ImgFile */
108
+ .imggen-image {
109
+ width: 100%;
110
+ height: auto;
111
+ display: block;
112
+ border-radius: var(--imggen-border-radius);
113
+ }
114
+
115
+ /* ---- Overlays ---- */
116
+
117
+ /* Base overlay that appears at the bottom */
118
+ .imggen-overlay {
119
+ position: absolute;
120
+ bottom: 0;
121
+ left: 0;
122
+ right: 0;
123
+ padding: var(--imggen-padding);
124
+ background-color: var(--imggen-overlay-bg);
125
+ backdrop-filter: blur(var(--imggen-blur-radius));
126
+ transition: opacity var(--imggen-transition-speed) ease;
127
+ z-index: 10;
128
+ display: flex;
129
+ flex-direction: column;
130
+ }
131
+
132
+ /* Top line row with prompt and version indicator */
133
+ .imggen-top-line {
134
+ display: flex;
135
+ align-items: center;
136
+ justify-content: space-between;
137
+ width: 100%;
138
+ }
139
+
140
+ /* Prompt text container */
141
+ .imggen-prompt {
142
+ width: 100%;
143
+ padding: 4px;
144
+ margin-bottom: 8px;
145
+ }
146
+
147
+ /* Prompt text styling */
148
+ .imggen-prompt-text {
149
+ color: var(--imggen-text-color);
150
+ width: 100%;
151
+ text-align: center;
152
+ font-weight: var(--imggen-font-weight);
153
+ padding: 2px;
154
+ cursor: pointer;
155
+ }
156
+
157
+ /* Prompt input for editing */
158
+ .imggen-prompt-input {
159
+ width: 100%;
160
+ box-sizing: border-box;
161
+ padding: 6px 8px;
162
+ border: 1px solid #ccc;
163
+ border-radius: 4px;
164
+ font-size: var(--imggen-font-size);
165
+ font-weight: var(--imggen-font-weight);
166
+ color: var(--imggen-text-color);
167
+ background-color: white;
168
+ }
169
+
170
+ .imggen-edit-mode {
171
+ border: 2px solid var(--imggen-accent);
172
+ padding: 6px 10px;
173
+ border-radius: 6px;
174
+ }
175
+
176
+ /* Controls row */
177
+ .imggen-controls {
178
+ display: flex;
179
+ align-items: center;
180
+ justify-content: space-between;
181
+ width: 100%;
182
+ padding-top: 2px;
183
+ }
184
+
185
+ /* Control button group */
186
+ .imggen-control-group {
187
+ display: flex;
188
+ gap: 6px;
189
+ align-items: center;
190
+ }
191
+
192
+ /* ---- Buttons ---- */
193
+
194
+ /* Base button styling */
195
+ .imggen-button {
196
+ background: var(--imggen-button-bg);
197
+ border-radius: 50%;
198
+ width: var(--imggen-button-size);
199
+ height: var(--imggen-button-size);
200
+ display: flex;
201
+ align-items: center;
202
+ justify-content: center;
203
+ border: none;
204
+ cursor: pointer;
205
+ opacity: 0.5;
206
+ transition: opacity var(--imggen-transition-speed) ease;
207
+ padding: 0;
208
+ font-size: var(--imggen-font-size);
209
+ color: var(--imggen-text-color);
210
+ }
211
+
212
+ .imggen-button-highlight {
213
+ background-color: var(--imggen-accent);
214
+ color: white;
215
+ }
216
+
217
+ .imggen-button:hover:not(:disabled) {
218
+ opacity: 1;
219
+ }
220
+
221
+ .imggen-button:disabled {
222
+ opacity: 0.3;
223
+ cursor: default;
224
+ }
225
+
226
+ /* Info button (appears at bottom left) */
227
+ .imggen-info-button {
228
+ position: absolute;
229
+ bottom: 10px;
230
+ left: 10px;
231
+ background: none;
232
+ border: none;
233
+ font-size: 24px;
234
+ color: #fff;
235
+ opacity: 0.5;
236
+ cursor: pointer;
237
+ padding: 0;
238
+ transition: opacity var(--imggen-transition-speed) ease;
239
+ }
240
+
241
+ .imggen-info-button:hover {
242
+ opacity: 1;
243
+ }
244
+
245
+ /* Delete button (top right corner) */
246
+ .imggen-delete-button {
247
+ position: absolute;
248
+ top: 10px;
249
+ right: 10px;
250
+ z-index: 20;
251
+ background-color: var(--imggen-button-bg);
252
+ border-radius: 50%;
253
+ width: 30px;
254
+ height: 30px;
255
+ display: flex;
256
+ align-items: center;
257
+ justify-content: center;
258
+ cursor: pointer;
259
+ border: none;
260
+ font-size: 16px;
261
+ opacity: 0.5;
262
+ transition: opacity var(--imggen-transition-speed) ease;
263
+ padding: 0;
264
+ }
265
+
266
+ .imggen-delete-button:hover {
267
+ opacity: 1;
268
+ color: var(--imggen-delete-hover-color);
269
+ }
270
+
271
+ /* ---- Progress Indicators ---- */
272
+
273
+ /* Progress bar container */
274
+ .imggen-progress-container {
275
+ position: absolute;
276
+ top: 0;
277
+ left: 0;
278
+ right: 0;
279
+ z-index: 50;
280
+ }
281
+
282
+ /* Actual progress bar */
283
+ .imggen-progress {
284
+ position: absolute;
285
+ top: 0;
286
+ left: 0;
287
+ height: var(--imggen-progress-height);
288
+ background-color: var(--imggen-accent);
289
+ transition: width 0.3s ease-in-out;
290
+ z-index: 11; /* Ensure it appears above the overlay */
291
+ }
292
+
293
+ /* Version indicator text */
294
+ .imggen-version-indicator {
295
+ font-size: var(--imggen-font-size);
296
+ color: var(--imggen-text-color);
297
+ transition: all 0.3s ease-in-out;
298
+ }
299
+
300
+ /* Version flash animation */
301
+ @keyframes version-flash {
302
+ 0% {
303
+ color: var(--imggen-text-color);
304
+ transform: scale(1);
305
+ }
306
+ 30% {
307
+ color: var(--imggen-flash);
308
+ transform: scale(1.3);
309
+ /* font-weight: bold; */
310
+ }
311
+ 70% {
312
+ color: var(--imggen-flash);
313
+ transform: scale(1.1);
314
+ font-weight: bold;
315
+ }
316
+ 100% {
317
+ color: var(--imggen-text-color);
318
+ transform: scale(1);
319
+ }
320
+ }
321
+
322
+ .imggen-version-flash {
323
+ animation: version-flash 2s ease-in-out;
324
+ }
325
+
326
+ /* Regenerate spinner animation */
327
+ @keyframes regen-spin {
328
+ 0% { transform: rotate(0deg); }
329
+ 100% { transform: rotate(360deg); }
330
+ }
331
+
332
+ .imggen-regen-spinning {
333
+ animation: regen-spin 2s linear infinite;
334
+ display: inline-block;
335
+ }
336
+
337
+ /* Status text (e.g. Generating...) */
338
+ .imggen-status-text {
339
+ width: 100%;
340
+ text-align: center;
341
+ font-size: var(--imggen-font-size);
342
+ color: var(--imggen-text-color);
343
+ opacity: 0.7;
344
+ padding: 8px 0;
345
+ }
346
+
347
+ /* ---- Placeholders & Errors ---- */
348
+
349
+ /* Placeholder styling */
350
+ .imggen-placeholder {
351
+ width: 100%;
352
+ height: 100%;
353
+ background-color: var(--imggen-background);
354
+ position: relative;
355
+ overflow: hidden;
356
+ display: flex;
357
+ align-items: center;
358
+ justify-content: center;
359
+ box-sizing: border-box;
360
+ }
361
+
362
+ /* Error container wrapper to ensure consistent dark background */
363
+ .imggen-error-container {
364
+ background-color: #222;
365
+ aspect-ratio: 1 / 1; /* Maintain square aspect ratio like images */
366
+ display: flex;
367
+ flex-direction: column;
368
+ justify-content: center;
369
+ align-items: center;
370
+ padding: 1rem;
371
+ width: 100%;
372
+ border-radius: var(--imggen-border-radius);
373
+ overflow: hidden;
374
+ }
375
+
376
+ /* Error container */
377
+ .imggen-error {
378
+ background-color: #000;
379
+ color: var(--imggen-error-text);
380
+ padding: 1.5rem;
381
+ border-radius: var(--imggen-border-radius);
382
+ border: 1px solid var(--imggen-error-border);
383
+ box-shadow: var(--imggen-shadow);
384
+ max-width: 80%;
385
+ display: flex;
386
+ flex-direction: column;
387
+ justify-content: center;
388
+ align-items: center;
389
+ text-align: center;
390
+ }
391
+
392
+ /* Error title */
393
+ .imggen-error-title {
394
+ color: var(--imggen-error-text);
395
+ margin-top: 0;
396
+ font-weight: bold;
397
+ font-size: 18px;
398
+ margin-bottom: 12px;
399
+ text-align: center;
400
+ }
401
+
402
+ /* Error message */
403
+ .imggen-error-message {
404
+ white-space: pre-wrap;
405
+ color: var(--imggen-error-text-body);
406
+ font-size: var(--imggen-font-size);
407
+ line-height: var(--imggen-line-height);
408
+ text-align: left;
409
+ font-family: monospace, sans-serif;
410
+ margin-bottom: 0;
411
+ }
412
+
413
+ /* Error display in full-screen backdrop */
414
+ .imggen-backdrop-error {
415
+ width: 100%;
416
+ height: 100%;
417
+ display: flex;
418
+ align-items: center;
419
+ justify-content: center;
420
+ padding: 2rem;
421
+ box-sizing: border-box;
422
+ background-color: #222; /* Dark gray background */
423
+ /* aspect-ratio: 1 / 1; Maintain square aspect ratio like images */
424
+ border-radius: var(--imggen-border-radius);
425
+ }
426
+
427
+ /* Delete confirmation overlay */
428
+ .imggen-delete-overlay {
429
+ position: absolute;
430
+ top: 0;
431
+ left: 0;
432
+ right: 0;
433
+ bottom: 0;
434
+ background-color: rgba(0, 0, 0, 0.7);
435
+ display: flex;
436
+ flex-direction: column;
437
+ align-items: center;
438
+ justify-content: center;
439
+ z-index: 30;
440
+ padding: 20px;
441
+ text-align: center;
442
+ }
443
+
444
+ /* Delete confirmation message */
445
+ .imggen-delete-message {
446
+ color: white;
447
+ font-size: 16px;
448
+ margin-bottom: 20px;
449
+ }
450
+
451
+ /* Delete confirmation button group */
452
+ .imggen-delete-buttons {
453
+ display: flex;
454
+ gap: 10px;
455
+ }
456
+
457
+ /* Delete confirmation button */
458
+ .imggen-delete-confirm {
459
+ background-color: var(--imggen-error-border);
460
+ color: white;
461
+ border: none;
462
+ padding: 8px 16px;
463
+ border-radius: 4px;
464
+ cursor: pointer;
465
+ }
466
+
467
+ /* Delete cancel button */
468
+ .imggen-delete-cancel {
469
+ background-color: #555;
470
+ color: white;
471
+ border: none;
472
+ padding: 8px 16px;
473
+ border-radius: 4px;
474
+ cursor: pointer;
475
+ }
476
+
477
+ /* Helper classes */
478
+ .imggen-truncate {
479
+ white-space: nowrap;
480
+ overflow: hidden;
481
+ text-overflow: ellipsis;
482
+ }
483
+
484
+ /* ---- Simple fullscreen backdrop ---- */
485
+ .imggen-backdrop {
486
+ position: fixed;
487
+ inset: 0;
488
+ background-color: rgba(0, 0, 0, 0.9);
489
+ display: flex;
490
+ flex-direction: column;
491
+ align-items: center;
492
+ justify-content: flex-start; /* anchor to top to avoid vertical jump */
493
+ padding-top: 5vh; /* give top breathing room */
494
+ z-index: 9999;
495
+ gap: 8px;
496
+ }
497
+
498
+ .imggen-backdrop-image {
499
+ max-width: 90vw;
500
+ max-height: 70vh;
501
+ object-fit: contain;
502
+ border-radius: var(--imggen-border-radius);
503
+ }
504
+
505
+ .imggen-backdrop .imggen-overlay {
506
+ position: static;
507
+ width: 100%;
508
+ box-sizing: border-box; /* include padding in width */
509
+ margin: 0;
510
+ left: auto;
511
+ right: auto;
512
+ bottom: auto;
513
+ background-color: var(--imggen-overlay-bg);
514
+ backdrop-filter: blur(var(--imggen-blur-radius));
515
+ border-radius: var(--imggen-border-radius);
516
+ }
517
+
518
+ /* Wrapper ensures overlay width matches image intrinsic width */
519
+ .imggen-full-wrapper {
520
+ display: inline-block; /* shrink-wrap to content width */
521
+ width: min(90vw, 70vh); /* Size proportional to viewport, matching backdrop-image constraints */
522
+ aspect-ratio: 1 / 1; /* Maintain square aspect ratio like images */
523
+ }
@@ -0,0 +1,36 @@
1
+ import * as React from 'react';
2
+ import type { ImageGenOptions } from 'call-ai';
3
+ import { Database } from 'use-fireproof';
4
+ import { ImgGenClasses } from '../utils/style-utils';
5
+ import './ImgGen.css';
6
+ export interface ImgGenProps {
7
+ /** Text prompt for image generation (required unless _id is provided) */
8
+ prompt?: string;
9
+ /** Document ID to load a specific image instead of generating a new one */
10
+ _id?: string;
11
+ /** Classname(s) to apply to the image */
12
+ className?: string;
13
+ /** Alt text for the image */
14
+ alt?: string;
15
+ /** Image generation options */
16
+ options?: ImageGenOptions;
17
+ /** Database name or instance to use for storing images */
18
+ database?: string | Database;
19
+ /** Callback when image load completes successfully */
20
+ onLoad?: () => void;
21
+ /** Callback when image load fails */
22
+ onError?: (error: Error) => void;
23
+ /** Callback when document is deleted */
24
+ onDelete?: (id: string) => void;
25
+ /** Callback when prompt is edited */
26
+ onPromptEdit?: (id: string, newPrompt: string) => void;
27
+ /** Custom CSS classes for styling component parts */
28
+ classes?: ImgGenClasses;
29
+ }
30
+ /**
31
+ * Main component for generating images with call-ai's imageGen
32
+ * Provides automatic caching, reactive updates, and placeholder handling
33
+ * Uses a mountKey to ensure clean state when switching documents
34
+ */
35
+ export declare function ImgGen(props: ImgGenProps): React.ReactElement;
36
+ export default ImgGen;