@vibes.diy/base 14.3.105 → 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/HandlePickerMenu.d.ts +1 -2
- package/components/HandlePickerMenu.js +1 -2
- package/components/HandlePickerMenu.js.map +1 -1
- package/components/OnboardingOverlay.d.ts +2 -13
- package/components/OnboardingOverlay.js +51 -33
- package/components/OnboardingOverlay.js.map +1 -1
- package/components/ViewerTagView.d.ts +1 -3
- package/components/ViewerTagView.js +1 -17
- package/components/ViewerTagView.js.map +1 -1
- package/components/index.d.ts +0 -1
- package/components/index.js +0 -1
- package/components/index.js.map +1 -1
- package/components/vibe-menu/VibeMenu.js +23 -7
- package/components/vibe-menu/VibeMenu.js.map +1 -1
- package/components/vibe-menu/cards/AccountCard.d.ts +5 -9
- package/components/vibe-menu/cards/AccountCard.js +69 -61
- 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 +85 -22
- package/components/vibe-menu/cards/CodeCard.js.map +1 -1
- package/components/vibe-menu/cards/CodeModeWorkspace.d.ts +1 -0
- package/components/vibe-menu/cards/CodeModeWorkspace.js +2 -1
- package/components/vibe-menu/cards/CodeModeWorkspace.js.map +1 -1
- package/components/vibe-menu/cards/CodeTabRow.d.ts +29 -3
- package/components/vibe-menu/cards/CodeTabRow.js +79 -12
- 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/fixtures.js +0 -2
- package/components/vibe-menu/fixtures.js.map +1 -1
- package/components/vibe-menu/index.d.ts +4 -0
- package/components/vibe-menu/index.js +4 -0
- package/components/vibe-menu/index.js.map +1 -1
- package/components/vibe-menu/menu-state.d.ts +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/open-resolver.d.ts +0 -2
- package/components/vibe-menu/open-resolver.js +0 -2
- package/components/vibe-menu/open-resolver.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/ScrollTabRow.d.ts +29 -0
- package/components/vibe-menu/parts/ScrollTabRow.js +172 -0
- package/components/vibe-menu/parts/ScrollTabRow.js.map +1 -0
- 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.d.ts +42 -0
- package/components/vibe-menu/sketches/CodeTierAudition.js +141 -0
- package/components/vibe-menu/sketches/CodeTierAudition.js.map +1 -0
- package/components/vibe-menu/slices.d.ts +5 -2
- 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/HandleChooser.d.ts +0 -44
- package/components/HandleChooser.js +0 -112
- package/components/HandleChooser.js.map +0 -1
- package/components/vibe-menu/sketches/AccountTabAudition.d.ts +0 -11
- package/components/vibe-menu/sketches/AccountTabAudition.js +0 -110
- 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":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAsE/B,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC;AAExC,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;IACvC,QAAQ,EAAE,0BAA0B;IACpC,KAAK,EAAE,8BAA8B;IACrC,QAAQ,EAAE,qBAAqB;IAC/B,MAAM,EAAE,uBAAuB;IAC/B,MAAM,EAAE,gBAAgB;CAChB,CAAC,CAAC;AAGZ,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IACrD,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC;AAGD,MAAM,UAAU,eAAe,CAAC,IAAgB,EAAE,KAAyB;IACzE,OAAO,KAAK,KAAK,SAAS;QACxB,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,EAAE;QAChC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,2BAA2B,KAAK,KAAK,WAAW,CAAC,QAAQ,GAAG,CAAC;AAChF,CAAC;AAGD,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmC/B,CAAC;AAIF,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC;AAID,SAAS,iBAAiB,CAAC,QAA4B;IACrD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAoE,SAAS,CAAC,CAAC;IACvH,KAAK,CAAC,eAAe,CAAC,GAAG,EAAE;QACzB,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO;QACnC,IAAI,KAAgD,CAAC;QACrD,MAAM,IAAI,GAAG,GAAS,EAAE;YACtB,MAAM,IAAI,GAAG,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACnC,QAAQ,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC1D,IAAI,IAAI,GAAG,CAAC;gBAAE,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC,CAAC;QAC9D,CAAC,CAAC;QACF,IAAI,EAAE,CAAC;QACP,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IACf,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC7C,OAAO,KAAK,EAAE,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,oBAAoB,CAAC,mBAAmB,CAAC,CAAC;AAChG,CAAC;AAED,SAAS,eAAe,CAAC,KAA2E;IAClG,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5E,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY,KAAK,WAAW,CAAC;IACrD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAsB,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IACjF,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAsB,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IAGnF,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAGnE,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACtE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7G,MAAM,OAAO,GAAG,OAAO,IAAI,MAAM,CAAC;IAElC,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAC7B,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QAGnB,IAAI,OAAO;YAAE,UAAU,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjD,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAG3B,MAAM,MAAM,GAAG,QAAQ,KAAK,SAAS,CAAC;IACtC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,CAA6B,SAAS,CAAC,CAAC;IAC5E,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACvC,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC;IAC3B,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,MAAM,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO;QACxC,MAAM,KAAK,GAAG,UAAU,CACtB,GAAG,EAAE;YACH,MAAM,CAAC,SAAS,CAAC,CAAC;YAClB,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC,EACD,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CACvC,CAAC;QACF,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAClB,MAAM,MAAM,GAAG,MAAM,KAAK,SAAS,CAAC;IACpC,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC;IAC3E,MAAM,KAAK,GAAG,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAEpD,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,KAAK,GAAG,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC;IAC7C,MAAM,QAAQ,GAAG,MAAM,IAAI,QAAQ,EAAE,KAAK,CAAC;IAC3C,MAAM,IAAI,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAClE,MAAM,GAAG,GAAG,CAAC,CAAS,EAAQ,EAAE;QAC9B,IAAI,MAAM,IAAI,CAAC,KAAK;YAAE,OAAO;QAC7B,IAAI,QAAQ,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC;YAC1B,IAAI,MAAM;gBAAE,QAAQ,EAAE,EAAE,CAAC;;gBACpB,MAAM,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC;aAAM,IAAI,MAAM;YAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;;YAC1B,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,mBAAmB,EAAE,CAAC,CAAC;IACxE,CAAC,CAAC;IACF,MAAM,IAAI,GACR,QAAQ,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS;QAC1C,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC;QAC9B,CAAC,CAAC,MAAM,IAAI,IAAI,KAAK,SAAS;YAC5B,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,GAAG;YACzC,CAAC,CAAC,EAAE,CAAC;IACX,OAAO,CACL,iCACE,SAAS,EAAC,WAAW,uBACF,KAAK,CAAC,YAAY,EACrC,MAAM,EAAE,CAAC,OAAO,iBACH,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,gBAAgB,iBAC3C,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,mBACrB,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,mBACvC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,gBAC1C,WAAW,CAAC,MAAM;QAE9B,6BAAK,SAAS,EAAC,gBAAgB;YAC7B,8BAAM,SAAS,EAAC,iBAAiB,IAAE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAQ;YAC5F,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACf,8BAAM,SAAS,EAAC,iBAAiB,IAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAQ,CAC7G,CACG;QACN,6BAAK,SAAS,EAAC,iBAAiB,EAAC,IAAI,EAAC,YAAY,gBAAa,WAAW,CAAC,QAAQ,gBAAc,IAAI,CAAC,MAAM,IACzG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACd,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAe,CAAC;YACjC,MAAM,EAAE,GAAG,QAAQ,KAAK,CAAC,CAAC;YAC1B,MAAM,KAAK,GAAG,QAAQ,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;YACxD,OAAO,CACL,6BAAK,GAAG,EAAE,CAAC,EAAE,SAAS,EAAC,gBAAgB,aAAU,EAAE;gBACjD,gCACE,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,OAAO,kBACE,EAAE,gBACJ,eAAe,CAAC,CAAC,EAAE,KAAK,CAAC,mBACtB,MAAM,IAAI,CAAC,KAAK,EAC/B,SAAS,EAAC,gBAAgB,aACjB,EAAE,EACX,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;oBAErB,6BACE,SAAS,EAAC,eAAe,EACzB,GAAG,EAAE,CAAC,CAAC,GAAG,EACV,GAAG,EAAC,EAAE,EACN,SAAS,EAAE,KAAK,EAChB,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAC9E,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAChF;oBACD,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAC5B,8BAAM,SAAS,EAAC,iBAAiB,iBAAa,kBAAkB,iBAAa,MAAM;wBACjF,2BAAG,GAAG,EAAE,KAAK,IAAG,KAAK,CAAK,CACrB,CACR,CACM;gBACR,SAAS,CAAC,CAAC,CAAC,6BAAK,SAAS,EAAC,eAAe,IAAE,CAAC,CAAC,KAAK,CAAO,CAAC,CAAC,CAAC,IAAI,CAC9D,CACP,CAAC;QACJ,CAAC,CAAC,CACE;QACL,SAAS,IAAI,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACxC,6BAAK,SAAS,EAAC,gBAAgB;YAC7B,6BAAK,SAAS,EAAC,gBAAgB;gBAC7B,6BAAK,SAAS,EAAC,iBAAiB,IAAE,IAAI,CAAC,KAAK,CAAO;gBACnD,6BAAK,SAAS,EAAC,iBAAiB,IAAE,IAAI,CAAC,KAAK,CAAO,CAC/C,CACF,CACP;QACD,8BAAM,SAAS,EAAC,gBAAgB,EAAC,IAAI,EAAC,QAAQ,eAAW,QAAQ,IAC9D,IAAI,CACA,CACC,CACX,CAAC;AACJ,CAAC;AAID,MAAM,UAAU,WAAW,CAAC,KAG3B;IACC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAClD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5E,OAAO,oBAAC,eAAe,IAAC,GAAG,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,GAAI,CAAC;AACpI,CAAC"}
|
|
@@ -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[];
|