@vibes.diy/base 14.2.7 → 14.2.9
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/components/ChatMessageRow.d.ts +11 -0
- package/components/ChatMessageRow.js +13 -0
- package/components/ChatMessageRow.js.map +1 -0
- package/components/EditorTabStrip.d.ts +1 -1
- package/components/EditorTabStrip.js +2 -1
- package/components/EditorTabStrip.js.map +1 -1
- package/components/HandlePickerMenu.d.ts +7 -1
- package/components/HandlePickerMenu.js +11 -3
- package/components/HandlePickerMenu.js.map +1 -1
- package/components/SharePanelView.d.ts +1 -2
- package/components/SharePanelView.js +16 -16
- package/components/SharePanelView.js.map +1 -1
- package/components/UnifiedVibeCard.d.ts +7 -1
- package/components/UnifiedVibeCard.js +185 -146
- package/components/UnifiedVibeCard.js.map +1 -1
- package/components/ViewerTagView.js +3 -0
- package/components/ViewerTagView.js.map +1 -1
- package/components/index.d.ts +1 -0
- package/components/index.js +1 -0
- package/components/index.js.map +1 -1
- package/hooks/img-gen/use-img-gen.d.ts +1 -0
- package/hooks/img-gen/use-img-gen.js +5 -3
- package/hooks/img-gen/use-img-gen.js.map +1 -1
- package/package.json +4 -4
|
@@ -4,6 +4,7 @@ import { ovalColors } from "./VibesSwitch.styles.js";
|
|
|
4
4
|
import { EditorTabStrip } from "./EditorTabStrip.js";
|
|
5
5
|
import { ViewerStandingView } from "./ViewerStandingView.js";
|
|
6
6
|
import { OptionButtons } from "./OptionButtons.js";
|
|
7
|
+
import { ChatMessageRow } from "./ChatMessageRow.js";
|
|
7
8
|
import { ViewerTagView } from "./ViewerTagView.js";
|
|
8
9
|
import { SignedOutSavePrompt } from "./SignedOutSavePrompt.js";
|
|
9
10
|
import { HandlePickerMenu } from "./HandlePickerMenu.js";
|
|
@@ -13,7 +14,7 @@ import { CodingIndicator } from "./CodingIndicator.js";
|
|
|
13
14
|
import { CopyLinkIconButton } from "./LinkLineControls.js";
|
|
14
15
|
import { AttachmentButton, AttachmentChips } from "./AttachmentRow.js";
|
|
15
16
|
import { useAttachments } from "../attachments/use-attachments.js";
|
|
16
|
-
import { PeopleIcon
|
|
17
|
+
import { PeopleIcon } from "./icons/index.js";
|
|
17
18
|
import { HOME_BRAND_FONT } from "./homeBrandFont.js";
|
|
18
19
|
import { SAFE_AREA_TOP } from "../theme/safe-area.js";
|
|
19
20
|
const UNIFIED_VIBE_CARD_DARK_VARS = `
|
|
@@ -25,6 +26,10 @@ const UNIFIED_VIBE_CARD_DARK_VARS = `
|
|
|
25
26
|
--color-dark-background-00: #1a1a1a;
|
|
26
27
|
--color-dark-background-01: #222222;
|
|
27
28
|
--color-dark-background-02: #222222;
|
|
29
|
+
/* The global field palette follows the OS. Pin the same semantic dark
|
|
30
|
+
values here so an explicit .dark host also darkens fields and borders. */
|
|
31
|
+
--vibes-field-bg: var(--vibes-ink-deep, #141414);
|
|
32
|
+
--vibes-card-border: var(--vibes-gray-mid, #555555);
|
|
28
33
|
--uvc-card-shadow: rgba(255,255,255,0.75);
|
|
29
34
|
--uvc-amber-text: #fbbf24;
|
|
30
35
|
--uvc-blue-text: #93c5fd;
|
|
@@ -34,6 +39,7 @@ const UNIFIED_VIBE_CARD_DARK_VARS = `
|
|
|
34
39
|
--uvc-suggestion-text: #e5e7eb;
|
|
35
40
|
--uvc-helper-text: #c2cbd8;
|
|
36
41
|
--uvc-build-text: #bac4d2;
|
|
42
|
+
--uvc-nav-chat: #c4b5fd;
|
|
37
43
|
--uvc-nav-edit: #fb923c;
|
|
38
44
|
--uvc-nav-share: #4ade80;
|
|
39
45
|
--uvc-nav-faq: #cbd5e1;
|
|
@@ -47,10 +53,10 @@ const UNIFIED_VIBE_CARD_DARK_VARS = `
|
|
|
47
53
|
--color-light-background-02: var(--color-dark-background-02, #222222);`;
|
|
48
54
|
const unifiedVibeCardDarkCss = `
|
|
49
55
|
@media (prefers-color-scheme: dark) {
|
|
50
|
-
[data-unified-vibe-card], [data-vibe-handle-menu], [data-vibe-version-menu]
|
|
56
|
+
[data-unified-vibe-card], [data-vibe-handle-menu], [data-vibe-version-menu] {${UNIFIED_VIBE_CARD_DARK_VARS}
|
|
51
57
|
}
|
|
52
58
|
}
|
|
53
|
-
.dark [data-unified-vibe-card], .dark [data-vibe-handle-menu], .dark [data-vibe-version-menu]
|
|
59
|
+
.dark [data-unified-vibe-card], .dark [data-vibe-handle-menu], .dark [data-vibe-version-menu] {${UNIFIED_VIBE_CARD_DARK_VARS}
|
|
54
60
|
}
|
|
55
61
|
/* Composer submit button: a blue pulsating glow while the field holds unsent
|
|
56
62
|
content, nudging the user to send it — the same "something's live, act on it"
|
|
@@ -120,12 +126,9 @@ const unifiedVibeCardDarkCss = `
|
|
|
120
126
|
animation: none;
|
|
121
127
|
}
|
|
122
128
|
}
|
|
123
|
-
/*
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
squash the circles into ovals. The circles are shrink-proof (flexShrink 0 in
|
|
127
|
-
NavIcon) and instead step DOWN via these vars so the row keeps fitting, clear
|
|
128
|
-
of the floating logo, on common 360–400px phones (Codex P2 on #3037). */
|
|
129
|
+
/* Four shrink-proof nav circles share the footer with the 120px logo spacer.
|
|
130
|
+
Compact size/gap steps keep them clear of the logo on narrow phones without
|
|
131
|
+
flex shrinking circles into ovals. */
|
|
129
132
|
@media (max-width: 400px) {
|
|
130
133
|
[data-unified-vibe-card] { --uvc-nav-size: 34px; --uvc-nav-gap: 4px; }
|
|
131
134
|
}
|
|
@@ -154,7 +157,7 @@ const unifiedVibeCardDarkCss = `
|
|
|
154
157
|
.vibes-edit-field:focus-within {
|
|
155
158
|
border-color: var(--vibes-blue);
|
|
156
159
|
}
|
|
157
|
-
/*
|
|
160
|
+
/* The suggestion well shares the transcript’s attributed content column. Quiet
|
|
158
161
|
suggestion borders and an opaque invitation distinguish optional actions
|
|
159
162
|
from the writing field. Gold upgrades retain their semantic color.
|
|
160
163
|
OptionButtons outside this well keep their own presentation. */
|
|
@@ -171,8 +174,24 @@ const unifiedVibeCardDarkCss = `
|
|
|
171
174
|
line-height: 1.5;
|
|
172
175
|
}
|
|
173
176
|
.vibes-chip-well [data-message-role="brainstorm-options"] {
|
|
177
|
+
display: flex;
|
|
178
|
+
flex-direction: row;
|
|
179
|
+
flex-wrap: wrap;
|
|
174
180
|
gap: 6px;
|
|
175
181
|
}
|
|
182
|
+
.vibes-chip-well [data-testid="option-buttons-explainer"] {
|
|
183
|
+
flex: 0 0 100%;
|
|
184
|
+
margin: 0;
|
|
185
|
+
}
|
|
186
|
+
/* Decorated chips keep their adjacent owner control in the same wrapping item. */
|
|
187
|
+
.vibes-chip-well [data-message-role="brainstorm-options"] > div {
|
|
188
|
+
min-width: 0;
|
|
189
|
+
max-width: 100%;
|
|
190
|
+
}
|
|
191
|
+
.vibes-chip-well [data-message-role="brainstorm-options"] > div [data-chip-role="option"] {
|
|
192
|
+
flex: 1 1 auto;
|
|
193
|
+
min-width: 0;
|
|
194
|
+
}
|
|
176
195
|
.vibes-chip-well [data-chip-role="option"]:not([data-chip-tone="gold"]) {
|
|
177
196
|
background-color: var(--vibes-field-bg, #ffffff);
|
|
178
197
|
border: 1px solid var(--uvc-suggestion-border, #a6adb7);
|
|
@@ -188,9 +207,10 @@ const unifiedVibeCardDarkCss = `
|
|
|
188
207
|
border-radius: 8px;
|
|
189
208
|
font-size: 13px;
|
|
190
209
|
line-height: 20px;
|
|
191
|
-
padding:
|
|
210
|
+
padding: 3px 6px;
|
|
192
211
|
min-height: 40px;
|
|
193
212
|
text-align: left;
|
|
213
|
+
overflow-wrap: anywhere;
|
|
194
214
|
}
|
|
195
215
|
/* The card owns this density; other SubTabStrip and BuildCard consumers keep
|
|
196
216
|
their defaults. Tab inline sizes need a scoped override, not a shared edit. */
|
|
@@ -273,14 +293,14 @@ export function UnifiedVibeCard(props) {
|
|
|
273
293
|
cancelHidePress();
|
|
274
294
|
}
|
|
275
295
|
};
|
|
276
|
-
const pickerInteractive = props.handles !== undefined;
|
|
296
|
+
const pickerInteractive = props.handles !== undefined || props.onAccountSettings !== undefined;
|
|
277
297
|
const [internalPickerOpen, setInternalPickerOpen] = useState(false);
|
|
278
298
|
const pickerOpen = props.handlePickerOpen ?? internalPickerOpen;
|
|
279
299
|
const setPickerOpen = (next) => {
|
|
280
300
|
if (props.handlePickerOpen === undefined)
|
|
281
301
|
setInternalPickerOpen(next);
|
|
282
302
|
props.onHandlePickerOpenChange?.(next);
|
|
283
|
-
if (next)
|
|
303
|
+
if (next === false)
|
|
284
304
|
setCreditsOpen(false);
|
|
285
305
|
};
|
|
286
306
|
const pickerWrapRef = useRef(null);
|
|
@@ -293,8 +313,16 @@ export function UnifiedVibeCard(props) {
|
|
|
293
313
|
if (!pickerWrapRef.current?.contains(target) && !menuRef.current?.contains(target))
|
|
294
314
|
setPickerOpen(false);
|
|
295
315
|
};
|
|
296
|
-
|
|
297
|
-
|
|
316
|
+
const onBlur = () => {
|
|
317
|
+
if (document.activeElement?.tagName === "IFRAME")
|
|
318
|
+
setPickerOpen(false);
|
|
319
|
+
};
|
|
320
|
+
document.addEventListener("pointerdown", onDown);
|
|
321
|
+
window.addEventListener("blur", onBlur);
|
|
322
|
+
return () => {
|
|
323
|
+
document.removeEventListener("pointerdown", onDown);
|
|
324
|
+
window.removeEventListener("blur", onBlur);
|
|
325
|
+
};
|
|
298
326
|
}, [pickerOpen]);
|
|
299
327
|
useEffect(() => {
|
|
300
328
|
if (open === false && pickerOpen === true)
|
|
@@ -307,22 +335,7 @@ export function UnifiedVibeCard(props) {
|
|
|
307
335
|
if (props.creditsMenuOpen === undefined)
|
|
308
336
|
setInternalCreditsOpen(next);
|
|
309
337
|
props.onCreditsMenuOpenChange?.(next);
|
|
310
|
-
if (next)
|
|
311
|
-
setPickerOpen(false);
|
|
312
338
|
};
|
|
313
|
-
const creditsWrapRef = useRef(null);
|
|
314
|
-
const creditsMenuRef = useRef(null);
|
|
315
|
-
useEffect(() => {
|
|
316
|
-
if (!creditsOpen)
|
|
317
|
-
return;
|
|
318
|
-
const onDown = (e) => {
|
|
319
|
-
const target = e.target;
|
|
320
|
-
if (!creditsWrapRef.current?.contains(target) && !creditsMenuRef.current?.contains(target))
|
|
321
|
-
setCreditsOpen(false);
|
|
322
|
-
};
|
|
323
|
-
document.addEventListener("mousedown", onDown);
|
|
324
|
-
return () => document.removeEventListener("mousedown", onDown);
|
|
325
|
-
}, [creditsOpen]);
|
|
326
339
|
useEffect(() => {
|
|
327
340
|
if (open === false && creditsOpen === true)
|
|
328
341
|
setCreditsOpen(false);
|
|
@@ -440,6 +453,25 @@ export function UnifiedVibeCard(props) {
|
|
|
440
453
|
}, [hasHistory, mounted]);
|
|
441
454
|
const [userHeight, setUserHeight] = useState(null);
|
|
442
455
|
const cardRef = useRef(null);
|
|
456
|
+
const switchWrapRef = useRef(null);
|
|
457
|
+
useEffect(() => {
|
|
458
|
+
if (open === false)
|
|
459
|
+
return;
|
|
460
|
+
const onOutsideClick = (event) => {
|
|
461
|
+
if (event.defaultPrevented || event.cancelBubble)
|
|
462
|
+
return;
|
|
463
|
+
const path = event.composedPath();
|
|
464
|
+
if ([cardRef.current, switchWrapRef.current].some((node) => node !== null && path.includes(node)))
|
|
465
|
+
return;
|
|
466
|
+
if (path.some((node) => "hasAttribute" in node &&
|
|
467
|
+
typeof node.hasAttribute === "function" &&
|
|
468
|
+
(node.hasAttribute("data-vibe-handle-menu") || node.hasAttribute("data-vibe-version-menu"))))
|
|
469
|
+
return;
|
|
470
|
+
setOpen(false);
|
|
471
|
+
};
|
|
472
|
+
window.addEventListener("click", onOutsideClick);
|
|
473
|
+
return () => window.removeEventListener("click", onOutsideClick);
|
|
474
|
+
}, [open, controlledOpen, onOpenChange]);
|
|
443
475
|
const dragStateRef = useRef(null);
|
|
444
476
|
const [dragging, setDragging] = useState(false);
|
|
445
477
|
const RESIZE_MIN = 220;
|
|
@@ -539,14 +571,13 @@ export function UnifiedVibeCard(props) {
|
|
|
539
571
|
const resizeValueNow = Math.round(Math.min(Math.max(userHeight ?? cardRef.current?.offsetHeight ?? 0, RESIZE_MIN), resizeValueMax));
|
|
540
572
|
return (React.createElement(React.Fragment, null,
|
|
541
573
|
React.createElement("style", null, unifiedVibeCardDarkCss),
|
|
542
|
-
open && (React.createElement("div", { "aria-hidden": true, "data-testid": "vibe-menu-backdrop", onClick: () => setOpen(false), style: { position: "fixed", inset: 0, zIndex: 1, pointerEvents: "auto" } })),
|
|
543
574
|
!hidden && (mounted || retained) && (React.createElement("div", { ref: cardRef, role: "dialog", "aria-label": "Vibe menu", "data-unified-vibe-card": true, className: props.className, "aria-hidden": mounted ? undefined : true, inert: mounted ? undefined : true, style: {
|
|
544
575
|
position: "absolute",
|
|
545
|
-
left:
|
|
546
|
-
right:
|
|
547
|
-
bottom:
|
|
576
|
+
left: 2,
|
|
577
|
+
right: 2,
|
|
578
|
+
bottom: 2,
|
|
548
579
|
zIndex: 2,
|
|
549
|
-
borderRadius:
|
|
580
|
+
borderRadius: 14,
|
|
550
581
|
maxHeight: cardHeight,
|
|
551
582
|
height: cardHeight,
|
|
552
583
|
overflow: "hidden",
|
|
@@ -573,7 +604,7 @@ export function UnifiedVibeCard(props) {
|
|
|
573
604
|
display: "flex",
|
|
574
605
|
alignItems: "center",
|
|
575
606
|
gap: 8,
|
|
576
|
-
padding: "
|
|
607
|
+
padding: "10px 10px 10px",
|
|
577
608
|
flexShrink: 0,
|
|
578
609
|
position: "relative",
|
|
579
610
|
userSelect: "none",
|
|
@@ -612,10 +643,18 @@ export function UnifiedVibeCard(props) {
|
|
|
612
643
|
props.appIconUrl && (React.createElement("img", { src: props.appIconUrl, alt: "", style: { width: "100%", height: "100%", objectFit: "cover", transform: "scale(2)" } })),
|
|
613
644
|
React.createElement(CodingIndicator, { active: props.coding === true })),
|
|
614
645
|
React.createElement("div", { style: { lineHeight: 1.2, minWidth: 0, flex: "1 1 auto" } },
|
|
615
|
-
React.createElement("strong", { style: {
|
|
646
|
+
React.createElement("strong", { style: {
|
|
647
|
+
fontFamily: HOME_BRAND_FONT,
|
|
648
|
+
display: "block",
|
|
649
|
+
fontSize: 13,
|
|
650
|
+
lineHeight: 1.3,
|
|
651
|
+
overflow: "hidden",
|
|
652
|
+
textOverflow: "ellipsis",
|
|
653
|
+
whiteSpace: "nowrap",
|
|
654
|
+
} }, appTitle),
|
|
616
655
|
appSlug &&
|
|
617
|
-
(props.onOpenApp === undefined && props.onCopyAppUrl === undefined ? (React.createElement("div", { className: "text-light-secondary dark:text-dark-secondary", style: { fontSize: 12 } }, appSlug)) : (React.createElement("div", { "data-vibe-card-header-controls": "true", "data-testid": "vibe-card-slug-line", style: { position: "relative", zIndex: 1, display: "flex", alignItems: "center", gap: 4, minWidth: 0 } },
|
|
618
|
-
props.onOpenApp === undefined ? (React.createElement("span", { className: "text-light-secondary dark:text-dark-secondary", style: { fontSize: 12 } }, appSlug)) : (React.createElement("button", { type: "button", "data-testid": "vibe-card-slug-link", onClick: props.onOpenApp, className: "text-light-secondary dark:text-dark-secondary", style: {
|
|
656
|
+
(props.onOpenApp === undefined && props.onCopyAppUrl === undefined ? (React.createElement("div", { className: "text-light-secondary dark:text-dark-secondary", style: { fontSize: 12, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, appSlug)) : (React.createElement("div", { "data-vibe-card-header-controls": "true", "data-testid": "vibe-card-slug-line", style: { position: "relative", zIndex: 1, display: "flex", alignItems: "center", gap: 4, minWidth: 0 } },
|
|
657
|
+
props.onOpenApp === undefined ? (React.createElement("span", { className: "text-light-secondary dark:text-dark-secondary", style: { fontSize: 12, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, appSlug)) : (React.createElement("button", { type: "button", "data-testid": "vibe-card-slug-link", onClick: props.onOpenApp, className: "text-light-secondary dark:text-dark-secondary", style: {
|
|
619
658
|
font: "inherit",
|
|
620
659
|
fontSize: 12,
|
|
621
660
|
lineHeight: "20px",
|
|
@@ -649,18 +688,20 @@ export function UnifiedVibeCard(props) {
|
|
|
649
688
|
alignItems: "center",
|
|
650
689
|
gap: 10,
|
|
651
690
|
flexShrink: 0,
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
691
|
+
maxWidth: "38%",
|
|
692
|
+
minWidth: 0,
|
|
693
|
+
} }, props.hideViewerTag ? null : props.handleSlug ? (React.createElement("div", { ref: pickerWrapRef, style: { position: "relative", minWidth: 0, maxWidth: "100%" } },
|
|
694
|
+
React.createElement(ViewerTagView, { slug: props.handleSlug, displayName: `@${props.handleSlug}`, avatarUrl: props.handleAvatarUrl, editable: Boolean(props.onPickAvatar), onPickFile: props.onPickAvatar, onTagClick: pickerInteractive ? () => setPickerOpen(!pickerOpen) : undefined, tagExpanded: pickerOpen, tagLabel: "Account and handles", style: {
|
|
695
|
+
background: "var(--color-light-background-01, #eee)",
|
|
696
|
+
border: "1px solid var(--color-light-decorative-01, #ddd)",
|
|
697
|
+
color: "var(--color-light-primary, #333)",
|
|
698
|
+
fontSize: 13,
|
|
699
|
+
padding: "3px 8px 3px 4px",
|
|
700
|
+
minWidth: 0,
|
|
701
|
+
maxWidth: "100%",
|
|
702
|
+
} }))) : props.viewerPending ? (React.createElement(ViewerTagView, { slug: "", pending: true })) : props.viewerNeedsHandle && !pickerInteractive ? (React.createElement(ViewerTagView, { slug: "", needsHandle: true, onChooseHandle: props.onChooseHandle })) : props.viewerNeedsHandle ? (React.createElement("div", { ref: pickerWrapRef },
|
|
703
|
+
React.createElement(ViewerTagView, { slug: "?", displayName: "Account", onTagClick: () => setPickerOpen(!pickerOpen), tagExpanded: pickerOpen, tagLabel: "Account and handles" }))) : pickerInteractive ? (React.createElement("div", { ref: pickerWrapRef },
|
|
704
|
+
React.createElement(ViewerTagView, { slug: "?", displayName: "Account", onTagClick: () => setPickerOpen(!pickerOpen), tagExpanded: pickerOpen, tagLabel: "Account and handles" }))) : (React.createElement(ViewerTagView, { slug: "?", anonymous: true, onSignIn: props.onSignIn })))),
|
|
664
705
|
(() => {
|
|
665
706
|
const wizardBanner = (props.publishWizardActive === true || props.publishWizardError === true) && props.onPublish;
|
|
666
707
|
if (wizardBanner && props.selectedNav !== "share") {
|
|
@@ -689,13 +730,9 @@ export function UnifiedVibeCard(props) {
|
|
|
689
730
|
return (React.createElement("div", { style: { padding: "0 14px", flexShrink: 0 } },
|
|
690
731
|
React.createElement(PublishBanner, { variant: props.publishState === "draft" || props.publishState === "old" ? props.publishState : undefined, onPublish: props.onPublish, publishing: props.publishing })));
|
|
691
732
|
}
|
|
692
|
-
|
|
693
|
-
if (!isOwnerChrome)
|
|
694
|
-
return null;
|
|
695
|
-
return (React.createElement("div", { style: { padding: "0 14px", flexShrink: 0 } },
|
|
696
|
-
React.createElement(AudienceLine, { access: props.publishAccess, pending: props.publishAccessPending, onShare: props.onShare })));
|
|
733
|
+
return null;
|
|
697
734
|
})(),
|
|
698
|
-
props.editorTab != null && props.selectedNav !== "share" && !agentPanelActive && (React.createElement("div", { "data-vibe-card-editor-tabs": true, style: { padding: "0 14px 6px", flexShrink: 0 } },
|
|
735
|
+
props.editorTab != null && props.editorTab !== "edit-chat" && props.selectedNav !== "share" && !agentPanelActive && (React.createElement("div", { "data-vibe-card-editor-tabs": true, style: { padding: "0 14px 6px", flexShrink: 0 } },
|
|
699
736
|
React.createElement(EditorTabStrip, { tab: props.editorTab, onTab: (t) => props.onEditorTab?.(t), standing: {
|
|
700
737
|
viewerMode: props.viewerMode,
|
|
701
738
|
memberReadOnly: props.memberReadOnly,
|
|
@@ -719,44 +756,49 @@ export function UnifiedVibeCard(props) {
|
|
|
719
756
|
...((props.bodyFill && props.body) || agentPanelActive || props.body == null
|
|
720
757
|
? { display: "flex", flexDirection: "column" }
|
|
721
758
|
: null),
|
|
722
|
-
} },
|
|
723
|
-
React.createElement("div", {
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
759
|
+
} },
|
|
760
|
+
props.retainedEditor != null && (React.createElement("div", { hidden: !props.editorVisible || agentPanelActive, inert: !props.editorVisible || agentPanelActive ? true : undefined, style: props.editorVisible && !agentPanelActive ? { flex: "1 1 auto", minHeight: 0 } : { display: "none" } }, props.retainedEditor)),
|
|
761
|
+
agentPanelActive ? (React.createElement("div", { style: { flex: "1 1 auto", minHeight: 0 } }, props.agentPanel)) : props.editorVisible && props.retainedEditor != null ? null : props.editorTab === "standing" ? (React.createElement(ViewerStandingView, { viewerMode: props.viewerMode, memberReadOnly: props.memberReadOnly, adminMode: props.adminMode, versionLocked: props.versionLocked, publishState: props.publishState, publishAccess: props.publishAccess, myGrant: props.myGrant, onToggleAdmin: props.onToggleAdmin, onUnlock: props.onUnlock })) : props.body != null ? (props.bodyFill ? (React.createElement("div", { style: { flex: "1 1 auto", minHeight: 0 } }, props.body)) : (props.body)) : (React.createElement(React.Fragment, null,
|
|
762
|
+
React.createElement("div", { ref: chipsRegionRef, style: streamFillActive
|
|
763
|
+
? { flex: "1 1 auto", minHeight: 0, display: "flex", flexDirection: "column" }
|
|
764
|
+
: { flex: "1 0 auto", minHeight: 0 } },
|
|
765
|
+
props.historyBody && (React.createElement("div", { "data-testid": "vibe-card-history", "aria-hidden": props.streamBody ? true : undefined, inert: props.streamBody ? true : undefined, style: { marginBottom: 8, ...(props.streamBody ? { display: "none" } : null) } }, props.historyBody)),
|
|
766
|
+
React.createElement("div", { "data-testid": "vibe-card-stream-region", style: {
|
|
767
|
+
position: "relative",
|
|
768
|
+
...(chipBuildLive ? { display: "flex", flexDirection: "column" } : {}),
|
|
769
|
+
...(streamFillActive ? { flex: "1 1 auto", minHeight: 0 } : null),
|
|
770
|
+
} },
|
|
771
|
+
props.streamBody && (React.createElement("div", { "data-testid": streamLive ? undefined : "vibe-card-stream-settled", style: streamLive
|
|
772
|
+
? {
|
|
773
|
+
...(chipBuildLive ? { flex: "1 1 auto" } : { position: "absolute", inset: 0 }),
|
|
774
|
+
display: "flex",
|
|
775
|
+
flexDirection: "column",
|
|
776
|
+
minHeight: 0,
|
|
777
|
+
}
|
|
778
|
+
: { marginBottom: 8 } },
|
|
779
|
+
React.createElement("div", { style: streamLive ? { flex: "1 1 auto", minHeight: 0, overflowY: "auto" } : undefined }, props.streamBody),
|
|
780
|
+
props.liveDuringBuild === true && React.createElement(PendingMessages, { messages: queued }))),
|
|
781
|
+
React.createElement("div", { "aria-hidden": streamLive && !chipBuildLive ? true : undefined, inert: streamLive && !chipBuildLive ? true : undefined, style: streamLive && !chipBuildLive ? { visibility: "hidden" } : { flexShrink: 0 } }, (props.seedOffer || props.upgradeChips || (visibleChips && visibleChips.length > 0)) && (React.createElement("div", { className: "mx-auto mt-2 w-full max-w-5xl" },
|
|
782
|
+
React.createElement(ChatMessageRow, { role: "ai", rowAttrs: { "data-message-role": "suggestions" } },
|
|
783
|
+
React.createElement("div", { className: "vibes-chip-well flex flex-col", "data-testid": "vibe-chip-set" },
|
|
784
|
+
(props.seedOffer || props.upgradeChips) && (React.createElement("div", { className: "flex flex-col gap-[6px]", inert: props.activeChip !== undefined },
|
|
785
|
+
props.seedOffer,
|
|
786
|
+
props.upgradeChips)),
|
|
787
|
+
visibleChips && visibleChips.length > 0 && (React.createElement(OptionButtons, { options: visibleChips, activeOption: props.activeChip, inSet: true, isFirst: props.activeChip === undefined, firstMessage: props.isOwner
|
|
788
|
+
? "Suggested requests:"
|
|
789
|
+
: "Describe a change to remix your own copy of this app:", onSelect: (o) => {
|
|
790
|
+
const r = props.onSelectChip?.(o);
|
|
791
|
+
return r && typeof r === "object" && "then" in r ? r.then((ok) => ok ?? false) : false;
|
|
792
|
+
}, decorate: (option) => decorateChip(option, props) }))))))),
|
|
793
|
+
props.streamFooter !== undefined && React.createElement("div", { className: "mx-auto w-full max-w-5xl" }, props.streamFooter)))))),
|
|
752
794
|
props.body == null && !agentPanelActive && (React.createElement("div", { style: { flexShrink: 0, padding: "0 14px 10px" } },
|
|
753
795
|
React.createElement(OtherRow, { value: draft, onValueChange: setDraft, queued: queued, onQueuedChange: setQueued, onSubmitOther: props.onSubmitOther, generating: props.generating, liveDuringBuild: props.liveDuringBuild, canSendNow: props.canSendNow, onStop: props.onStop, stopDisabled: props.stopDisabled, attachmentsCtl: attachmentsCtl }))),
|
|
754
|
-
agentPanelActive ? (React.createElement("div", { "aria-hidden": true, style: { display: "flex", flexShrink: 0, padding: "0
|
|
796
|
+
agentPanelActive ? (React.createElement("div", { "aria-hidden": true, style: { display: "flex", flexShrink: 0, padding: "0 8px" } },
|
|
755
797
|
React.createElement("div", { style: { width: 120, height: 50, marginLeft: "auto" } }))) : (React.createElement("div", { style: {
|
|
756
798
|
display: "flex",
|
|
757
799
|
alignItems: "center",
|
|
758
800
|
gap: "var(--uvc-nav-gap, 6px)",
|
|
759
|
-
padding: "0
|
|
801
|
+
padding: "0 8px",
|
|
760
802
|
borderTop: "1px solid var(--color-light-decorative-00, #e5e5e5)",
|
|
761
803
|
flexShrink: 0,
|
|
762
804
|
} },
|
|
@@ -764,52 +806,74 @@ export function UnifiedVibeCard(props) {
|
|
|
764
806
|
React.createElement("svg", { width: "17", height: "17", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true" },
|
|
765
807
|
React.createElement("path", { d: "M3 12l9-9 9 9" }),
|
|
766
808
|
React.createElement("path", { d: "M5 10v10a1 1 0 001 1h4v-6h4v6h4a1 1 0 001-1V10" }))),
|
|
767
|
-
React.createElement(NavIcon, { label: "
|
|
768
|
-
React.createElement(
|
|
769
|
-
|
|
809
|
+
React.createElement(NavIcon, { label: "Chat", color: "var(--uvc-nav-chat, #7c3aed)", selected: props.selectedNav === "edit-chat", onClick: props.onChat },
|
|
810
|
+
React.createElement("svg", { width: "17", height: "17", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true" },
|
|
811
|
+
React.createElement("path", { d: "M21 11a8 8 0 01-8 8H7l-4 3V11a9 9 0 0118 0Z" }))),
|
|
812
|
+
React.createElement(NavIcon, { label: "Edit", color: "var(--uvc-nav-edit, #c2410c)", selected: ["edit", "standing", "code", "files", "data", "style", "settings", "faq"].includes(props.selectedNav ?? "edit"), onClick: props.onEdit },
|
|
770
813
|
React.createElement("svg", { width: "17", height: "17", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true" },
|
|
771
814
|
React.createElement("path", { d: "M12 20h9" }),
|
|
772
815
|
React.createElement("path", { d: "M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5z" }))),
|
|
773
|
-
React.createElement(NavIcon, { label: "Share", color: "var(--uvc-nav-share, #15803d)", selected: props.selectedNav === "share", onClick: props.onShare, buttonRef: props.shareButtonRef, badgeCount:
|
|
816
|
+
React.createElement(NavIcon, { label: "Share", color: "var(--uvc-nav-share, #15803d)", selected: props.selectedNav === "share", onClick: props.onShare, buttonRef: props.shareButtonRef, badgeCount: props.pendingRequestCount ?? 0 },
|
|
774
817
|
React.createElement(PeopleIcon, null)),
|
|
775
|
-
React.createElement(NavIcon, { label: "FAQ", color: "var(--uvc-nav-faq, #4b5563)", selected: props.selectedNav === "faq", onClick: props.onAbout }, "?"),
|
|
776
818
|
React.createElement("div", { "aria-hidden": true, style: { width: 120, height: 50, flexShrink: 0, marginLeft: "auto" } })))))),
|
|
777
|
-
open && pickerInteractive && pickerOpen &&
|
|
819
|
+
open && pickerInteractive && pickerOpen && (React.createElement("div", { ref: menuRef, "data-vibe-handle-menu": true, className: "text-light-primary dark:text-dark-primary", style: {
|
|
778
820
|
position: "fixed",
|
|
779
821
|
top: `calc(${SAFE_AREA_TOP} + 16px)`,
|
|
780
822
|
right: 3,
|
|
781
823
|
zIndex: 4,
|
|
782
824
|
pointerEvents: "auto",
|
|
783
|
-
} },
|
|
784
|
-
|
|
785
|
-
props.
|
|
825
|
+
} }, React.createElement(HandlePickerMenu, { handles: props.handles ?? [], activeSlug: props.handleSlug, busy: props.handlePickerBusy, header: creditsEnabled ? (React.createElement("div", { style: { padding: 8 } },
|
|
826
|
+
React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10 } },
|
|
827
|
+
React.createElement(CreditsRingView, { remaining: props.credits?.remaining, grantIncluded: props.credits?.grantIncluded, loading: props.credits?.loading, expanded: creditsOpen, onClick: () => setCreditsOpen(!creditsOpen) }),
|
|
828
|
+
React.createElement("span", null, "Credits")),
|
|
829
|
+
creditsOpen && (React.createElement(CreditsDetailMenu, { plan: props.credits?.plan, remaining: props.credits?.remaining, grantRemaining: props.credits?.grantRemaining, grantIncluded: props.credits?.grantIncluded, grantResetsAt: props.credits?.grantResetsAt, purchasedRemaining: props.credits?.purchasedRemaining, loading: props.credits?.loading, style: {
|
|
830
|
+
position: "static",
|
|
831
|
+
right: "auto",
|
|
832
|
+
top: "auto",
|
|
833
|
+
bottom: "auto",
|
|
834
|
+
width: "100%",
|
|
835
|
+
minWidth: 0,
|
|
836
|
+
boxShadow: "none",
|
|
837
|
+
border: "none",
|
|
838
|
+
padding: 0,
|
|
839
|
+
}, onManage: props.onManageCredits
|
|
840
|
+
? () => {
|
|
841
|
+
props.onManageCredits?.();
|
|
842
|
+
setCreditsOpen(false);
|
|
843
|
+
}
|
|
844
|
+
: undefined })))) : undefined, onSignIn: props.onSignIn, onChooseHandle: props.viewerNeedsHandle ? props.onChooseHandle : undefined, onSettings: props.onAccountSettings
|
|
845
|
+
? () => {
|
|
846
|
+
props.onAccountSettings?.();
|
|
786
847
|
setPickerOpen(false);
|
|
787
|
-
}
|
|
848
|
+
}
|
|
849
|
+
: undefined, onMyVibes: props.onMyVibes
|
|
850
|
+
? () => {
|
|
851
|
+
props.onMyVibes?.();
|
|
852
|
+
setPickerOpen(false);
|
|
853
|
+
}
|
|
854
|
+
: undefined, onMemberships: props.onMemberships
|
|
855
|
+
? () => {
|
|
856
|
+
props.onMemberships?.();
|
|
857
|
+
setPickerOpen(false);
|
|
858
|
+
}
|
|
859
|
+
: undefined, style: { position: "static", right: "auto", top: "auto", bottom: "auto" }, onSelect: (slug) => {
|
|
860
|
+
props.onSelectHandle?.(slug);
|
|
861
|
+
setPickerOpen(false);
|
|
862
|
+
}, onNewHandle: props.onNewHandle
|
|
863
|
+
? (handle) => {
|
|
788
864
|
props.onNewHandle?.(handle);
|
|
789
865
|
setPickerOpen(false);
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
top: `calc(${SAFE_AREA_TOP} + 16px)`,
|
|
799
|
-
right: 3,
|
|
800
|
-
zIndex: 4,
|
|
801
|
-
pointerEvents: "auto",
|
|
802
|
-
} },
|
|
803
|
-
React.createElement(CreditsDetailMenu, { plan: props.credits?.plan, remaining: props.credits?.remaining, grantRemaining: props.credits?.grantRemaining, grantIncluded: props.credits?.grantIncluded, grantResetsAt: props.credits?.grantResetsAt, purchasedRemaining: props.credits?.purchasedRemaining, loading: props.credits?.loading, style: { position: "static", right: "auto", top: "auto", bottom: "auto" }, onManage: props.onManageCredits
|
|
804
|
-
? () => {
|
|
805
|
-
props.onManageCredits?.();
|
|
806
|
-
setCreditsOpen(false);
|
|
807
|
-
}
|
|
808
|
-
: undefined }))),
|
|
809
|
-
!hidden && (React.createElement("div", { style: {
|
|
866
|
+
}
|
|
867
|
+
: undefined, onLogout: props.onLogout
|
|
868
|
+
? () => {
|
|
869
|
+
props.onLogout?.();
|
|
870
|
+
setPickerOpen(false);
|
|
871
|
+
}
|
|
872
|
+
: undefined }))),
|
|
873
|
+
!hidden && (React.createElement("div", { ref: switchWrapRef, style: {
|
|
810
874
|
position: "absolute",
|
|
811
|
-
right:
|
|
812
|
-
bottom:
|
|
875
|
+
right: 2,
|
|
876
|
+
bottom: 7,
|
|
813
877
|
zIndex: 3,
|
|
814
878
|
pointerEvents: "auto",
|
|
815
879
|
display: "flex",
|
|
@@ -1110,31 +1174,6 @@ function PublishBanner({ variant, onPublish, publishing, locked, onUnlock, autoP
|
|
|
1110
1174
|
opacity: publishing ? 0.6 : 1,
|
|
1111
1175
|
} }, publishing ? "Publishing…" : variant === "draft" ? "Update" : "Publish this version"))));
|
|
1112
1176
|
}
|
|
1113
|
-
function AudienceLine({ access, pending, onShare, }) {
|
|
1114
|
-
return (React.createElement("div", { "data-testid": "vibe-card-audience-line", className: "text-light-secondary dark:text-dark-secondary", style: {
|
|
1115
|
-
display: "flex",
|
|
1116
|
-
alignItems: "baseline",
|
|
1117
|
-
gap: 6,
|
|
1118
|
-
marginBottom: 10,
|
|
1119
|
-
fontSize: 12,
|
|
1120
|
-
lineHeight: 1.4,
|
|
1121
|
-
} },
|
|
1122
|
-
React.createElement("span", null, pending === true
|
|
1123
|
-
? "Checking who can open it…"
|
|
1124
|
-
: access === "public"
|
|
1125
|
-
? "Anyone with the link can open it."
|
|
1126
|
-
: "Only people you approve can open it."),
|
|
1127
|
-
pending !== true && onShare && (React.createElement("button", { type: "button", onClick: onShare, "aria-label": "Change who can open this vibe", style: {
|
|
1128
|
-
flexShrink: 0,
|
|
1129
|
-
background: "transparent",
|
|
1130
|
-
border: "none",
|
|
1131
|
-
padding: 0,
|
|
1132
|
-
font: "inherit",
|
|
1133
|
-
color: "currentColor",
|
|
1134
|
-
textDecoration: "underline",
|
|
1135
|
-
cursor: "pointer",
|
|
1136
|
-
} }, "Change"))));
|
|
1137
|
-
}
|
|
1138
1177
|
function decorateChip(option, props) {
|
|
1139
1178
|
const fp = props.chipFastPaths?.[option];
|
|
1140
1179
|
if (!fp)
|