@vibes.diy/base 14.2.6 → 14.2.8
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 +6 -1
- package/components/UnifiedVibeCard.js +164 -145
- 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);
|
|
@@ -539,14 +552,13 @@ export function UnifiedVibeCard(props) {
|
|
|
539
552
|
const resizeValueNow = Math.round(Math.min(Math.max(userHeight ?? cardRef.current?.offsetHeight ?? 0, RESIZE_MIN), resizeValueMax));
|
|
540
553
|
return (React.createElement(React.Fragment, null,
|
|
541
554
|
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
555
|
!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
556
|
position: "absolute",
|
|
545
|
-
left:
|
|
546
|
-
right:
|
|
547
|
-
bottom:
|
|
557
|
+
left: 2,
|
|
558
|
+
right: 2,
|
|
559
|
+
bottom: 2,
|
|
548
560
|
zIndex: 2,
|
|
549
|
-
borderRadius:
|
|
561
|
+
borderRadius: 14,
|
|
550
562
|
maxHeight: cardHeight,
|
|
551
563
|
height: cardHeight,
|
|
552
564
|
overflow: "hidden",
|
|
@@ -573,7 +585,7 @@ export function UnifiedVibeCard(props) {
|
|
|
573
585
|
display: "flex",
|
|
574
586
|
alignItems: "center",
|
|
575
587
|
gap: 8,
|
|
576
|
-
padding: "
|
|
588
|
+
padding: "10px 10px 10px",
|
|
577
589
|
flexShrink: 0,
|
|
578
590
|
position: "relative",
|
|
579
591
|
userSelect: "none",
|
|
@@ -612,10 +624,18 @@ export function UnifiedVibeCard(props) {
|
|
|
612
624
|
props.appIconUrl && (React.createElement("img", { src: props.appIconUrl, alt: "", style: { width: "100%", height: "100%", objectFit: "cover", transform: "scale(2)" } })),
|
|
613
625
|
React.createElement(CodingIndicator, { active: props.coding === true })),
|
|
614
626
|
React.createElement("div", { style: { lineHeight: 1.2, minWidth: 0, flex: "1 1 auto" } },
|
|
615
|
-
React.createElement("strong", { style: {
|
|
627
|
+
React.createElement("strong", { style: {
|
|
628
|
+
fontFamily: HOME_BRAND_FONT,
|
|
629
|
+
display: "block",
|
|
630
|
+
fontSize: 13,
|
|
631
|
+
lineHeight: 1.3,
|
|
632
|
+
overflow: "hidden",
|
|
633
|
+
textOverflow: "ellipsis",
|
|
634
|
+
whiteSpace: "nowrap",
|
|
635
|
+
} }, appTitle),
|
|
616
636
|
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: {
|
|
637
|
+
(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 } },
|
|
638
|
+
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
639
|
font: "inherit",
|
|
620
640
|
fontSize: 12,
|
|
621
641
|
lineHeight: "20px",
|
|
@@ -649,18 +669,20 @@ export function UnifiedVibeCard(props) {
|
|
|
649
669
|
alignItems: "center",
|
|
650
670
|
gap: 10,
|
|
651
671
|
flexShrink: 0,
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
672
|
+
maxWidth: "38%",
|
|
673
|
+
minWidth: 0,
|
|
674
|
+
} }, props.hideViewerTag ? null : props.handleSlug ? (React.createElement("div", { ref: pickerWrapRef, style: { position: "relative", minWidth: 0, maxWidth: "100%" } },
|
|
675
|
+
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: {
|
|
676
|
+
background: "var(--color-light-background-01, #eee)",
|
|
677
|
+
border: "1px solid var(--color-light-decorative-01, #ddd)",
|
|
678
|
+
color: "var(--color-light-primary, #333)",
|
|
679
|
+
fontSize: 13,
|
|
680
|
+
padding: "3px 8px 3px 4px",
|
|
681
|
+
minWidth: 0,
|
|
682
|
+
maxWidth: "100%",
|
|
683
|
+
} }))) : 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 },
|
|
684
|
+
React.createElement(ViewerTagView, { slug: "?", displayName: "Account", onTagClick: () => setPickerOpen(!pickerOpen), tagExpanded: pickerOpen, tagLabel: "Account and handles" }))) : pickerInteractive ? (React.createElement("div", { ref: pickerWrapRef },
|
|
685
|
+
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
686
|
(() => {
|
|
665
687
|
const wizardBanner = (props.publishWizardActive === true || props.publishWizardError === true) && props.onPublish;
|
|
666
688
|
if (wizardBanner && props.selectedNav !== "share") {
|
|
@@ -689,13 +711,9 @@ export function UnifiedVibeCard(props) {
|
|
|
689
711
|
return (React.createElement("div", { style: { padding: "0 14px", flexShrink: 0 } },
|
|
690
712
|
React.createElement(PublishBanner, { variant: props.publishState === "draft" || props.publishState === "old" ? props.publishState : undefined, onPublish: props.onPublish, publishing: props.publishing })));
|
|
691
713
|
}
|
|
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 })));
|
|
714
|
+
return null;
|
|
697
715
|
})(),
|
|
698
|
-
props.editorTab != null && props.selectedNav !== "share" && !agentPanelActive && (React.createElement("div", { "data-vibe-card-editor-tabs": true, style: { padding: "0 14px 6px", flexShrink: 0 } },
|
|
716
|
+
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
717
|
React.createElement(EditorTabStrip, { tab: props.editorTab, onTab: (t) => props.onEditorTab?.(t), standing: {
|
|
700
718
|
viewerMode: props.viewerMode,
|
|
701
719
|
memberReadOnly: props.memberReadOnly,
|
|
@@ -719,44 +737,48 @@ export function UnifiedVibeCard(props) {
|
|
|
719
737
|
...((props.bodyFill && props.body) || agentPanelActive || props.body == null
|
|
720
738
|
? { display: "flex", flexDirection: "column" }
|
|
721
739
|
: 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
|
-
|
|
740
|
+
} },
|
|
741
|
+
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)),
|
|
742
|
+
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,
|
|
743
|
+
React.createElement("div", { ref: chipsRegionRef, style: streamFillActive
|
|
744
|
+
? { flex: "1 1 auto", minHeight: 0, display: "flex", flexDirection: "column" }
|
|
745
|
+
: { flex: "1 0 auto", minHeight: 0 } },
|
|
746
|
+
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)),
|
|
747
|
+
React.createElement("div", { "data-testid": "vibe-card-stream-region", style: {
|
|
748
|
+
position: "relative",
|
|
749
|
+
...(chipBuildLive ? { display: "flex", flexDirection: "column" } : {}),
|
|
750
|
+
...(streamFillActive ? { flex: "1 1 auto", minHeight: 0 } : null),
|
|
751
|
+
} },
|
|
752
|
+
props.streamBody && (React.createElement("div", { "data-testid": streamLive ? undefined : "vibe-card-stream-settled", style: streamLive
|
|
753
|
+
? {
|
|
754
|
+
...(chipBuildLive ? { flex: "1 1 auto" } : { position: "absolute", inset: 0 }),
|
|
755
|
+
display: "flex",
|
|
756
|
+
flexDirection: "column",
|
|
757
|
+
minHeight: 0,
|
|
758
|
+
}
|
|
759
|
+
: { marginBottom: 8 } },
|
|
760
|
+
React.createElement("div", { style: streamLive ? { flex: "1 1 auto", minHeight: 0, overflowY: "auto" } : undefined }, props.streamBody),
|
|
761
|
+
props.liveDuringBuild === true && React.createElement(PendingMessages, { messages: queued }))),
|
|
762
|
+
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" },
|
|
763
|
+
React.createElement(ChatMessageRow, { role: "ai", rowAttrs: { "data-message-role": "suggestions" } },
|
|
764
|
+
React.createElement("div", { className: "vibes-chip-well flex flex-col", "data-testid": "vibe-chip-set" },
|
|
765
|
+
(props.seedOffer || props.upgradeChips) && (React.createElement("div", { className: "flex flex-col gap-[6px]", inert: props.activeChip !== undefined },
|
|
766
|
+
props.seedOffer,
|
|
767
|
+
props.upgradeChips)),
|
|
768
|
+
visibleChips && visibleChips.length > 0 && (React.createElement(OptionButtons, { options: visibleChips, activeOption: props.activeChip, inSet: true, isFirst: props.activeChip === undefined, firstMessage: props.isOwner
|
|
769
|
+
? "Suggested requests:"
|
|
770
|
+
: "Describe a change to remix your own copy of this app:", onSelect: (o) => {
|
|
771
|
+
const r = props.onSelectChip?.(o);
|
|
772
|
+
return r && typeof r === "object" && "then" in r ? r.then((ok) => ok ?? false) : false;
|
|
773
|
+
}, decorate: (option) => decorateChip(option, props) })))))))))))),
|
|
752
774
|
props.body == null && !agentPanelActive && (React.createElement("div", { style: { flexShrink: 0, padding: "0 14px 10px" } },
|
|
753
775
|
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
|
|
776
|
+
agentPanelActive ? (React.createElement("div", { "aria-hidden": true, style: { display: "flex", flexShrink: 0, padding: "0 8px" } },
|
|
755
777
|
React.createElement("div", { style: { width: 120, height: 50, marginLeft: "auto" } }))) : (React.createElement("div", { style: {
|
|
756
778
|
display: "flex",
|
|
757
779
|
alignItems: "center",
|
|
758
780
|
gap: "var(--uvc-nav-gap, 6px)",
|
|
759
|
-
padding: "0
|
|
781
|
+
padding: "0 8px",
|
|
760
782
|
borderTop: "1px solid var(--color-light-decorative-00, #e5e5e5)",
|
|
761
783
|
flexShrink: 0,
|
|
762
784
|
} },
|
|
@@ -764,52 +786,74 @@ export function UnifiedVibeCard(props) {
|
|
|
764
786
|
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
787
|
React.createElement("path", { d: "M3 12l9-9 9 9" }),
|
|
766
788
|
React.createElement("path", { d: "M5 10v10a1 1 0 001 1h4v-6h4v6h4a1 1 0 001-1V10" }))),
|
|
767
|
-
React.createElement(NavIcon, { label: "
|
|
768
|
-
React.createElement(
|
|
769
|
-
|
|
789
|
+
React.createElement(NavIcon, { label: "Chat", color: "var(--uvc-nav-chat, #7c3aed)", selected: props.selectedNav === "edit-chat", onClick: props.onChat },
|
|
790
|
+
React.createElement("svg", { width: "17", height: "17", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true" },
|
|
791
|
+
React.createElement("path", { d: "M21 11a8 8 0 01-8 8H7l-4 3V11a9 9 0 0118 0Z" }))),
|
|
792
|
+
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
793
|
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
794
|
React.createElement("path", { d: "M12 20h9" }),
|
|
772
795
|
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:
|
|
796
|
+
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
797
|
React.createElement(PeopleIcon, null)),
|
|
775
|
-
React.createElement(NavIcon, { label: "FAQ", color: "var(--uvc-nav-faq, #4b5563)", selected: props.selectedNav === "faq", onClick: props.onAbout }, "?"),
|
|
776
798
|
React.createElement("div", { "aria-hidden": true, style: { width: 120, height: 50, flexShrink: 0, marginLeft: "auto" } })))))),
|
|
777
|
-
open && pickerInteractive && pickerOpen &&
|
|
799
|
+
open && pickerInteractive && pickerOpen && (React.createElement("div", { ref: menuRef, "data-vibe-handle-menu": true, className: "text-light-primary dark:text-dark-primary", style: {
|
|
778
800
|
position: "fixed",
|
|
779
801
|
top: `calc(${SAFE_AREA_TOP} + 16px)`,
|
|
780
802
|
right: 3,
|
|
781
803
|
zIndex: 4,
|
|
782
804
|
pointerEvents: "auto",
|
|
783
|
-
} },
|
|
784
|
-
|
|
785
|
-
props.
|
|
805
|
+
} }, React.createElement(HandlePickerMenu, { handles: props.handles ?? [], activeSlug: props.handleSlug, busy: props.handlePickerBusy, header: creditsEnabled ? (React.createElement("div", { style: { padding: 8 } },
|
|
806
|
+
React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10 } },
|
|
807
|
+
React.createElement(CreditsRingView, { remaining: props.credits?.remaining, grantIncluded: props.credits?.grantIncluded, loading: props.credits?.loading, expanded: creditsOpen, onClick: () => setCreditsOpen(!creditsOpen) }),
|
|
808
|
+
React.createElement("span", null, "Credits")),
|
|
809
|
+
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: {
|
|
810
|
+
position: "static",
|
|
811
|
+
right: "auto",
|
|
812
|
+
top: "auto",
|
|
813
|
+
bottom: "auto",
|
|
814
|
+
width: "100%",
|
|
815
|
+
minWidth: 0,
|
|
816
|
+
boxShadow: "none",
|
|
817
|
+
border: "none",
|
|
818
|
+
padding: 0,
|
|
819
|
+
}, onManage: props.onManageCredits
|
|
820
|
+
? () => {
|
|
821
|
+
props.onManageCredits?.();
|
|
822
|
+
setCreditsOpen(false);
|
|
823
|
+
}
|
|
824
|
+
: undefined })))) : undefined, onSignIn: props.onSignIn, onChooseHandle: props.viewerNeedsHandle ? props.onChooseHandle : undefined, onSettings: props.onAccountSettings
|
|
825
|
+
? () => {
|
|
826
|
+
props.onAccountSettings?.();
|
|
827
|
+
setPickerOpen(false);
|
|
828
|
+
}
|
|
829
|
+
: undefined, onMyVibes: props.onMyVibes
|
|
830
|
+
? () => {
|
|
831
|
+
props.onMyVibes?.();
|
|
832
|
+
setPickerOpen(false);
|
|
833
|
+
}
|
|
834
|
+
: undefined, onMemberships: props.onMemberships
|
|
835
|
+
? () => {
|
|
836
|
+
props.onMemberships?.();
|
|
786
837
|
setPickerOpen(false);
|
|
787
|
-
}
|
|
838
|
+
}
|
|
839
|
+
: undefined, style: { position: "static", right: "auto", top: "auto", bottom: "auto" }, onSelect: (slug) => {
|
|
840
|
+
props.onSelectHandle?.(slug);
|
|
841
|
+
setPickerOpen(false);
|
|
842
|
+
}, onNewHandle: props.onNewHandle
|
|
843
|
+
? (handle) => {
|
|
788
844
|
props.onNewHandle?.(handle);
|
|
789
845
|
setPickerOpen(false);
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
position: "fixed",
|
|
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 }))),
|
|
846
|
+
}
|
|
847
|
+
: undefined, onLogout: props.onLogout
|
|
848
|
+
? () => {
|
|
849
|
+
props.onLogout?.();
|
|
850
|
+
setPickerOpen(false);
|
|
851
|
+
}
|
|
852
|
+
: undefined }))),
|
|
809
853
|
!hidden && (React.createElement("div", { style: {
|
|
810
854
|
position: "absolute",
|
|
811
|
-
right:
|
|
812
|
-
bottom:
|
|
855
|
+
right: 2,
|
|
856
|
+
bottom: 7,
|
|
813
857
|
zIndex: 3,
|
|
814
858
|
pointerEvents: "auto",
|
|
815
859
|
display: "flex",
|
|
@@ -1110,31 +1154,6 @@ function PublishBanner({ variant, onPublish, publishing, locked, onUnlock, autoP
|
|
|
1110
1154
|
opacity: publishing ? 0.6 : 1,
|
|
1111
1155
|
} }, publishing ? "Publishing…" : variant === "draft" ? "Update" : "Publish this version"))));
|
|
1112
1156
|
}
|
|
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
1157
|
function decorateChip(option, props) {
|
|
1139
1158
|
const fp = props.chipFastPaths?.[option];
|
|
1140
1159
|
if (!fp)
|