@vibes.diy/base 14.3.106 → 14.3.107
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/vibe-menu/VibeMenu.js +5 -3
- package/components/vibe-menu/VibeMenu.js.map +1 -1
- package/components/vibe-menu/cards/AccountCard.d.ts +4 -0
- package/components/vibe-menu/cards/AccountCard.js +64 -1
- package/components/vibe-menu/cards/AccountCard.js.map +1 -1
- package/components/vibe-menu/cards/CodeCard.d.ts +2 -1
- package/components/vibe-menu/cards/CodeCard.js +12 -3
- package/components/vibe-menu/cards/CodeCard.js.map +1 -1
- package/components/vibe-menu/cards/CodeTabRow.d.ts +1 -1
- package/components/vibe-menu/cards/CodeTabRow.js +6 -0
- package/components/vibe-menu/cards/CodeTabRow.js.map +1 -1
- package/components/vibe-menu/cards/HomeCard.d.ts +8 -0
- package/components/vibe-menu/cards/HomeCard.js +67 -5
- package/components/vibe-menu/cards/HomeCard.js.map +1 -1
- package/components/vibe-menu/cards/ShareCard.d.ts +3 -0
- package/components/vibe-menu/cards/ShareCard.js +109 -16
- package/components/vibe-menu/cards/ShareCard.js.map +1 -1
- package/components/vibe-menu/index.d.ts +3 -0
- package/components/vibe-menu/index.js +3 -0
- package/components/vibe-menu/index.js.map +1 -1
- package/components/vibe-menu/moments.d.ts +9 -0
- package/components/vibe-menu/moments.js +6 -0
- package/components/vibe-menu/moments.js.map +1 -1
- package/components/vibe-menu/parts/AccessToggle.js +2 -1
- package/components/vibe-menu/parts/AccessToggle.js.map +1 -1
- package/components/vibe-menu/parts/CardTabRow.d.ts +27 -0
- package/components/vibe-menu/{sketches → parts}/CardTabRow.js +2 -7
- package/components/vibe-menu/parts/CardTabRow.js.map +1 -0
- package/components/vibe-menu/parts/Composer.js +2 -1
- package/components/vibe-menu/parts/Composer.js.map +1 -1
- package/components/vibe-menu/parts/MomentLine.js +10 -5
- package/components/vibe-menu/parts/MomentLine.js.map +1 -1
- package/components/vibe-menu/parts/SurveyStrip.d.ts +13 -3
- package/components/vibe-menu/parts/SurveyStrip.js +97 -54
- package/components/vibe-menu/parts/SurveyStrip.js.map +1 -1
- package/components/vibe-menu/parts/ThinkingLine.d.ts +24 -0
- package/components/vibe-menu/parts/ThinkingLine.js +77 -0
- package/components/vibe-menu/parts/ThinkingLine.js.map +1 -0
- package/components/vibe-menu/parts/brief-faces-art.d.ts +12 -0
- package/components/vibe-menu/parts/brief-faces-art.js +540 -0
- package/components/vibe-menu/parts/brief-faces-art.js.map +1 -0
- package/components/vibe-menu/sketches/CodeTierAudition.js +1 -1
- package/components/vibe-menu/sketches/CodeTierAudition.js.map +1 -1
- package/components/vibe-menu/slices.d.ts +5 -0
- package/components/vibe-menu/slices.js.map +1 -1
- package/components/vibe-menu/vibe-menu.styles.d.ts +1 -1
- package/components/vibe-menu/vibe-menu.styles.js +0 -25
- package/components/vibe-menu/vibe-menu.styles.js.map +1 -1
- package/package.json +5 -5
- package/components/vibe-menu/sketches/AccountTabAudition.d.ts +0 -11
- package/components/vibe-menu/sketches/AccountTabAudition.js +0 -90
- package/components/vibe-menu/sketches/AccountTabAudition.js.map +0 -1
- package/components/vibe-menu/sketches/CardTabRow.d.ts +0 -27
- package/components/vibe-menu/sketches/CardTabRow.js.map +0 -1
- package/components/vibe-menu/sketches/HomeTabAudition.d.ts +0 -26
- package/components/vibe-menu/sketches/HomeTabAudition.js +0 -87
- package/components/vibe-menu/sketches/HomeTabAudition.js.map +0 -1
- package/components/vibe-menu/sketches/ShareTabAudition.d.ts +0 -14
- package/components/vibe-menu/sketches/ShareTabAudition.js +0 -155
- package/components/vibe-menu/sketches/ShareTabAudition.js.map +0 -1
|
@@ -4,21 +4,31 @@ export interface SurveyFace {
|
|
|
4
4
|
readonly label: string;
|
|
5
5
|
readonly pitch: string;
|
|
6
6
|
}
|
|
7
|
+
export interface SurveyChoosing {
|
|
8
|
+
readonly index: number;
|
|
9
|
+
readonly endsAtMs: number;
|
|
10
|
+
}
|
|
7
11
|
export interface CodeSurvey {
|
|
8
12
|
readonly id: string;
|
|
9
13
|
readonly faces: readonly SurveyFace[];
|
|
10
14
|
readonly picked?: number;
|
|
11
15
|
readonly onPick?: (index: number) => void;
|
|
16
|
+
readonly onChoose?: (index: number) => void;
|
|
17
|
+
readonly onCancel?: () => void;
|
|
18
|
+
readonly choosing?: SurveyChoosing;
|
|
12
19
|
readonly onShown?: (faces: number) => void;
|
|
13
20
|
}
|
|
21
|
+
export declare const SURVEY_COUNTDOWN_MS = 3000;
|
|
14
22
|
export declare const SURVEY_COPY: Readonly<{
|
|
15
|
-
readonly choosing: "
|
|
23
|
+
readonly choosing: "Pick a look for your app";
|
|
16
24
|
readonly aside: "Optional · the build goes on";
|
|
25
|
+
readonly counting: "Tap again to cancel";
|
|
17
26
|
readonly picked: "Building in this look";
|
|
18
|
-
readonly pick: "Build this one";
|
|
19
27
|
readonly region: "Steer the look";
|
|
20
28
|
}>;
|
|
21
|
-
export declare
|
|
29
|
+
export declare function surveyCountdownDigit(msLeft: number): number;
|
|
30
|
+
export declare function surveyTileLabel(face: SurveyFace, digit: number | undefined): string;
|
|
31
|
+
export declare const SURVEY_STRIP_CSS = "\n/* Its own container: the aside steps out when the strip itself is narrow, on any host. */\n[data-vibe-menu] .vm-survey { margin: 0 0 var(--space-14); container: vm-survey / inline-size; }\n/* Code mode's card is wide and its pinned top is capped: the strip keeps the card-sized tiles. */\n[data-vibe-menu] .vm-codemode .vm-survey { margin-bottom: 10px; max-width: 420px; }\n[data-vibe-menu] .vm-survey-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-8); margin: 0 0 var(--space-8); padding: 0 var(--space-2); }\n[data-vibe-menu] .vm-survey-title { font: 600 15px/1.3 var(--font-display); color: var(--ink); }\n[data-vibe-menu] .vm-survey-aside { font: 400 12px/1.3 var(--font-display); color: var(--muted); white-space: nowrap; }\n[data-vibe-menu] .vm-survey-strip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-8); }\n/* Three readings keep the four-up tile size: the missing tile's column stays empty. */\n[data-vibe-menu] .vm-survey-strip[data-count=\"3\"] { grid-template-columns: repeat(3, minmax(0, 1fr)); padding-right: calc((100% - 24px) / 4 + 8px); }\n[data-vibe-menu] .vm-survey-cell { min-width: 0; }\n[data-vibe-menu] .vm-survey-tile { position: relative; display: block; width: 100%; min-height: 44px; padding: 0; aspect-ratio: 1; border: var(--stroke-rule) solid var(--line-card); border-radius: var(--radius-switch); overflow: hidden; background: var(--card-bg); cursor: pointer; touch-action: manipulation; }\n[data-vibe-menu] .vm-survey-tile[data-on=\"true\"] { outline: var(--stroke-focus) solid var(--accent); outline-offset: 2px; }\n[data-vibe-menu] .vm-survey-tile[aria-disabled=\"true\"] { cursor: default; }\n[data-vibe-menu] .vm-survey[data-selected] .vm-survey-cell:not([data-on=\"true\"]) .vm-survey-tile { opacity: 0.55; }\n[data-vibe-menu] .vm-survey[data-picked] .vm-survey-cell:not([data-on=\"true\"]) .vm-survey-tile { opacity: 0.35; }\n[data-vibe-menu] .vm-survey-art { display: block; width: 100%; height: 100%; object-fit: cover; }\n/* The countdown: a small chip in the corner, so the look stays in full view. */\n[data-vibe-menu] .vm-survey-count { position: absolute; top: 6px; right: 6px; display: grid; place-items: center; width: 28px; height: 28px; border-radius: var(--radius-full); border: var(--stroke-rule) solid var(--line-card); background: var(--accent); color: var(--on-accent); font: 700 14px/1 var(--font-display); font-variant-numeric: tabular-nums; pointer-events: none; }\n[data-vibe-menu] .vm-survey-count b { font: inherit; animation: vm-survey-tick 240ms ease-out; }\n@keyframes vm-survey-tick { from { transform: scale(1.35); } to { transform: scale(1); } }\n@media (prefers-reduced-motion: reduce) { [data-vibe-menu] .vm-survey-count b { animation: none; } }\n[data-vibe-menu] .vm-survey-cap { margin-top: var(--space-6); padding: 0 var(--space-2); font: 700 13px/1.25 var(--font-display); color: var(--ink); }\n[data-vibe-menu] .vm-survey-foot { display: flex; align-items: center; gap: var(--space-12); margin-top: var(--space-10); padding: 0 var(--space-2); }\n[data-vibe-menu] .vm-survey-text { flex: 1 1 auto; min-width: 0; }\n[data-vibe-menu] .vm-survey-label { font: 700 14px/1.3 var(--font-display); color: var(--ink); }\n[data-vibe-menu] .vm-survey-pitch { margin-top: var(--space-2); font: 400 13px/1.4 var(--font-display); color: var(--muted); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }\n[data-vibe-menu] .vm-survey-live { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }\n/* The first build's picker: a two-by-two grid of large tiles, each with its name. */\n[data-vibe-menu] .vm-survey[data-presentation=\"filmstrip\"] { margin-top: var(--space-16); }\n[data-vibe-menu] .vm-survey[data-presentation=\"filmstrip\"] .vm-survey-head { margin-top: var(--space-12); margin-bottom: var(--space-12); }\n[data-vibe-menu] .vm-survey[data-presentation=\"filmstrip\"] .vm-survey-title { font-size: 17px; }\n[data-vibe-menu] .vm-survey[data-presentation=\"filmstrip\"] .vm-survey-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-12) var(--space-10); padding-right: 0; }\n@container vm-survey (max-width: 360px) { [data-vibe-menu] .vm-survey:not([data-presentation=\"filmstrip\"]) .vm-survey-aside { display: none; } }\n";
|
|
22
32
|
export declare function surveyMinLoaded(count: number): number;
|
|
23
33
|
export declare function SurveyStrip(props: {
|
|
24
34
|
readonly survey: CodeSurvey;
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
export const SURVEY_COUNTDOWN_MS = 3000;
|
|
2
3
|
export const SURVEY_COPY = Object.freeze({
|
|
3
|
-
choosing: "
|
|
4
|
+
choosing: "Pick a look for your app",
|
|
4
5
|
aside: "Optional · the build goes on",
|
|
6
|
+
counting: "Tap again to cancel",
|
|
5
7
|
picked: "Building in this look",
|
|
6
|
-
pick: "Build this one",
|
|
7
8
|
region: "Steer the look",
|
|
8
9
|
});
|
|
10
|
+
export function surveyCountdownDigit(msLeft) {
|
|
11
|
+
const steps = Math.round(SURVEY_COUNTDOWN_MS / 1000);
|
|
12
|
+
return Math.min(steps, Math.max(1, Math.ceil(msLeft / 1000)));
|
|
13
|
+
}
|
|
14
|
+
export function surveyTileLabel(face, digit) {
|
|
15
|
+
return digit === undefined
|
|
16
|
+
? `${face.label}: ${face.pitch}`
|
|
17
|
+
: `${face.label}: building this look in ${digit}. ${SURVEY_COPY.counting}.`;
|
|
18
|
+
}
|
|
9
19
|
export const SURVEY_STRIP_CSS = `
|
|
10
20
|
/* Its own container: the aside steps out when the strip itself is narrow, on any host. */
|
|
11
21
|
[data-vibe-menu] .vm-survey { margin: 0 0 var(--space-14); container: vm-survey / inline-size; }
|
|
@@ -17,53 +27,59 @@ export const SURVEY_STRIP_CSS = `
|
|
|
17
27
|
[data-vibe-menu] .vm-survey-strip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-8); }
|
|
18
28
|
/* Three readings keep the four-up tile size: the missing tile's column stays empty. */
|
|
19
29
|
[data-vibe-menu] .vm-survey-strip[data-count="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); padding-right: calc((100% - 24px) / 4 + 8px); }
|
|
20
|
-
[data-vibe-menu] .vm-survey-
|
|
30
|
+
[data-vibe-menu] .vm-survey-cell { min-width: 0; }
|
|
31
|
+
[data-vibe-menu] .vm-survey-tile { position: relative; display: block; width: 100%; min-height: 44px; padding: 0; aspect-ratio: 1; border: var(--stroke-rule) solid var(--line-card); border-radius: var(--radius-switch); overflow: hidden; background: var(--card-bg); cursor: pointer; touch-action: manipulation; }
|
|
21
32
|
[data-vibe-menu] .vm-survey-tile[data-on="true"] { outline: var(--stroke-focus) solid var(--accent); outline-offset: 2px; }
|
|
22
33
|
[data-vibe-menu] .vm-survey-tile[aria-disabled="true"] { cursor: default; }
|
|
23
|
-
[data-vibe-menu] .vm-survey[data-
|
|
34
|
+
[data-vibe-menu] .vm-survey[data-selected] .vm-survey-cell:not([data-on="true"]) .vm-survey-tile { opacity: 0.55; }
|
|
35
|
+
[data-vibe-menu] .vm-survey[data-picked] .vm-survey-cell:not([data-on="true"]) .vm-survey-tile { opacity: 0.35; }
|
|
24
36
|
[data-vibe-menu] .vm-survey-art { display: block; width: 100%; height: 100%; object-fit: cover; }
|
|
37
|
+
/* The countdown: a small chip in the corner, so the look stays in full view. */
|
|
38
|
+
[data-vibe-menu] .vm-survey-count { position: absolute; top: 6px; right: 6px; display: grid; place-items: center; width: 28px; height: 28px; border-radius: var(--radius-full); border: var(--stroke-rule) solid var(--line-card); background: var(--accent); color: var(--on-accent); font: 700 14px/1 var(--font-display); font-variant-numeric: tabular-nums; pointer-events: none; }
|
|
39
|
+
[data-vibe-menu] .vm-survey-count b { font: inherit; animation: vm-survey-tick 240ms ease-out; }
|
|
40
|
+
@keyframes vm-survey-tick { from { transform: scale(1.35); } to { transform: scale(1); } }
|
|
41
|
+
@media (prefers-reduced-motion: reduce) { [data-vibe-menu] .vm-survey-count b { animation: none; } }
|
|
42
|
+
[data-vibe-menu] .vm-survey-cap { margin-top: var(--space-6); padding: 0 var(--space-2); font: 700 13px/1.25 var(--font-display); color: var(--ink); }
|
|
25
43
|
[data-vibe-menu] .vm-survey-foot { display: flex; align-items: center; gap: var(--space-12); margin-top: var(--space-10); padding: 0 var(--space-2); }
|
|
26
44
|
[data-vibe-menu] .vm-survey-text { flex: 1 1 auto; min-width: 0; }
|
|
27
45
|
[data-vibe-menu] .vm-survey-label { font: 700 14px/1.3 var(--font-display); color: var(--ink); }
|
|
28
46
|
[data-vibe-menu] .vm-survey-pitch { margin-top: var(--space-2); font: 400 13px/1.4 var(--font-display); color: var(--muted); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
|
29
|
-
[data-vibe-menu] .vm-survey-
|
|
30
|
-
|
|
47
|
+
[data-vibe-menu] .vm-survey-live { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
|
|
48
|
+
/* The first build's picker: a two-by-two grid of large tiles, each with its name. */
|
|
31
49
|
[data-vibe-menu] .vm-survey[data-presentation="filmstrip"] { margin-top: var(--space-16); }
|
|
32
|
-
[data-vibe-menu] .vm-survey-guide { margin: 0 0 var(--space-12); font: 600 17px/1.3 var(--font-display); color: var(--ink); }
|
|
33
|
-
[data-vibe-menu] .vm-survey-preview { aspect-ratio: 1; overflow: hidden; border-radius: var(--radius-switch); background: var(--card-bg); border: var(--stroke-rule) solid var(--line-card); }
|
|
34
|
-
[data-vibe-menu] .vm-survey-preview canvas { width: 100%; height: 100%; object-fit: contain; display: block; }
|
|
35
50
|
[data-vibe-menu] .vm-survey[data-presentation="filmstrip"] .vm-survey-head { margin-top: var(--space-12); margin-bottom: var(--space-12); }
|
|
36
|
-
[data-vibe-menu] .vm-survey[data-presentation="filmstrip"] .vm-survey-
|
|
37
|
-
[data-vibe-menu] .vm-survey[data-presentation="filmstrip"] .vm-survey-
|
|
38
|
-
[data-vibe-menu] .vm-survey[data-presentation="filmstrip"] .vm-survey-pick { width: 100%; height: 48px; font-size: 16px; }
|
|
39
|
-
[data-vibe-menu] .vm-survey-direction { margin: var(--space-10) 0 0; font: 400 13px/1.4 var(--font-display); color: var(--muted); text-align: center; }
|
|
51
|
+
[data-vibe-menu] .vm-survey[data-presentation="filmstrip"] .vm-survey-title { font-size: 17px; }
|
|
52
|
+
[data-vibe-menu] .vm-survey[data-presentation="filmstrip"] .vm-survey-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-12) var(--space-10); padding-right: 0; }
|
|
40
53
|
@container vm-survey (max-width: 360px) { [data-vibe-menu] .vm-survey:not([data-presentation="filmstrip"]) .vm-survey-aside { display: none; } }
|
|
41
54
|
`;
|
|
42
55
|
export function surveyMinLoaded(count) {
|
|
43
56
|
return Math.min(count, Math.max(3, count - 1));
|
|
44
57
|
}
|
|
45
|
-
function
|
|
46
|
-
const
|
|
58
|
+
function useCountdownDigit(endsAtMs) {
|
|
59
|
+
const [digit, setDigit] = React.useState(undefined);
|
|
47
60
|
React.useLayoutEffect(() => {
|
|
48
|
-
|
|
49
|
-
const target = canvas.current;
|
|
50
|
-
if (target === null || image === undefined || image.naturalWidth === 0)
|
|
61
|
+
if (endsAtMs === undefined)
|
|
51
62
|
return;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
63
|
+
let timer;
|
|
64
|
+
const tick = () => {
|
|
65
|
+
const left = endsAtMs - Date.now();
|
|
66
|
+
setDigit({ endsAtMs, digit: surveyCountdownDigit(left) });
|
|
67
|
+
if (left > 0)
|
|
68
|
+
timer = setTimeout(tick, left % 1000 || 1000);
|
|
69
|
+
};
|
|
70
|
+
tick();
|
|
71
|
+
return () => clearTimeout(timer);
|
|
72
|
+
}, [endsAtMs]);
|
|
73
|
+
if (endsAtMs === undefined)
|
|
74
|
+
return undefined;
|
|
75
|
+
return digit?.endsAtMs === endsAtMs ? digit.digit : surveyCountdownDigit(SURVEY_COUNTDOWN_MS);
|
|
58
76
|
}
|
|
59
77
|
function SurveyStripBody(props) {
|
|
60
|
-
const { faces, picked, onPick, onShown } = props.survey;
|
|
78
|
+
const { faces, picked, onPick, onShown, onChoose, onCancel } = props.survey;
|
|
61
79
|
const filmstrip = props.presentation === "filmstrip";
|
|
62
|
-
const images = React.useRef(new Map());
|
|
63
80
|
const [loaded, setLoaded] = React.useState(() => new Set());
|
|
64
81
|
const [errored, setErrored] = React.useState(() => new Set());
|
|
65
82
|
const failed = new Set([...errored].filter((i) => !loaded.has(i)));
|
|
66
|
-
const [focus, setFocus] = React.useState(undefined);
|
|
67
83
|
const kept = faces.map((_, i) => i).filter((i) => !failed.has(i));
|
|
68
84
|
const settled = faces.every((_, i) => loaded.has(i) || failed.has(i));
|
|
69
85
|
const enough = kept.length >= surveyMinLoaded(faces.length) && (picked === undefined || !failed.has(picked));
|
|
@@ -74,39 +90,66 @@ function SurveyStripBody(props) {
|
|
|
74
90
|
if (visible)
|
|
75
91
|
onShownRef.current?.(kept.length);
|
|
76
92
|
}, [visible, kept.length]);
|
|
93
|
+
const hosted = onChoose !== undefined;
|
|
94
|
+
const [own, setOwn] = React.useState(undefined);
|
|
95
|
+
const onPickRef = React.useRef(onPick);
|
|
96
|
+
onPickRef.current = onPick;
|
|
97
|
+
React.useEffect(() => {
|
|
98
|
+
if (hosted || own === undefined)
|
|
99
|
+
return;
|
|
100
|
+
const timer = setTimeout(() => {
|
|
101
|
+
setOwn(undefined);
|
|
102
|
+
onPickRef.current?.(own.index);
|
|
103
|
+
}, Math.max(0, own.endsAtMs - Date.now()));
|
|
104
|
+
return () => clearTimeout(timer);
|
|
105
|
+
}, [hosted, own]);
|
|
106
|
+
const chosen = picked !== undefined;
|
|
107
|
+
const counting = chosen ? undefined : hosted ? props.survey.choosing : own;
|
|
108
|
+
const digit = useCountdownDigit(counting?.endsAtMs);
|
|
77
109
|
if (!enough)
|
|
78
110
|
return null;
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
const face = faces[
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
111
|
+
const ready = onPick !== undefined || hosted;
|
|
112
|
+
const selected = picked ?? counting?.index;
|
|
113
|
+
const face = selected === undefined ? undefined : faces[selected];
|
|
114
|
+
const tap = (i) => {
|
|
115
|
+
if (chosen || !ready)
|
|
116
|
+
return;
|
|
117
|
+
if (counting?.index === i) {
|
|
118
|
+
if (hosted)
|
|
119
|
+
onCancel?.();
|
|
120
|
+
else
|
|
121
|
+
setOwn(undefined);
|
|
122
|
+
}
|
|
123
|
+
else if (hosted)
|
|
124
|
+
onChoose(i);
|
|
125
|
+
else
|
|
126
|
+
setOwn({ index: i, endsAtMs: Date.now() + SURVEY_COUNTDOWN_MS });
|
|
127
|
+
};
|
|
128
|
+
const live = counting !== undefined && face !== undefined
|
|
129
|
+
? surveyTileLabel(face, digit)
|
|
130
|
+
: chosen && face !== undefined
|
|
131
|
+
? `${SURVEY_COPY.picked}: ${face.label}.`
|
|
132
|
+
: "";
|
|
133
|
+
return (React.createElement("section", { className: "vm-survey", "data-presentation": props.presentation, hidden: !visible, "data-testid": visible ? "survey-strip" : "survey-preload", "data-picked": chosen ? "" : undefined, "data-selected": selected === undefined ? undefined : "", "data-counting": counting === undefined ? undefined : "", "aria-label": SURVEY_COPY.region },
|
|
87
134
|
React.createElement("div", { className: "vm-survey-head" },
|
|
88
|
-
React.createElement("span", { className: "vm-survey-title" },
|
|
89
|
-
|
|
90
|
-
kept.indexOf(shown) + 1,
|
|
91
|
-
" / ",
|
|
92
|
-
kept.length)) : chosen ? null : (React.createElement("span", { className: "vm-survey-aside" }, SURVEY_COPY.aside))),
|
|
135
|
+
React.createElement("span", { className: "vm-survey-title" }, chosen ? SURVEY_COPY.picked : SURVEY_COPY.choosing),
|
|
136
|
+
chosen ? null : (React.createElement("span", { className: "vm-survey-aside" }, counting === undefined ? SURVEY_COPY.aside : SURVEY_COPY.counting))),
|
|
93
137
|
React.createElement("div", { className: "vm-survey-strip", role: "radiogroup", "aria-label": SURVEY_COPY.choosing, "data-count": kept.length }, kept.map((i) => {
|
|
94
138
|
const f = faces[i];
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
139
|
+
const on = selected === i;
|
|
140
|
+
const count = counting?.index === i ? digit : undefined;
|
|
141
|
+
return (React.createElement("div", { key: i, className: "vm-survey-cell", "data-on": on },
|
|
142
|
+
React.createElement("button", { type: "button", role: "radio", "aria-checked": on, "aria-label": surveyTileLabel(f, count), "aria-disabled": chosen || !ready, className: "vm-survey-tile", "data-on": on, onClick: () => tap(i) },
|
|
143
|
+
React.createElement("img", { className: "vm-survey-art", src: f.src, alt: "", draggable: false, onLoad: () => setLoaded((prev) => (prev.has(i) ? prev : new Set(prev).add(i))), onError: () => setErrored((prev) => (prev.has(i) ? prev : new Set(prev).add(i))) }),
|
|
144
|
+
count === undefined ? null : (React.createElement("span", { className: "vm-survey-count", "data-testid": "survey-countdown", "aria-hidden": "true" },
|
|
145
|
+
React.createElement("b", { key: count }, count)))),
|
|
146
|
+
filmstrip ? React.createElement("div", { className: "vm-survey-cap" }, f.label) : null));
|
|
103
147
|
})),
|
|
104
|
-
React.createElement("div", { className: "vm-survey-foot" },
|
|
105
|
-
|
|
106
|
-
React.createElement("div", { className: "vm-survey-label" }, face
|
|
107
|
-
React.createElement("div", { className: "vm-survey-pitch" }, face
|
|
108
|
-
|
|
109
|
-
filmstrip ? (React.createElement("p", { className: "vm-survey-direction", "aria-live": "polite" }, chosen ? "Your direction is queued for the agent." : "Your agent will apply this look.")) : null));
|
|
148
|
+
filmstrip || face === undefined ? null : (React.createElement("div", { className: "vm-survey-foot" },
|
|
149
|
+
React.createElement("div", { className: "vm-survey-text" },
|
|
150
|
+
React.createElement("div", { className: "vm-survey-label" }, face.label),
|
|
151
|
+
React.createElement("div", { className: "vm-survey-pitch" }, face.pitch)))),
|
|
152
|
+
React.createElement("span", { className: "vm-survey-live", role: "status", "aria-live": "polite" }, live)));
|
|
110
153
|
}
|
|
111
154
|
export function SurveyStrip(props) {
|
|
112
155
|
const srcs = props.survey.faces.map((f) => f.src);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SurveyStrip.js","sourceRoot":"","sources":["../../../../jsr/components/vibe-menu/parts/SurveyStrip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"SurveyStrip.js","sourceRoot":"","sources":["../../../../jsr/components/vibe-menu/parts/SurveyStrip.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export declare function formatBuildElapsed(elapsedMs: number): string;
|
|
3
|
+
export type FacesInk = "contrast" | "current";
|
|
4
|
+
export interface FacesGlyphProps {
|
|
5
|
+
readonly size?: number;
|
|
6
|
+
readonly ink?: FacesInk;
|
|
7
|
+
readonly style?: React.CSSProperties;
|
|
8
|
+
}
|
|
9
|
+
export declare function FacesGlyph({ size, ink, style }: FacesGlyphProps): React.JSX.Element;
|
|
10
|
+
export interface ThinkingLineProps {
|
|
11
|
+
readonly ink?: FacesInk;
|
|
12
|
+
readonly complete?: boolean;
|
|
13
|
+
readonly verb?: string;
|
|
14
|
+
readonly elapsed?: string;
|
|
15
|
+
readonly wrapping?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function useElapsedText(startedAtMs: number | undefined, stoppedAtMs?: number): string | undefined;
|
|
18
|
+
export declare function LiveThinkingLine({ verb, startedAtMs, stoppedAtMs, ink, }: {
|
|
19
|
+
readonly verb?: string;
|
|
20
|
+
readonly startedAtMs: number | undefined;
|
|
21
|
+
readonly stoppedAtMs?: number;
|
|
22
|
+
readonly ink?: FacesInk;
|
|
23
|
+
}): React.JSX.Element;
|
|
24
|
+
export declare function ThinkingLine({ verb, elapsed, complete, wrapping, ink }: ThinkingLineProps): React.JSX.Element;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { BRIEF_FACES } from "./brief-faces-art.js";
|
|
4
|
+
export function formatBuildElapsed(elapsedMs) {
|
|
5
|
+
const clamped = Number.isFinite(elapsedMs) ? Math.max(0, Math.floor(elapsedMs / 1000)) : 0;
|
|
6
|
+
const seconds = clamped % 60;
|
|
7
|
+
const minutes = Math.floor(clamped / 60) % 60;
|
|
8
|
+
const hours = Math.floor(clamped / 3600);
|
|
9
|
+
const two = (n) => (n < 10 ? `0${n}` : `${n}`);
|
|
10
|
+
if (hours > 0)
|
|
11
|
+
return `${hours}:${two(minutes)}:${two(seconds)}`;
|
|
12
|
+
return `${two(minutes)}:${two(seconds)}`;
|
|
13
|
+
}
|
|
14
|
+
const FACES_CSS = `
|
|
15
|
+
.thinking-line-face {
|
|
16
|
+
grid-area: 1 / 1; width: 100%; height: 100%; opacity: 0;
|
|
17
|
+
animation: thinking-line-faces ${(BRIEF_FACES.length * 0.35).toFixed(2)}s steps(1) infinite;
|
|
18
|
+
}
|
|
19
|
+
.thinking-line-face path { fill: var(--faces-ink, light-dark(#000, #fff)); }
|
|
20
|
+
@keyframes thinking-line-faces {
|
|
21
|
+
0% { opacity: 1; }
|
|
22
|
+
${(100 / BRIEF_FACES.length).toFixed(3)}% { opacity: 0; }
|
|
23
|
+
100% { opacity: 0; }
|
|
24
|
+
}
|
|
25
|
+
@media (prefers-reduced-motion: reduce) {
|
|
26
|
+
.thinking-line-face { animation: none; }
|
|
27
|
+
.thinking-line-face:first-child { opacity: 1; }
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
export function FacesGlyph({ size = 18, ink = "contrast", style }) {
|
|
31
|
+
const inkVar = ink === "current" ? { "--faces-ink": "currentColor" } : null;
|
|
32
|
+
return (React.createElement(React.Fragment, null,
|
|
33
|
+
React.createElement("style", null, FACES_CSS),
|
|
34
|
+
React.createElement("span", { "aria-hidden": true, className: "vm-faces", "data-testid": "thinking-line-glyph", style: { display: "grid", width: size, height: size, flexShrink: 0, ...inkVar, ...style } }, BRIEF_FACES.map((face, index) => (React.createElement("svg", { key: face.viewBox, className: "thinking-line-face", style: { animationDelay: `${(index * 0.35).toFixed(2)}s` }, viewBox: face.viewBox, fill: "none", preserveAspectRatio: "xMidYMid meet" }, face.paths.map((path, pathIndex) => (React.createElement("path", { key: pathIndex, ...path })))))))));
|
|
35
|
+
}
|
|
36
|
+
export function useElapsedText(startedAtMs, stoppedAtMs) {
|
|
37
|
+
const [now, setNow] = useState(undefined);
|
|
38
|
+
const stopped = stoppedAtMs !== undefined;
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (startedAtMs === undefined || stopped)
|
|
41
|
+
return;
|
|
42
|
+
setNow(Date.now());
|
|
43
|
+
const id = setInterval(() => {
|
|
44
|
+
setNow(Date.now());
|
|
45
|
+
}, 1000);
|
|
46
|
+
const onVisible = () => {
|
|
47
|
+
setNow(Date.now());
|
|
48
|
+
};
|
|
49
|
+
document.addEventListener("visibilitychange", onVisible);
|
|
50
|
+
return () => {
|
|
51
|
+
clearInterval(id);
|
|
52
|
+
document.removeEventListener("visibilitychange", onVisible);
|
|
53
|
+
};
|
|
54
|
+
}, [startedAtMs, stopped]);
|
|
55
|
+
if (startedAtMs === undefined)
|
|
56
|
+
return undefined;
|
|
57
|
+
if (stoppedAtMs !== undefined)
|
|
58
|
+
return formatBuildElapsed(Math.max(0, stoppedAtMs - startedAtMs));
|
|
59
|
+
if (now === undefined)
|
|
60
|
+
return undefined;
|
|
61
|
+
return formatBuildElapsed(now - startedAtMs);
|
|
62
|
+
}
|
|
63
|
+
export function LiveThinkingLine({ verb, startedAtMs, stoppedAtMs, ink, }) {
|
|
64
|
+
return (React.createElement(ThinkingLine, { verb: verb, wrapping: stoppedAtMs !== undefined, elapsed: useElapsedText(startedAtMs, stoppedAtMs), ink: ink }));
|
|
65
|
+
}
|
|
66
|
+
export function ThinkingLine({ verb, elapsed, complete = false, wrapping = false, ink }) {
|
|
67
|
+
const word = complete ? "Vibe is ready, enjoy." : (verb ?? "Waiting for a response");
|
|
68
|
+
return (React.createElement(React.Fragment, null,
|
|
69
|
+
React.createElement("span", { className: "flex w-full min-w-0 items-baseline gap-2", "data-testid": "thinking-line" },
|
|
70
|
+
complete === false && wrapping === false && (React.createElement(FacesGlyph, { size: 18, ink: ink, style: { alignSelf: "flex-start", marginTop: "calc(0.75em - 9px)" } })),
|
|
71
|
+
complete === false && elapsed !== undefined && (React.createElement("span", { "aria-hidden": true, className: "min-w-0 shrink-0", "data-testid": "thinking-line-elapsed", style: { fontVariantNumeric: "tabular-nums" } }, elapsed)),
|
|
72
|
+
complete === false && elapsed !== undefined && (React.createElement("span", { "aria-hidden": true, className: "shrink-0" }, "\u00B7")),
|
|
73
|
+
React.createElement("span", { role: "status", "aria-live": "polite", className: "min-w-0 truncate", "data-testid": "thinking-line-verb", title: word },
|
|
74
|
+
word,
|
|
75
|
+
complete === false && wrapping === false ? "…" : ""))));
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=ThinkingLine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThinkingLine.js","sourceRoot":"","sources":["../../../../jsr/components/vibe-menu/parts/ThinkingLine.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface BriefMotifPath {
|
|
2
|
+
readonly d: string;
|
|
3
|
+
readonly fill: string;
|
|
4
|
+
readonly stroke?: string;
|
|
5
|
+
readonly strokeWidth?: number;
|
|
6
|
+
readonly transform?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface BriefMotif {
|
|
9
|
+
readonly viewBox: string;
|
|
10
|
+
readonly paths: readonly BriefMotifPath[];
|
|
11
|
+
}
|
|
12
|
+
export declare const BRIEF_FACES: readonly BriefMotif[];
|