@getrheo/flow-runtime 1.0.0
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/dist/agentPrompt/index.d.ts +72 -0
- package/dist/agentPrompt/index.js +739 -0
- package/dist/agentPrompt/index.js.map +1 -0
- package/dist/aiFlowGenerationMerge.d.ts +32 -0
- package/dist/aiFlowGenerationMerge.js +120 -0
- package/dist/aiFlowGenerationMerge.js.map +1 -0
- package/dist/animations.d.ts +110 -0
- package/dist/animations.js +312 -0
- package/dist/animations.js.map +1 -0
- package/dist/assignment.d.ts +7 -0
- package/dist/assignment.js +25 -0
- package/dist/assignment.js.map +1 -0
- package/dist/brandGradient.d.ts +57 -0
- package/dist/brandGradient.js +137 -0
- package/dist/brandGradient.js.map +1 -0
- package/dist/brandGradientManifestIssues.d.ts +11 -0
- package/dist/brandGradientManifestIssues.js +302 -0
- package/dist/brandGradientManifestIssues.js.map +1 -0
- package/dist/buildFlowPreview.d.ts +7 -0
- package/dist/buildFlowPreview.js +81 -0
- package/dist/buildFlowPreview.js.map +1 -0
- package/dist/buttonVariantChrome.d.ts +26 -0
- package/dist/buttonVariantChrome.js +59 -0
- package/dist/buttonVariantChrome.js.map +1 -0
- package/dist/checkboxGlyphStyle.d.ts +31 -0
- package/dist/checkboxGlyphStyle.js +241 -0
- package/dist/checkboxGlyphStyle.js.map +1 -0
- package/dist/choiceOptionSelection.d.ts +11 -0
- package/dist/choiceOptionSelection.js +120 -0
- package/dist/choiceOptionSelection.js.map +1 -0
- package/dist/colorAlpha.d.ts +8 -0
- package/dist/colorAlpha.js +48 -0
- package/dist/colorAlpha.js.map +1 -0
- package/dist/counterLayer.d.ts +42 -0
- package/dist/counterLayer.js +95 -0
- package/dist/counterLayer.js.map +1 -0
- package/dist/decisionEval.d.ts +27 -0
- package/dist/decisionEval.js +197 -0
- package/dist/decisionEval.js.map +1 -0
- package/dist/dropShadow.d.ts +26 -0
- package/dist/dropShadow.js +76 -0
- package/dist/dropShadow.js.map +1 -0
- package/dist/emailPasswordAuthValidation.d.ts +16 -0
- package/dist/emailPasswordAuthValidation.js +25 -0
- package/dist/emailPasswordAuthValidation.js.map +1 -0
- package/dist/flowBuilderRules.d.ts +15 -0
- package/dist/flowBuilderRules.js +368 -0
- package/dist/flowBuilderRules.js.map +1 -0
- package/dist/flowGraph.d.ts +19 -0
- package/dist/flowGraph.js +373 -0
- package/dist/flowGraph.js.map +1 -0
- package/dist/hyperlinkLabel.d.ts +19 -0
- package/dist/hyperlinkLabel.js +232 -0
- package/dist/hyperlinkLabel.js.map +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.js +4200 -0
- package/dist/index.js.map +1 -0
- package/dist/interpolateTemplate.d.ts +44 -0
- package/dist/interpolateTemplate.js +188 -0
- package/dist/interpolateTemplate.js.map +1 -0
- package/dist/layerRotate.d.ts +10 -0
- package/dist/layerRotate.js +9 -0
- package/dist/layerRotate.js.map +1 -0
- package/dist/layerTypography.d.ts +36 -0
- package/dist/layerTypography.js +68 -0
- package/dist/layerTypography.js.map +1 -0
- package/dist/layers.d.ts +69 -0
- package/dist/layers.js +257 -0
- package/dist/layers.js.map +1 -0
- package/dist/layout/index.d.ts +57 -0
- package/dist/layout/index.js +151 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/manifestBillingSlice.d.ts +17 -0
- package/dist/manifestBillingSlice.js +102 -0
- package/dist/manifestBillingSlice.js.map +1 -0
- package/dist/prepareAiGeneratedScreen.d.ts +17 -0
- package/dist/prepareAiGeneratedScreen.js +99 -0
- package/dist/prepareAiGeneratedScreen.js.map +1 -0
- package/dist/publish-exports.json +166 -0
- package/dist/responsive/breakpoints.d.ts +34 -0
- package/dist/responsive/breakpoints.js +52 -0
- package/dist/responsive/breakpoints.js.map +1 -0
- package/dist/responsive/index.d.ts +8 -0
- package/dist/responsive/index.js +307 -0
- package/dist/responsive/index.js.map +1 -0
- package/dist/responsive/layerResolve.d.ts +43 -0
- package/dist/responsive/layerResolve.js +168 -0
- package/dist/responsive/layerResolve.js.map +1 -0
- package/dist/responsive/merge.d.ts +19 -0
- package/dist/responsive/merge.js +74 -0
- package/dist/responsive/merge.js.map +1 -0
- package/dist/responsive/previewSafeAreaInsets.d.ts +14 -0
- package/dist/responsive/previewSafeAreaInsets.js +24 -0
- package/dist/responsive/previewSafeAreaInsets.js.map +1 -0
- package/dist/responsive/screenContainerResolve.d.ts +11 -0
- package/dist/responsive/screenContainerResolve.js +122 -0
- package/dist/responsive/screenContainerResolve.js.map +1 -0
- package/dist/responsive/screenShellInsets.d.ts +11 -0
- package/dist/responsive/screenShellInsets.js +26 -0
- package/dist/responsive/screenShellInsets.js.map +1 -0
- package/dist/restingMotion.d.ts +167 -0
- package/dist/restingMotion.js +484 -0
- package/dist/restingMotion.js.map +1 -0
- package/dist/rheoAgentManifestMerge.d.ts +33 -0
- package/dist/rheoAgentManifestMerge.js +55 -0
- package/dist/rheoAgentManifestMerge.js.map +1 -0
- package/dist/scaleInputStyle.d.ts +35 -0
- package/dist/scaleInputStyle.js +77 -0
- package/dist/scaleInputStyle.js.map +1 -0
- package/dist/scaleValidation.d.ts +9 -0
- package/dist/scaleValidation.js +21 -0
- package/dist/scaleValidation.js.map +1 -0
- package/dist/stateMachine.d.ts +105 -0
- package/dist/stateMachine.js +674 -0
- package/dist/stateMachine.js.map +1 -0
- package/dist/stepResponse-BXgoZ7o-.d.ts +112 -0
- package/dist/textInputValidation.d.ts +14 -0
- package/dist/textInputValidation.js +46 -0
- package/dist/textInputValidation.js.map +1 -0
- package/dist/translationPlaceholders.d.ts +9 -0
- package/dist/translationPlaceholders.js +52 -0
- package/dist/translationPlaceholders.js.map +1 -0
- package/dist/validation.d.ts +31 -0
- package/dist/validation.js +233 -0
- package/dist/validation.js.map +1 -0
- package/package.json +242 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/brandGradient.ts"],"names":[],"mappings":"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","file":"brandGradient.js","sourcesContent":["import type { BrandGradient, Branding } from '@getrheo/contracts/dashboard';\nimport type { ThemedColor } from '@getrheo/contracts/layers';\n\nexport const BRAND_GRADIENT_PREFIX = '$brandGradient:' as const;\n\n/** Serialize a branding gradient preset to a CSS `background` value. */\nexport const brandGradientToCss = (g: BrandGradient): string => {\n const stops = g.stops.map((s) => `${s.color} ${(s.offset * 100).toFixed(0)}%`).join(', ');\n if (g.type === 'linear') {\n const angle = g.angle ?? 180;\n return `linear-gradient(${angle}deg, ${stops})`;\n }\n return `radial-gradient(circle, ${stops})`;\n};\n\nexport const isBrandGradientToken = (s: string): boolean => s.startsWith(BRAND_GRADIENT_PREFIX);\n\n/**\n * Resolve `$brandGradient:<uuid>` using app branding presets.\n * Unknown or missing preset id → `undefined`.\n */\nexport const resolveBrandGradientToken = (\n branding: Branding | undefined,\n token: string,\n): string | undefined => {\n if (!isBrandGradientToken(token)) return undefined;\n const id = token.slice(BRAND_GRADIENT_PREFIX.length);\n const preset = branding?.gradientPresets.find((x) => x.id === id);\n return preset ? brandGradientToCss(preset) : undefined;\n};\n\nconst rawThemedString = (\n palette: 'light' | 'dark',\n value: ThemedColor | undefined,\n): string | undefined => {\n if (value === undefined) return undefined;\n if (typeof value === 'string') return value;\n return palette === 'dark' ? (value.dark ?? value.light) : (value.light ?? value.dark);\n};\n\n/** Resolve a manifest themed color to a branding gradient preset if it references `$brandGradient:`. */\nexport const brandGradientFromThemedColor = (\n branding: Branding | undefined,\n palette: 'light' | 'dark',\n value: ThemedColor | undefined,\n): BrandGradient | undefined => {\n const raw = rawThemedString(palette, value);\n if (raw === undefined || !isBrandGradientToken(raw)) return undefined;\n const id = raw.slice(BRAND_GRADIENT_PREFIX.length);\n return branding?.gradientPresets.find((x) => x.id === id);\n};\n\n/** Native `LinearGradient` props for linear brand presets; `null` for radial (use solid fallback). */\nexport type BrandGradientNativeLinear = {\n colors: string[];\n locations: number[];\n start: { x: number; y: number };\n end: { x: number; y: number };\n};\n\nexport const brandGradientNativeLinear = (g: BrandGradient): BrandGradientNativeLinear | null => {\n if (g.type !== 'linear') return null;\n const angleDeg = g.angle ?? 180;\n const θ = (angleDeg * Math.PI) / 180;\n const ux = Math.sin(θ);\n const uy = -Math.cos(θ);\n return {\n colors: g.stops.map((s) => s.color),\n locations: g.stops.map((s) => s.offset),\n start: { x: 0.5 - ux * 0.5, y: 0.5 - uy * 0.5 },\n end: { x: 0.5 + ux * 0.5, y: 0.5 + uy * 0.5 },\n };\n};\n\nexport const brandGradientSolidFallback = (g: BrandGradient): string => g.stops[0]?.color ?? '#808080';\n\nconst HEX_FOR_GRADIENT = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;\n\n/** Normalize hex for stored CSS gradients (3 → 6 chars; strip alpha channel for 8-char hex). */\nexport const normalizeHexForGradient = (hex: string): string => {\n const t = hex.trim();\n if (!HEX_FOR_GRADIENT.test(t)) return t;\n if (t.length === 4) {\n const [, r, g, b] = t;\n return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();\n }\n if (t.length === 9) return t.slice(0, 7).toLowerCase();\n return t.toLowerCase();\n};\n\n/** One color stop in a dashboard-authored `linear-gradient(...)` (percent along the axis). */\nexport type LinearGradientStopModel = { color: string; offsetPct: number };\n\nconst clampPct = (n: number): number => Math.min(100, Math.max(0, n));\n\n/** Build canonical `linear-gradient(<deg>deg, #hex <pct>%, ...)` with at least two stops. */\nexport const buildLinearGradientCss = (angleDeg: number, stops: LinearGradientStopModel[]): string => {\n const a = Number.isFinite(angleDeg) ? angleDeg : 180;\n const sorted = [...stops]\n .map((s) => ({\n offsetPct: clampPct(Number.isFinite(s.offsetPct) ? s.offsetPct : 0),\n color: normalizeHexForGradient(s.color),\n }))\n .sort((x, y) => x.offsetPct - y.offsetPct);\n if (sorted.length < 2) {\n throw new Error('linear gradient requires at least 2 color stops');\n }\n for (const s of sorted) {\n if (!HEX_FOR_GRADIENT.test(s.color)) {\n throw new Error(`invalid gradient stop color: ${s.color}`);\n }\n }\n const body = sorted.map((s) => `${s.color} ${s.offsetPct.toFixed(0)}%`).join(', ');\n return `linear-gradient(${a}deg, ${body})`;\n};\n\nexport const buildTwoStopLinearGradientCss = (\n angleDeg: number,\n color0: string,\n color1: string,\n): string =>\n buildLinearGradientCss(angleDeg, [\n { color: color0, offsetPct: 0 },\n { color: color1, offsetPct: 100 },\n ]);\n\nexport const isStoredLinearGradientCss = (s: string): boolean =>\n /^\\s*linear-gradient\\s*\\(/i.test(s.trim());\n\n/** Parse dashboard-authored linear gradients with hex stops and explicit `%` positions. */\nexport const parseLinearGradientCss = (s: string): { angleDeg: number; stops: LinearGradientStopModel[] } | null => {\n const t = s.trim();\n const head = t.match(/^\\s*linear-gradient\\s*\\(\\s*([-0-9.]+)\\s*deg\\s*,\\s*(.*)\\)\\s*$/is);\n if (!head) return null;\n const angleStr = head[1];\n const innerRaw = head[2];\n if (angleStr === undefined || innerRaw === undefined) return null;\n const angleDeg = Number(angleStr);\n if (!Number.isFinite(angleDeg)) return null;\n const inner = innerRaw.trim();\n if (!inner) return null;\n const parts = inner.split(/,(?=\\s*#)/);\n const stops: LinearGradientStopModel[] = [];\n for (const part of parts) {\n const p = part.trim();\n const m = p.match(/^(#[0-9a-fA-F]{3,8})\\s+([-0-9.]+)\\s*%$/i);\n if (!m) return null;\n const hex = m[1];\n const offsetStr = m[2];\n if (hex === undefined || offsetStr === undefined) return null;\n const color = normalizeHexForGradient(hex);\n const offsetPct = Number(offsetStr);\n if (!Number.isFinite(offsetPct)) return null;\n if (!HEX_FOR_GRADIENT.test(color)) return null;\n stops.push({ color, offsetPct });\n }\n if (stops.length < 2) return null;\n return { angleDeg, stops };\n};\n\nexport const parseTwoStopLinearGradientCss = (\n s: string,\n): { angleDeg: number; color0: string; color1: string } | null => {\n const p = parseLinearGradientCss(s);\n if (!p || p.stops.length !== 2) return null;\n const sorted = [...p.stops].sort((a, b) => a.offsetPct - b.offsetPct);\n const s0 = sorted[0];\n const s1 = sorted[1];\n if (!s0 || !s1 || s0.offsetPct !== 0 || s1.offsetPct !== 100) return null;\n return { angleDeg: p.angleDeg, color0: s0.color, color1: s1.color };\n};\n\nexport const nativeLinearFromAngleAndStops = (\n angleDeg: number,\n stops: { color: string; offsetPct: number }[],\n): BrandGradientNativeLinear => {\n const sorted = [...stops]\n .map((s) => ({\n color: normalizeHexForGradient(s.color),\n offsetPct: clampPct(Number.isFinite(s.offsetPct) ? s.offsetPct : 0),\n }))\n .sort((a, b) => a.offsetPct - b.offsetPct);\n const θ = (angleDeg * Math.PI) / 180;\n const ux = Math.sin(θ);\n const uy = -Math.cos(θ);\n return {\n colors: sorted.map((s) => s.color),\n locations: sorted.map((s) => s.offsetPct / 100),\n start: { x: 0.5 - ux * 0.5, y: 0.5 - uy * 0.5 },\n end: { x: 0.5 + ux * 0.5, y: 0.5 + uy * 0.5 },\n };\n};\n\nexport const nativeLinearFromAngleAndTwoColors = (\n angleDeg: number,\n color0: string,\n color1: string,\n): BrandGradientNativeLinear =>\n nativeLinearFromAngleAndStops(angleDeg, [\n { color: color0, offsetPct: 0 },\n { color: color1, offsetPct: 100 },\n ]);\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Branding } from '@getrheo/contracts/dashboard';
|
|
2
|
+
import { FlowManifest } from '@getrheo/contracts/manifest';
|
|
3
|
+
import { ManifestValidationIssue } from './validation.js';
|
|
4
|
+
import '@getrheo/contracts';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Non-schema checks: `$brandGradient:` is only valid on background-like fields; optional unknown-id check when `branding` is set.
|
|
8
|
+
*/
|
|
9
|
+
declare const collectBrandGradientManifestIssues: (manifest: FlowManifest, branding: Branding | undefined) => ManifestValidationIssue[];
|
|
10
|
+
|
|
11
|
+
export { collectBrandGradientManifestIssues };
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import '@getrheo/contracts/localized';
|
|
2
|
+
import '@getrheo/contracts/layers';
|
|
3
|
+
|
|
4
|
+
// src/brandGradient.ts
|
|
5
|
+
var BRAND_GRADIENT_PREFIX = "$brandGradient:";
|
|
6
|
+
var brandGradientToCss = (g) => {
|
|
7
|
+
const stops = g.stops.map((s) => `${s.color} ${(s.offset * 100).toFixed(0)}%`).join(", ");
|
|
8
|
+
if (g.type === "linear") {
|
|
9
|
+
const angle = g.angle ?? 180;
|
|
10
|
+
return `linear-gradient(${angle}deg, ${stops})`;
|
|
11
|
+
}
|
|
12
|
+
return `radial-gradient(circle, ${stops})`;
|
|
13
|
+
};
|
|
14
|
+
var isBrandGradientToken = (s) => s.startsWith(BRAND_GRADIENT_PREFIX);
|
|
15
|
+
var resolveBrandGradientToken = (branding, token) => {
|
|
16
|
+
if (!isBrandGradientToken(token)) return void 0;
|
|
17
|
+
const id = token.slice(BRAND_GRADIENT_PREFIX.length);
|
|
18
|
+
const preset = branding?.gradientPresets.find((x) => x.id === id);
|
|
19
|
+
return preset ? brandGradientToCss(preset) : void 0;
|
|
20
|
+
};
|
|
21
|
+
var isStoredLinearGradientCss = (s) => /^\s*linear-gradient\s*\(/i.test(s.trim());
|
|
22
|
+
var walkLayers = (root, fn) => {
|
|
23
|
+
const visit = (l, depth) => {
|
|
24
|
+
fn(l, depth);
|
|
25
|
+
if (l.kind === "stack") l.children.forEach((c) => visit(c, depth + 1));
|
|
26
|
+
else if (l.kind === "carousel") l.slides.forEach((c) => visit(c, depth + 1));
|
|
27
|
+
else if (l.kind === "button") l.children.forEach((c) => visit(c, depth + 1));
|
|
28
|
+
else if (l.kind === "back_button") l.children.forEach((c) => visit(c, depth + 1));
|
|
29
|
+
else if (l.kind === "hyperlink") l.children.forEach((c) => visit(c, depth + 1));
|
|
30
|
+
else if (l.kind === "single_choice" || l.kind === "multiple_choice") {
|
|
31
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
32
|
+
} else if (l.kind === "text_input" || l.kind === "scale_input") {
|
|
33
|
+
l.children?.forEach((c) => visit(c, depth + 1));
|
|
34
|
+
} else if (l.kind === "oauth_login") {
|
|
35
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
36
|
+
} else if (l.kind === "oauth_provider" && l.variant === "custom") {
|
|
37
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
38
|
+
} else if (l.kind === "email_password_auth") {
|
|
39
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
40
|
+
} else if (l.kind === "email_password_field") {
|
|
41
|
+
l.children?.forEach((c) => visit(c, depth + 1));
|
|
42
|
+
} else if (l.kind === "email_password_submit") {
|
|
43
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
visit(root, 0);
|
|
47
|
+
};
|
|
48
|
+
var walkScreen = (screen, fn) => {
|
|
49
|
+
if (screen.regions.header) walkLayers(screen.regions.header, fn);
|
|
50
|
+
walkLayers(screen.regions.body, fn);
|
|
51
|
+
if (screen.regions.footer) walkLayers(screen.regions.footer, fn);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// src/brandGradientManifestIssues.ts
|
|
55
|
+
var BP_KEYS = ["sm", "md", "lg", "xl", "2xl"];
|
|
56
|
+
var themedStrings = (tc) => {
|
|
57
|
+
if (tc === void 0) return [];
|
|
58
|
+
if (typeof tc === "string") return [tc];
|
|
59
|
+
const out = [];
|
|
60
|
+
if (tc.light !== void 0) out.push(tc.light);
|
|
61
|
+
if (tc.dark !== void 0) out.push(tc.dark);
|
|
62
|
+
return out;
|
|
63
|
+
};
|
|
64
|
+
var pushIssue = (issues, stepId, layerId, field, message, code) => {
|
|
65
|
+
issues.push({
|
|
66
|
+
stepId,
|
|
67
|
+
path: ["screens", stepId, layerId, field],
|
|
68
|
+
message,
|
|
69
|
+
code
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
var checkThemed = (issues, stepId, layerId, field, tc, allowGradient, branding) => {
|
|
73
|
+
for (const s of themedStrings(tc)) {
|
|
74
|
+
if (isBrandGradientToken(s)) {
|
|
75
|
+
if (!allowGradient) {
|
|
76
|
+
pushIssue(
|
|
77
|
+
issues,
|
|
78
|
+
stepId,
|
|
79
|
+
layerId,
|
|
80
|
+
field,
|
|
81
|
+
`Brand gradient presets can only be used on background fills (not ${field}).`,
|
|
82
|
+
"brand_gradient.disallowed_field"
|
|
83
|
+
);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (branding !== void 0 && resolveBrandGradientToken(branding, s) === void 0) {
|
|
87
|
+
pushIssue(
|
|
88
|
+
issues,
|
|
89
|
+
stepId,
|
|
90
|
+
layerId,
|
|
91
|
+
field,
|
|
92
|
+
`Brand gradient preset not found: ${s}`,
|
|
93
|
+
"brand_gradient.unknown_preset"
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (isStoredLinearGradientCss(s)) {
|
|
99
|
+
if (!allowGradient) {
|
|
100
|
+
pushIssue(
|
|
101
|
+
issues,
|
|
102
|
+
stepId,
|
|
103
|
+
layerId,
|
|
104
|
+
field,
|
|
105
|
+
`CSS linear gradients can only be used on background fills in v1 (not ${field}).`,
|
|
106
|
+
"brand_gradient.linear_css_disallowed_field"
|
|
107
|
+
);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
var checkCommon = (issues, stepId, layerId, fieldPrefix, s, branding) => {
|
|
114
|
+
if (!s) return;
|
|
115
|
+
checkThemed(issues, stepId, layerId, `${fieldPrefix}background`, s.background, true, branding);
|
|
116
|
+
checkThemed(issues, stepId, layerId, `${fieldPrefix}border.color`, s.border?.color, false, branding);
|
|
117
|
+
checkThemed(issues, stepId, layerId, `${fieldPrefix}shadow.color`, s.shadow?.color, false, branding);
|
|
118
|
+
};
|
|
119
|
+
var checkTextLike = (issues, stepId, layerId, fieldPrefix, s, branding) => {
|
|
120
|
+
if (!s) return;
|
|
121
|
+
checkCommon(issues, stepId, layerId, fieldPrefix, s, branding);
|
|
122
|
+
checkThemed(issues, stepId, layerId, `${fieldPrefix}color`, s.color, false, branding);
|
|
123
|
+
};
|
|
124
|
+
var walkCommonBreakpoints = (issues, stepId, layerId, base, breakpoints, branding) => {
|
|
125
|
+
checkCommon(issues, stepId, layerId, "style.", base, branding);
|
|
126
|
+
if (!breakpoints) return;
|
|
127
|
+
for (const k of BP_KEYS) {
|
|
128
|
+
const patch = breakpoints[k];
|
|
129
|
+
if (patch) checkCommon(issues, stepId, layerId, `styleBreakpoints.${k}.`, patch, branding);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
var walkTextBreakpoints = (issues, stepId, layerId, base, breakpoints, branding) => {
|
|
133
|
+
checkTextLike(issues, stepId, layerId, "style.", base, branding);
|
|
134
|
+
if (!breakpoints) return;
|
|
135
|
+
for (const k of BP_KEYS) {
|
|
136
|
+
const patch = breakpoints[k];
|
|
137
|
+
if (patch) checkTextLike(issues, stepId, layerId, `styleBreakpoints.${k}.`, patch, branding);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
var checkCheckboxGlyph = (issues, stepId, layerId, suffix, g, branding) => {
|
|
141
|
+
if (!g) return;
|
|
142
|
+
const p = suffix ? `${suffix}.` : "";
|
|
143
|
+
checkThemed(issues, stepId, layerId, `${p}background`, g.background, true, branding);
|
|
144
|
+
checkThemed(issues, stepId, layerId, `${p}border.color`, g.border?.color, false, branding);
|
|
145
|
+
checkThemed(issues, stepId, layerId, `${p}shadow.color`, g.shadow?.color, false, branding);
|
|
146
|
+
checkThemed(issues, stepId, layerId, `${p}checkColor`, g.checkColor, false, branding);
|
|
147
|
+
};
|
|
148
|
+
var checkCarouselPageControl = (issues, stepId, layerId, pc, branding) => {
|
|
149
|
+
if (!pc) return;
|
|
150
|
+
const ind = pc.indicators;
|
|
151
|
+
if (ind) {
|
|
152
|
+
checkThemed(issues, stepId, layerId, "pageControl.indicators.defaultColor", ind.defaultColor, false, branding);
|
|
153
|
+
checkThemed(issues, stepId, layerId, "pageControl.indicators.activeColor", ind.activeColor, false, branding);
|
|
154
|
+
checkThemed(issues, stepId, layerId, "pageControl.indicators.border.color", ind.border?.color, false, branding);
|
|
155
|
+
checkThemed(
|
|
156
|
+
issues,
|
|
157
|
+
stepId,
|
|
158
|
+
layerId,
|
|
159
|
+
"pageControl.indicators.activeBorder.color",
|
|
160
|
+
ind.activeBorder?.color,
|
|
161
|
+
false,
|
|
162
|
+
branding
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
checkThemed(issues, stepId, layerId, "pageControl.border.color", pc.border?.color, false, branding);
|
|
166
|
+
checkThemed(issues, stepId, layerId, "pageControl.shadow.color", pc.shadow?.color, false, branding);
|
|
167
|
+
};
|
|
168
|
+
var scanLayer = (issues, screen, layer, branding) => {
|
|
169
|
+
const stepId = screen.id;
|
|
170
|
+
const id = layer.id;
|
|
171
|
+
switch (layer.kind) {
|
|
172
|
+
case "stack":
|
|
173
|
+
walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);
|
|
174
|
+
checkCommon(issues, stepId, id, "selectedStyle.", layer.selectedStyle, branding);
|
|
175
|
+
return;
|
|
176
|
+
case "text":
|
|
177
|
+
walkTextBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);
|
|
178
|
+
return;
|
|
179
|
+
case "image":
|
|
180
|
+
walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);
|
|
181
|
+
return;
|
|
182
|
+
case "lottie":
|
|
183
|
+
case "video":
|
|
184
|
+
walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);
|
|
185
|
+
return;
|
|
186
|
+
case "icon": {
|
|
187
|
+
const base = layer.style;
|
|
188
|
+
checkCommon(issues, stepId, id, "style.", base, branding);
|
|
189
|
+
checkThemed(issues, stepId, id, "style.color", base?.color, false, branding);
|
|
190
|
+
const bp = layer.styleBreakpoints;
|
|
191
|
+
if (bp) {
|
|
192
|
+
for (const k of BP_KEYS) {
|
|
193
|
+
const patch = bp[k];
|
|
194
|
+
if (!patch) continue;
|
|
195
|
+
checkCommon(issues, stepId, id, `styleBreakpoints.${k}.`, patch, branding);
|
|
196
|
+
checkThemed(issues, stepId, id, `styleBreakpoints.${k}.color`, patch.color, false, branding);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
case "button":
|
|
202
|
+
case "back_button": {
|
|
203
|
+
const base = layer.style;
|
|
204
|
+
checkTextLike(issues, stepId, id, "style.", base, branding);
|
|
205
|
+
const bp = layer.styleBreakpoints;
|
|
206
|
+
if (bp) {
|
|
207
|
+
for (const k of BP_KEYS) {
|
|
208
|
+
const patch = bp[k];
|
|
209
|
+
if (patch) checkTextLike(issues, stepId, id, `styleBreakpoints.${k}.`, patch, branding);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
case "hyperlink":
|
|
215
|
+
walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);
|
|
216
|
+
return;
|
|
217
|
+
case "progress":
|
|
218
|
+
checkCommon(issues, stepId, id, "style.", layer.style, branding);
|
|
219
|
+
checkThemed(issues, stepId, id, "trackColor", layer.trackColor, false, branding);
|
|
220
|
+
checkThemed(issues, stepId, id, "fillColor", layer.fillColor, false, branding);
|
|
221
|
+
return;
|
|
222
|
+
case "loader":
|
|
223
|
+
checkCommon(issues, stepId, id, "style.", layer.style, branding);
|
|
224
|
+
checkThemed(issues, stepId, id, "trackColor", layer.trackColor, false, branding);
|
|
225
|
+
checkThemed(issues, stepId, id, "fillColor", layer.fillColor, false, branding);
|
|
226
|
+
return;
|
|
227
|
+
case "counter":
|
|
228
|
+
walkTextBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);
|
|
229
|
+
return;
|
|
230
|
+
case "checkbox":
|
|
231
|
+
checkCheckboxGlyph(issues, stepId, id, "uncheckedStyle", layer.uncheckedStyle, branding);
|
|
232
|
+
checkCheckboxGlyph(issues, stepId, id, "checkedStyle", layer.checkedStyle, branding);
|
|
233
|
+
return;
|
|
234
|
+
case "carousel":
|
|
235
|
+
walkCommonBreakpoints(issues, stepId, id, layer.style, void 0, branding);
|
|
236
|
+
checkCarouselPageControl(issues, stepId, id, layer.pageControl, branding);
|
|
237
|
+
return;
|
|
238
|
+
case "single_choice":
|
|
239
|
+
case "multiple_choice":
|
|
240
|
+
return;
|
|
241
|
+
case "text_input":
|
|
242
|
+
walkCommonBreakpoints(issues, stepId, id, layer.style, void 0, branding);
|
|
243
|
+
return;
|
|
244
|
+
case "scale_input":
|
|
245
|
+
walkCommonBreakpoints(issues, stepId, id, layer.style, void 0, branding);
|
|
246
|
+
checkThemed(issues, stepId, id, "labelStyle.color", layer.labelStyle?.color, false, branding);
|
|
247
|
+
checkThemed(issues, stepId, id, "valueStyle.color", layer.valueStyle?.color, false, branding);
|
|
248
|
+
checkThemed(issues, stepId, id, "trackColor", layer.trackColor, false, branding);
|
|
249
|
+
checkThemed(issues, stepId, id, "fillColor", layer.fillColor, false, branding);
|
|
250
|
+
checkThemed(issues, stepId, id, "thumbColor", layer.thumbColor, false, branding);
|
|
251
|
+
return;
|
|
252
|
+
case "oauth_login":
|
|
253
|
+
walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);
|
|
254
|
+
return;
|
|
255
|
+
case "oauth_provider":
|
|
256
|
+
if (layer.variant === "preset") {
|
|
257
|
+
walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);
|
|
258
|
+
} else {
|
|
259
|
+
const base = layer.style;
|
|
260
|
+
checkTextLike(issues, stepId, id, "style.", base, branding);
|
|
261
|
+
const bp = layer.styleBreakpoints;
|
|
262
|
+
if (bp) {
|
|
263
|
+
for (const k of BP_KEYS) {
|
|
264
|
+
const patch = bp[k];
|
|
265
|
+
if (patch) checkTextLike(issues, stepId, id, `styleBreakpoints.${k}.`, patch, branding);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return;
|
|
270
|
+
case "email_password_auth":
|
|
271
|
+
walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);
|
|
272
|
+
return;
|
|
273
|
+
case "email_password_field":
|
|
274
|
+
walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);
|
|
275
|
+
return;
|
|
276
|
+
case "email_password_submit": {
|
|
277
|
+
const base = layer.style;
|
|
278
|
+
checkTextLike(issues, stepId, id, "style.", base, branding);
|
|
279
|
+
const bp = layer.styleBreakpoints;
|
|
280
|
+
if (bp) {
|
|
281
|
+
for (const k of BP_KEYS) {
|
|
282
|
+
const patch = bp[k];
|
|
283
|
+
if (patch) checkTextLike(issues, stepId, id, `styleBreakpoints.${k}.`, patch, branding);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
default:
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
var collectBrandGradientManifestIssues = (manifest, branding) => {
|
|
293
|
+
const issues = [];
|
|
294
|
+
for (const screen of manifest.screens) {
|
|
295
|
+
walkScreen(screen, (layer) => scanLayer(issues, screen, layer, branding));
|
|
296
|
+
}
|
|
297
|
+
return issues;
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
export { collectBrandGradientManifestIssues };
|
|
301
|
+
//# sourceMappingURL=brandGradientManifestIssues.js.map
|
|
302
|
+
//# sourceMappingURL=brandGradientManifestIssues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/brandGradient.ts","../src/layers.ts","../src/brandGradientManifestIssues.ts"],"names":[],"mappings":"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","file":"brandGradientManifestIssues.js","sourcesContent":["import type { BrandGradient, Branding } from '@getrheo/contracts/dashboard';\nimport type { ThemedColor } from '@getrheo/contracts/layers';\n\nexport const BRAND_GRADIENT_PREFIX = '$brandGradient:' as const;\n\n/** Serialize a branding gradient preset to a CSS `background` value. */\nexport const brandGradientToCss = (g: BrandGradient): string => {\n const stops = g.stops.map((s) => `${s.color} ${(s.offset * 100).toFixed(0)}%`).join(', ');\n if (g.type === 'linear') {\n const angle = g.angle ?? 180;\n return `linear-gradient(${angle}deg, ${stops})`;\n }\n return `radial-gradient(circle, ${stops})`;\n};\n\nexport const isBrandGradientToken = (s: string): boolean => s.startsWith(BRAND_GRADIENT_PREFIX);\n\n/**\n * Resolve `$brandGradient:<uuid>` using app branding presets.\n * Unknown or missing preset id → `undefined`.\n */\nexport const resolveBrandGradientToken = (\n branding: Branding | undefined,\n token: string,\n): string | undefined => {\n if (!isBrandGradientToken(token)) return undefined;\n const id = token.slice(BRAND_GRADIENT_PREFIX.length);\n const preset = branding?.gradientPresets.find((x) => x.id === id);\n return preset ? brandGradientToCss(preset) : undefined;\n};\n\nconst rawThemedString = (\n palette: 'light' | 'dark',\n value: ThemedColor | undefined,\n): string | undefined => {\n if (value === undefined) return undefined;\n if (typeof value === 'string') return value;\n return palette === 'dark' ? (value.dark ?? value.light) : (value.light ?? value.dark);\n};\n\n/** Resolve a manifest themed color to a branding gradient preset if it references `$brandGradient:`. */\nexport const brandGradientFromThemedColor = (\n branding: Branding | undefined,\n palette: 'light' | 'dark',\n value: ThemedColor | undefined,\n): BrandGradient | undefined => {\n const raw = rawThemedString(palette, value);\n if (raw === undefined || !isBrandGradientToken(raw)) return undefined;\n const id = raw.slice(BRAND_GRADIENT_PREFIX.length);\n return branding?.gradientPresets.find((x) => x.id === id);\n};\n\n/** Native `LinearGradient` props for linear brand presets; `null` for radial (use solid fallback). */\nexport type BrandGradientNativeLinear = {\n colors: string[];\n locations: number[];\n start: { x: number; y: number };\n end: { x: number; y: number };\n};\n\nexport const brandGradientNativeLinear = (g: BrandGradient): BrandGradientNativeLinear | null => {\n if (g.type !== 'linear') return null;\n const angleDeg = g.angle ?? 180;\n const θ = (angleDeg * Math.PI) / 180;\n const ux = Math.sin(θ);\n const uy = -Math.cos(θ);\n return {\n colors: g.stops.map((s) => s.color),\n locations: g.stops.map((s) => s.offset),\n start: { x: 0.5 - ux * 0.5, y: 0.5 - uy * 0.5 },\n end: { x: 0.5 + ux * 0.5, y: 0.5 + uy * 0.5 },\n };\n};\n\nexport const brandGradientSolidFallback = (g: BrandGradient): string => g.stops[0]?.color ?? '#808080';\n\nconst HEX_FOR_GRADIENT = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;\n\n/** Normalize hex for stored CSS gradients (3 → 6 chars; strip alpha channel for 8-char hex). */\nexport const normalizeHexForGradient = (hex: string): string => {\n const t = hex.trim();\n if (!HEX_FOR_GRADIENT.test(t)) return t;\n if (t.length === 4) {\n const [, r, g, b] = t;\n return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();\n }\n if (t.length === 9) return t.slice(0, 7).toLowerCase();\n return t.toLowerCase();\n};\n\n/** One color stop in a dashboard-authored `linear-gradient(...)` (percent along the axis). */\nexport type LinearGradientStopModel = { color: string; offsetPct: number };\n\nconst clampPct = (n: number): number => Math.min(100, Math.max(0, n));\n\n/** Build canonical `linear-gradient(<deg>deg, #hex <pct>%, ...)` with at least two stops. */\nexport const buildLinearGradientCss = (angleDeg: number, stops: LinearGradientStopModel[]): string => {\n const a = Number.isFinite(angleDeg) ? angleDeg : 180;\n const sorted = [...stops]\n .map((s) => ({\n offsetPct: clampPct(Number.isFinite(s.offsetPct) ? s.offsetPct : 0),\n color: normalizeHexForGradient(s.color),\n }))\n .sort((x, y) => x.offsetPct - y.offsetPct);\n if (sorted.length < 2) {\n throw new Error('linear gradient requires at least 2 color stops');\n }\n for (const s of sorted) {\n if (!HEX_FOR_GRADIENT.test(s.color)) {\n throw new Error(`invalid gradient stop color: ${s.color}`);\n }\n }\n const body = sorted.map((s) => `${s.color} ${s.offsetPct.toFixed(0)}%`).join(', ');\n return `linear-gradient(${a}deg, ${body})`;\n};\n\nexport const buildTwoStopLinearGradientCss = (\n angleDeg: number,\n color0: string,\n color1: string,\n): string =>\n buildLinearGradientCss(angleDeg, [\n { color: color0, offsetPct: 0 },\n { color: color1, offsetPct: 100 },\n ]);\n\nexport const isStoredLinearGradientCss = (s: string): boolean =>\n /^\\s*linear-gradient\\s*\\(/i.test(s.trim());\n\n/** Parse dashboard-authored linear gradients with hex stops and explicit `%` positions. */\nexport const parseLinearGradientCss = (s: string): { angleDeg: number; stops: LinearGradientStopModel[] } | null => {\n const t = s.trim();\n const head = t.match(/^\\s*linear-gradient\\s*\\(\\s*([-0-9.]+)\\s*deg\\s*,\\s*(.*)\\)\\s*$/is);\n if (!head) return null;\n const angleStr = head[1];\n const innerRaw = head[2];\n if (angleStr === undefined || innerRaw === undefined) return null;\n const angleDeg = Number(angleStr);\n if (!Number.isFinite(angleDeg)) return null;\n const inner = innerRaw.trim();\n if (!inner) return null;\n const parts = inner.split(/,(?=\\s*#)/);\n const stops: LinearGradientStopModel[] = [];\n for (const part of parts) {\n const p = part.trim();\n const m = p.match(/^(#[0-9a-fA-F]{3,8})\\s+([-0-9.]+)\\s*%$/i);\n if (!m) return null;\n const hex = m[1];\n const offsetStr = m[2];\n if (hex === undefined || offsetStr === undefined) return null;\n const color = normalizeHexForGradient(hex);\n const offsetPct = Number(offsetStr);\n if (!Number.isFinite(offsetPct)) return null;\n if (!HEX_FOR_GRADIENT.test(color)) return null;\n stops.push({ color, offsetPct });\n }\n if (stops.length < 2) return null;\n return { angleDeg, stops };\n};\n\nexport const parseTwoStopLinearGradientCss = (\n s: string,\n): { angleDeg: number; color0: string; color1: string } | null => {\n const p = parseLinearGradientCss(s);\n if (!p || p.stops.length !== 2) return null;\n const sorted = [...p.stops].sort((a, b) => a.offsetPct - b.offsetPct);\n const s0 = sorted[0];\n const s1 = sorted[1];\n if (!s0 || !s1 || s0.offsetPct !== 0 || s1.offsetPct !== 100) return null;\n return { angleDeg: p.angleDeg, color0: s0.color, color1: s1.color };\n};\n\nexport const nativeLinearFromAngleAndStops = (\n angleDeg: number,\n stops: { color: string; offsetPct: number }[],\n): BrandGradientNativeLinear => {\n const sorted = [...stops]\n .map((s) => ({\n color: normalizeHexForGradient(s.color),\n offsetPct: clampPct(Number.isFinite(s.offsetPct) ? s.offsetPct : 0),\n }))\n .sort((a, b) => a.offsetPct - b.offsetPct);\n const θ = (angleDeg * Math.PI) / 180;\n const ux = Math.sin(θ);\n const uy = -Math.cos(θ);\n return {\n colors: sorted.map((s) => s.color),\n locations: sorted.map((s) => s.offsetPct / 100),\n start: { x: 0.5 - ux * 0.5, y: 0.5 - uy * 0.5 },\n end: { x: 0.5 + ux * 0.5, y: 0.5 + uy * 0.5 },\n };\n};\n\nexport const nativeLinearFromAngleAndTwoColors = (\n angleDeg: number,\n color0: string,\n color1: string,\n): BrandGradientNativeLinear =>\n nativeLinearFromAngleAndStops(angleDeg, [\n { color: color0, offsetPct: 0 },\n { color: color1, offsetPct: 100 },\n ]);\n","import type { Branding } from '@getrheo/contracts/dashboard';\nimport type { FlowManifest, Theme } from '@getrheo/contracts/manifest';\nimport type { Screen } from '@getrheo/contracts/screens';\nimport {\n brandGradientFromThemedColor,\n brandGradientNativeLinear,\n brandGradientSolidFallback,\n isStoredLinearGradientCss,\n nativeLinearFromAngleAndStops,\n parseLinearGradientCss,\n resolveBrandGradientToken,\n type BrandGradientNativeLinear,\n} from './brandGradient';\nimport type {\n InputLayer,\n Layer,\n MultipleChoiceLayer,\n ScaleInputLayer,\n SingleChoiceLayer,\n StackLayer,\n TextInputLayer,\n ThemedColor,\n} from '@getrheo/contracts/layers';\nimport type { LocalizedText } from '@getrheo/contracts/localized';\nimport { resolveLocalizedText } from '@getrheo/contracts/localized';\nimport { isInputLayer } from '@getrheo/contracts/layers';\n\n/** Walk a layer tree depth-first. */\nexport const walkLayers = (root: Layer, fn: (l: Layer, depth: number) => void): void => {\n const visit = (l: Layer, depth: number): void => {\n fn(l, depth);\n if (l.kind === 'stack') l.children.forEach((c) => visit(c, depth + 1));\n else if (l.kind === 'carousel') l.slides.forEach((c) => visit(c, depth + 1));\n else if (l.kind === 'button') l.children.forEach((c) => visit(c, depth + 1));\n else if (l.kind === 'back_button') l.children.forEach((c) => visit(c, depth + 1));\n else if (l.kind === 'hyperlink') l.children.forEach((c) => visit(c, depth + 1));\n else if (l.kind === 'single_choice' || l.kind === 'multiple_choice') {\n l.children.forEach((c) => visit(c, depth + 1));\n } else if (l.kind === 'text_input' || l.kind === 'scale_input') {\n l.children?.forEach((c) => visit(c, depth + 1));\n } else if (l.kind === 'oauth_login') {\n l.children.forEach((c) => visit(c, depth + 1));\n } else if (l.kind === 'oauth_provider' && l.variant === 'custom') {\n l.children.forEach((c) => visit(c, depth + 1));\n } else if (l.kind === 'email_password_auth') {\n l.children.forEach((c) => visit(c, depth + 1));\n } else if (l.kind === 'email_password_field') {\n l.children?.forEach((c) => visit(c, depth + 1));\n } else if (l.kind === 'email_password_submit') {\n l.children.forEach((c) => visit(c, depth + 1));\n }\n };\n visit(root, 0);\n};\n\n/** Walk every layer in a screen's regions (header → body → footer). */\nexport const walkScreen = (screen: Screen, fn: (l: Layer) => void): void => {\n if (screen.regions.header) walkLayers(screen.regions.header, fn);\n walkLayers(screen.regions.body, fn);\n if (screen.regions.footer) walkLayers(screen.regions.footer, fn);\n};\n\n/** Find the screen's lone input layer (if any). Schema enforces ≤1. */\nexport const findInputLayer = (screen: Screen): InputLayer | null => {\n let found: InputLayer | null = null;\n walkScreen(screen, (l) => {\n if (!found && isInputLayer(l)) found = l;\n });\n return found;\n};\n\n/** Input kinds that use a screen draft and require an explicit Continue to submit. */\nexport const findManualSubmitInputLayer = (\n screen: Screen,\n): MultipleChoiceLayer | TextInputLayer | ScaleInputLayer | null => {\n const input = findInputLayer(screen);\n if (!input) return null;\n if (input.kind === 'multiple_choice' || input.kind === 'text_input' || input.kind === 'scale_input') {\n return input;\n }\n return null;\n};\n\n/**\n * Whether the screen contains any Button layer that submits the screen\n * (i.e. `action.kind === 'continue'`). Used by input layers to decide\n * between auto-submit-on-tap (legacy behaviour for choice-only screens)\n * and writing into the screen-level draft for a Button to submit.\n */\nexport const screenHasContinueButton = (screen: Screen): boolean => {\n let found = false;\n walkScreen(screen, (l) => {\n if (l.kind === 'button' && l.action.kind === 'continue') found = true;\n });\n return found;\n};\n\n/**\n * Resolve a choice layer's option stack by stable optionId via its\n * binding. Returns null when the binding is missing or the bound child\n * was removed (manifest validation rejects that, but runtime stays safe).\n */\nexport const findOptionStackForChoice = (\n layer: SingleChoiceLayer | MultipleChoiceLayer,\n optionId: string,\n): StackLayer | null => {\n const binding = layer.optionBindings.find((b) => b.optionId === optionId);\n if (!binding) return null;\n const stack = layer.children.find((c) => c.id === binding.rootLayerId);\n return stack ?? null;\n};\n\n/**\n * Best-effort textual label for a choice option, used by interpolation\n * (e.g. `{{ goal }}` rendering the chosen option's label) and by editor\n * surfaces that show option rows. Walks the option's child subtree\n * depth-first and returns the first `text` layer's content; falls back\n * to the option's stable id when no text is present.\n */\nexport const choiceOptionLabel = (\n layer: SingleChoiceLayer | MultipleChoiceLayer,\n optionId: string,\n locale: string,\n): string => {\n const stack = findOptionStackForChoice(layer, optionId);\n if (!stack) return '';\n let foundText: LocalizedText | null = null;\n walkLayers(stack, (l) => {\n if (foundText) return;\n if (l.kind === 'text') foundText = l.text;\n });\n if (foundText) return resolveLocalizedText(foundText, locale);\n return optionId;\n};\n\n/** Find a layer in a screen by id, including nested children/slides. */\nexport const findLayerById = (screen: Screen, id: string): Layer | null => {\n let found: Layer | null = null;\n walkScreen(screen, (l) => {\n if (!found && l.id === id) found = l;\n });\n return found;\n};\n\n/** Collect all input fieldKeys across a manifest. */\nexport const collectFieldKeys = (manifest: FlowManifest): { fieldKey: string; screenId: string }[] => {\n const out: { fieldKey: string; screenId: string }[] = [];\n for (const screen of manifest.screens) {\n walkScreen(screen as unknown as Screen, (l) => {\n if (isInputLayer(l)) out.push({ fieldKey: l.fieldKey, screenId: screen.id });\n if (l.kind === 'checkbox') out.push({ fieldKey: l.fieldKey, screenId: screen.id });\n if (l.kind === 'email_password_auth') {\n out.push({ fieldKey: l.fieldKey, screenId: screen.id });\n }\n });\n }\n return out;\n};\n\n/**\n * Pick a snake_case field key starting from `base` that is not in `used`\n * (e.g. `text` → `text_2` → `text_3` when `text` is taken).\n */\nexport const nextUniqueFieldKey = (base: string, used: Iterable<string>): string => {\n const set = used instanceof Set ? used : new Set(used);\n if (!set.has(base)) return base;\n let n = 2;\n while (set.has(`${base}_${n}`)) n += 1;\n return `${base}_${n}`;\n};\n\n/**\n * Resolve a token reference like `$primary` to a literal value from `theme`.\n * Pass-through for non-token strings; returns undefined for `undefined`.\n */\nexport const resolveTokens = <T extends string | undefined>(\n theme: Theme | undefined,\n value: T,\n): T | string => {\n if (value === undefined) return value;\n if (typeof value !== 'string' || !value.startsWith('$')) return value;\n const key = value.slice(1) as keyof Theme;\n const literal = theme?.[key];\n if (typeof literal === 'string') return literal;\n return value;\n};\n\n/**\n * Resolve a layer color for the current appearance (`light` | `dark`).\n * Plain string uses `resolveTokens` for both modes (legacy). Object form\n * picks `light` / `dark` with fallback to the other key when one is omitted.\n */\nexport const resolveThemedColor = (\n theme: Theme | undefined,\n palette: 'light' | 'dark',\n value: ThemedColor | undefined,\n): string | undefined => {\n if (value === undefined) return undefined;\n if (typeof value === 'string') return resolveTokens(theme, value) as string;\n const raw = palette === 'dark' ? (value.dark ?? value.light) : (value.light ?? value.dark);\n if (raw === undefined) return undefined;\n return resolveTokens(theme, raw) as string;\n};\n\n/**\n * Resolve a themed value used for CSS `background` (or RN background fill).\n * Supports `$brandGradient:<uuid>` when branding presets are provided; other values match {@link resolveThemedColor}.\n */\nexport const resolveThemedBackground = (\n theme: Theme | undefined,\n branding: Branding | undefined,\n palette: 'light' | 'dark',\n value: ThemedColor | undefined,\n): string | undefined => {\n if (value === undefined) return undefined;\n if (typeof value === 'string') {\n if (value.startsWith('$brandGradient:')) {\n return resolveBrandGradientToken(branding, value);\n }\n return resolveTokens(theme, value) as string;\n }\n const raw = palette === 'dark' ? (value.dark ?? value.light) : (value.light ?? value.dark);\n if (raw === undefined) return undefined;\n if (raw.startsWith('$brandGradient:')) {\n return resolveBrandGradientToken(branding, raw);\n }\n return resolveTokens(theme, raw) as string;\n};\n\nexport const nativeBrandBackgroundFromThemedColor = (\n theme: Theme | undefined,\n branding: Branding | undefined,\n palette: 'light' | 'dark',\n value: ThemedColor | undefined,\n): { solid?: string; linear?: BrandGradientNativeLinear } => {\n const preset = brandGradientFromThemedColor(branding, palette, value);\n if (preset) {\n const lin = brandGradientNativeLinear(preset);\n if (lin) return { linear: lin };\n return { solid: brandGradientSolidFallback(preset) };\n }\n const bg = resolveThemedBackground(theme, branding, palette, value) as string | undefined;\n if (!bg) return {};\n const parsed = parseLinearGradientCss(bg);\n if (parsed) {\n return {\n linear: nativeLinearFromAngleAndStops(\n parsed.angleDeg,\n parsed.stops.map((s) => ({ color: s.color, offsetPct: s.offsetPct })),\n ),\n };\n }\n if (isStoredLinearGradientCss(bg)) {\n const first = bg.match(/#[0-9a-fA-F]{3,8}/);\n return { solid: first ? first[0] : '#808080' };\n }\n return { solid: bg };\n};\n","import type { Branding } from '@getrheo/contracts/dashboard';\nimport type { FlowManifest } from '@getrheo/contracts/manifest';\nimport type {\n CarouselPageControl,\n CheckboxGlyphStyle,\n CommonStyle,\n Layer,\n TextStyle,\n ThemedColor,\n} from '@getrheo/contracts/layers';\nimport type { Screen } from '@getrheo/contracts/screens';\nimport type { ManifestValidationIssue } from './validation';\nimport { isBrandGradientToken, isStoredLinearGradientCss, resolveBrandGradientToken } from './brandGradient';\nimport { walkScreen } from './layers';\n\nconst BP_KEYS = ['sm', 'md', 'lg', 'xl', '2xl'] as const;\n\nconst themedStrings = (tc: ThemedColor | undefined): string[] => {\n if (tc === undefined) return [];\n if (typeof tc === 'string') return [tc];\n const out: string[] = [];\n if (tc.light !== undefined) out.push(tc.light);\n if (tc.dark !== undefined) out.push(tc.dark);\n return out;\n};\n\nconst pushIssue = (\n issues: ManifestValidationIssue[],\n stepId: string,\n layerId: string,\n field: string,\n message: string,\n code: string,\n): void => {\n issues.push({\n stepId,\n path: ['screens', stepId, layerId, field],\n message,\n code,\n });\n};\n\nconst checkThemed = (\n issues: ManifestValidationIssue[],\n stepId: string,\n layerId: string,\n field: string,\n tc: ThemedColor | undefined,\n allowGradient: boolean,\n branding: Branding | undefined,\n): void => {\n for (const s of themedStrings(tc)) {\n if (isBrandGradientToken(s)) {\n if (!allowGradient) {\n pushIssue(\n issues,\n stepId,\n layerId,\n field,\n `Brand gradient presets can only be used on background fills (not ${field}).`,\n 'brand_gradient.disallowed_field',\n );\n return;\n }\n if (branding !== undefined && resolveBrandGradientToken(branding, s) === undefined) {\n pushIssue(\n issues,\n stepId,\n layerId,\n field,\n `Brand gradient preset not found: ${s}`,\n 'brand_gradient.unknown_preset',\n );\n }\n continue;\n }\n if (isStoredLinearGradientCss(s)) {\n if (!allowGradient) {\n pushIssue(\n issues,\n stepId,\n layerId,\n field,\n `CSS linear gradients can only be used on background fills in v1 (not ${field}).`,\n 'brand_gradient.linear_css_disallowed_field',\n );\n return;\n }\n }\n }\n};\n\nconst checkCommon = (\n issues: ManifestValidationIssue[],\n stepId: string,\n layerId: string,\n fieldPrefix: string,\n s: CommonStyle | undefined,\n branding: Branding | undefined,\n): void => {\n if (!s) return;\n checkThemed(issues, stepId, layerId, `${fieldPrefix}background`, s.background, true, branding);\n checkThemed(issues, stepId, layerId, `${fieldPrefix}border.color`, s.border?.color, false, branding);\n checkThemed(issues, stepId, layerId, `${fieldPrefix}shadow.color`, s.shadow?.color, false, branding);\n};\n\nconst checkTextLike = (\n issues: ManifestValidationIssue[],\n stepId: string,\n layerId: string,\n fieldPrefix: string,\n s: TextStyle | undefined,\n branding: Branding | undefined,\n): void => {\n if (!s) return;\n checkCommon(issues, stepId, layerId, fieldPrefix, s, branding);\n checkThemed(issues, stepId, layerId, `${fieldPrefix}color`, s.color, false, branding);\n};\n\nconst walkCommonBreakpoints = (\n issues: ManifestValidationIssue[],\n stepId: string,\n layerId: string,\n base: CommonStyle | undefined,\n breakpoints:\n | Partial<Record<(typeof BP_KEYS)[number], Partial<CommonStyle> | undefined>>\n | undefined,\n branding: Branding | undefined,\n): void => {\n checkCommon(issues, stepId, layerId, 'style.', base, branding);\n if (!breakpoints) return;\n for (const k of BP_KEYS) {\n const patch = breakpoints[k];\n if (patch) checkCommon(issues, stepId, layerId, `styleBreakpoints.${k}.`, patch, branding);\n }\n};\n\nconst walkTextBreakpoints = (\n issues: ManifestValidationIssue[],\n stepId: string,\n layerId: string,\n base: TextStyle | undefined,\n breakpoints:\n | Partial<Record<(typeof BP_KEYS)[number], Partial<TextStyle> | undefined>>\n | undefined,\n branding: Branding | undefined,\n): void => {\n checkTextLike(issues, stepId, layerId, 'style.', base, branding);\n if (!breakpoints) return;\n for (const k of BP_KEYS) {\n const patch = breakpoints[k];\n if (patch) checkTextLike(issues, stepId, layerId, `styleBreakpoints.${k}.`, patch, branding);\n }\n};\n\nconst checkCheckboxGlyph = (\n issues: ManifestValidationIssue[],\n stepId: string,\n layerId: string,\n suffix: string,\n g: CheckboxGlyphStyle | undefined,\n branding: Branding | undefined,\n): void => {\n if (!g) return;\n const p = suffix ? `${suffix}.` : '';\n checkThemed(issues, stepId, layerId, `${p}background`, g.background, true, branding);\n checkThemed(issues, stepId, layerId, `${p}border.color`, g.border?.color, false, branding);\n checkThemed(issues, stepId, layerId, `${p}shadow.color`, g.shadow?.color, false, branding);\n checkThemed(issues, stepId, layerId, `${p}checkColor`, g.checkColor, false, branding);\n};\n\nconst checkCarouselPageControl = (\n issues: ManifestValidationIssue[],\n stepId: string,\n layerId: string,\n pc: CarouselPageControl | undefined,\n branding: Branding | undefined,\n): void => {\n if (!pc) return;\n const ind = pc.indicators;\n if (ind) {\n checkThemed(issues, stepId, layerId, 'pageControl.indicators.defaultColor', ind.defaultColor, false, branding);\n checkThemed(issues, stepId, layerId, 'pageControl.indicators.activeColor', ind.activeColor, false, branding);\n checkThemed(issues, stepId, layerId, 'pageControl.indicators.border.color', ind.border?.color, false, branding);\n checkThemed(\n issues,\n stepId,\n layerId,\n 'pageControl.indicators.activeBorder.color',\n ind.activeBorder?.color,\n false,\n branding,\n );\n }\n checkThemed(issues, stepId, layerId, 'pageControl.border.color', pc.border?.color, false, branding);\n checkThemed(issues, stepId, layerId, 'pageControl.shadow.color', pc.shadow?.color, false, branding);\n};\n\nconst scanLayer = (issues: ManifestValidationIssue[], screen: Screen, layer: Layer, branding: Branding | undefined) => {\n const stepId = screen.id;\n const id = layer.id;\n\n switch (layer.kind) {\n case 'stack':\n walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);\n checkCommon(issues, stepId, id, 'selectedStyle.', layer.selectedStyle, branding);\n return;\n case 'text':\n walkTextBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);\n return;\n case 'image':\n walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);\n return;\n case 'lottie':\n case 'video':\n walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);\n return;\n case 'icon': {\n const base = layer.style;\n checkCommon(issues, stepId, id, 'style.', base, branding);\n checkThemed(issues, stepId, id, 'style.color', base?.color, false, branding);\n const bp = layer.styleBreakpoints;\n if (bp) {\n for (const k of BP_KEYS) {\n const patch = bp[k];\n if (!patch) continue;\n checkCommon(issues, stepId, id, `styleBreakpoints.${k}.`, patch, branding);\n checkThemed(issues, stepId, id, `styleBreakpoints.${k}.color`, patch.color, false, branding);\n }\n }\n return;\n }\n case 'button':\n case 'back_button': {\n const base = layer.style;\n checkTextLike(issues, stepId, id, 'style.', base, branding);\n const bp = layer.styleBreakpoints;\n if (bp) {\n for (const k of BP_KEYS) {\n const patch = bp[k];\n if (patch) checkTextLike(issues, stepId, id, `styleBreakpoints.${k}.`, patch, branding);\n }\n }\n return;\n }\n case 'hyperlink':\n walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);\n return;\n case 'progress':\n checkCommon(issues, stepId, id, 'style.', layer.style, branding);\n checkThemed(issues, stepId, id, 'trackColor', layer.trackColor, false, branding);\n checkThemed(issues, stepId, id, 'fillColor', layer.fillColor, false, branding);\n return;\n case 'loader':\n checkCommon(issues, stepId, id, 'style.', layer.style, branding);\n checkThemed(issues, stepId, id, 'trackColor', layer.trackColor, false, branding);\n checkThemed(issues, stepId, id, 'fillColor', layer.fillColor, false, branding);\n return;\n case 'counter':\n walkTextBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);\n return;\n case 'checkbox':\n checkCheckboxGlyph(issues, stepId, id, 'uncheckedStyle', layer.uncheckedStyle, branding);\n checkCheckboxGlyph(issues, stepId, id, 'checkedStyle', layer.checkedStyle, branding);\n return;\n case 'carousel':\n walkCommonBreakpoints(issues, stepId, id, layer.style, undefined, branding);\n checkCarouselPageControl(issues, stepId, id, layer.pageControl, branding);\n return;\n case 'single_choice':\n case 'multiple_choice':\n return;\n case 'text_input':\n walkCommonBreakpoints(issues, stepId, id, layer.style, undefined, branding);\n return;\n case 'scale_input':\n walkCommonBreakpoints(issues, stepId, id, layer.style, undefined, branding);\n checkThemed(issues, stepId, id, 'labelStyle.color', layer.labelStyle?.color, false, branding);\n checkThemed(issues, stepId, id, 'valueStyle.color', layer.valueStyle?.color, false, branding);\n checkThemed(issues, stepId, id, 'trackColor', layer.trackColor, false, branding);\n checkThemed(issues, stepId, id, 'fillColor', layer.fillColor, false, branding);\n checkThemed(issues, stepId, id, 'thumbColor', layer.thumbColor, false, branding);\n return;\n case 'oauth_login':\n walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);\n return;\n case 'oauth_provider':\n if (layer.variant === 'preset') {\n walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);\n } else {\n const base = layer.style;\n checkTextLike(issues, stepId, id, 'style.', base, branding);\n const bp = layer.styleBreakpoints;\n if (bp) {\n for (const k of BP_KEYS) {\n const patch = bp[k];\n if (patch) checkTextLike(issues, stepId, id, `styleBreakpoints.${k}.`, patch, branding);\n }\n }\n }\n return;\n case 'email_password_auth':\n walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);\n return;\n case 'email_password_field':\n walkCommonBreakpoints(issues, stepId, id, layer.style, layer.styleBreakpoints, branding);\n return;\n case 'email_password_submit': {\n const base = layer.style;\n checkTextLike(issues, stepId, id, 'style.', base, branding);\n const bp = layer.styleBreakpoints;\n if (bp) {\n for (const k of BP_KEYS) {\n const patch = bp[k];\n if (patch) checkTextLike(issues, stepId, id, `styleBreakpoints.${k}.`, patch, branding);\n }\n }\n return;\n }\n default:\n return;\n }\n};\n\n/**\n * Non-schema checks: `$brandGradient:` is only valid on background-like fields; optional unknown-id check when `branding` is set.\n */\nexport const collectBrandGradientManifestIssues = (\n manifest: FlowManifest,\n branding: Branding | undefined,\n): ManifestValidationIssue[] => {\n const issues: ManifestValidationIssue[] = [];\n for (const screen of manifest.screens) {\n walkScreen(screen as Screen, (layer) => scanLayer(issues, screen as Screen, layer, branding));\n }\n return issues;\n};\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { FlowPreview } from '@getrheo/contracts/dashboard';
|
|
2
|
+
import { FlowManifest } from '@getrheo/contracts/manifest';
|
|
3
|
+
|
|
4
|
+
/** Canvas thumbnail nodes/edges for dashboard flow list and template previews. */
|
|
5
|
+
declare const buildFlowPreview: (manifest: FlowManifest) => FlowPreview;
|
|
6
|
+
|
|
7
|
+
export { buildFlowPreview };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import '@getrheo/contracts/localized';
|
|
2
|
+
import { isInputLayer } from '@getrheo/contracts/layers';
|
|
3
|
+
|
|
4
|
+
// src/layers.ts
|
|
5
|
+
var walkLayers = (root, fn) => {
|
|
6
|
+
const visit = (l, depth) => {
|
|
7
|
+
fn(l, depth);
|
|
8
|
+
if (l.kind === "stack") l.children.forEach((c) => visit(c, depth + 1));
|
|
9
|
+
else if (l.kind === "carousel") l.slides.forEach((c) => visit(c, depth + 1));
|
|
10
|
+
else if (l.kind === "button") l.children.forEach((c) => visit(c, depth + 1));
|
|
11
|
+
else if (l.kind === "back_button") l.children.forEach((c) => visit(c, depth + 1));
|
|
12
|
+
else if (l.kind === "hyperlink") l.children.forEach((c) => visit(c, depth + 1));
|
|
13
|
+
else if (l.kind === "single_choice" || l.kind === "multiple_choice") {
|
|
14
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
15
|
+
} else if (l.kind === "text_input" || l.kind === "scale_input") {
|
|
16
|
+
l.children?.forEach((c) => visit(c, depth + 1));
|
|
17
|
+
} else if (l.kind === "oauth_login") {
|
|
18
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
19
|
+
} else if (l.kind === "oauth_provider" && l.variant === "custom") {
|
|
20
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
21
|
+
} else if (l.kind === "email_password_auth") {
|
|
22
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
23
|
+
} else if (l.kind === "email_password_field") {
|
|
24
|
+
l.children?.forEach((c) => visit(c, depth + 1));
|
|
25
|
+
} else if (l.kind === "email_password_submit") {
|
|
26
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
visit(root, 0);
|
|
30
|
+
};
|
|
31
|
+
var walkScreen = (screen, fn) => {
|
|
32
|
+
if (screen.regions.header) walkLayers(screen.regions.header, fn);
|
|
33
|
+
walkLayers(screen.regions.body, fn);
|
|
34
|
+
if (screen.regions.footer) walkLayers(screen.regions.footer, fn);
|
|
35
|
+
};
|
|
36
|
+
var findInputLayer = (screen) => {
|
|
37
|
+
let found = null;
|
|
38
|
+
walkScreen(screen, (l) => {
|
|
39
|
+
if (!found && isInputLayer(l)) found = l;
|
|
40
|
+
});
|
|
41
|
+
return found;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// src/buildFlowPreview.ts
|
|
45
|
+
var buildFlowPreview = (manifest) => {
|
|
46
|
+
const screens = Array.isArray(manifest?.screens) ? manifest.screens : [];
|
|
47
|
+
const stored = manifest?.builderMeta?.layout?.nodes ?? [];
|
|
48
|
+
const positions = new Map(stored.map((n) => [n.id, { x: n.x, y: n.y }]));
|
|
49
|
+
const nodes = screens.map((screen, idx) => {
|
|
50
|
+
const pos = positions.get(screen.id) ?? { x: 80 + idx * 360, y: 120 };
|
|
51
|
+
return {
|
|
52
|
+
id: screen.id,
|
|
53
|
+
x: pos.x,
|
|
54
|
+
y: pos.y,
|
|
55
|
+
isEntry: manifest?.entryScreenId === screen.id
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
const edges = [];
|
|
59
|
+
for (const screen of screens) {
|
|
60
|
+
const input = findInputLayer(screen);
|
|
61
|
+
const branchingOn = input && (input.kind === "single_choice" || input.kind === "multiple_choice") && input.branching.enabled;
|
|
62
|
+
const nextDefault = screen.next?.default;
|
|
63
|
+
if (branchingOn) {
|
|
64
|
+
for (const cond of input.branching.conditions) {
|
|
65
|
+
if (cond.goTo) {
|
|
66
|
+
edges.push({ source: screen.id, target: cond.goTo, branching: true });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (nextDefault) {
|
|
70
|
+
edges.push({ source: screen.id, target: nextDefault, branching: true });
|
|
71
|
+
}
|
|
72
|
+
} else if (nextDefault) {
|
|
73
|
+
edges.push({ source: screen.id, target: nextDefault });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return { nodes, edges };
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export { buildFlowPreview };
|
|
80
|
+
//# sourceMappingURL=buildFlowPreview.js.map
|
|
81
|
+
//# sourceMappingURL=buildFlowPreview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/layers.ts","../src/buildFlowPreview.ts"],"names":[],"mappings":"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","file":"buildFlowPreview.js","sourcesContent":["import type { Branding } from '@getrheo/contracts/dashboard';\nimport type { FlowManifest, Theme } from '@getrheo/contracts/manifest';\nimport type { Screen } from '@getrheo/contracts/screens';\nimport {\n brandGradientFromThemedColor,\n brandGradientNativeLinear,\n brandGradientSolidFallback,\n isStoredLinearGradientCss,\n nativeLinearFromAngleAndStops,\n parseLinearGradientCss,\n resolveBrandGradientToken,\n type BrandGradientNativeLinear,\n} from './brandGradient';\nimport type {\n InputLayer,\n Layer,\n MultipleChoiceLayer,\n ScaleInputLayer,\n SingleChoiceLayer,\n StackLayer,\n TextInputLayer,\n ThemedColor,\n} from '@getrheo/contracts/layers';\nimport type { LocalizedText } from '@getrheo/contracts/localized';\nimport { resolveLocalizedText } from '@getrheo/contracts/localized';\nimport { isInputLayer } from '@getrheo/contracts/layers';\n\n/** Walk a layer tree depth-first. */\nexport const walkLayers = (root: Layer, fn: (l: Layer, depth: number) => void): void => {\n const visit = (l: Layer, depth: number): void => {\n fn(l, depth);\n if (l.kind === 'stack') l.children.forEach((c) => visit(c, depth + 1));\n else if (l.kind === 'carousel') l.slides.forEach((c) => visit(c, depth + 1));\n else if (l.kind === 'button') l.children.forEach((c) => visit(c, depth + 1));\n else if (l.kind === 'back_button') l.children.forEach((c) => visit(c, depth + 1));\n else if (l.kind === 'hyperlink') l.children.forEach((c) => visit(c, depth + 1));\n else if (l.kind === 'single_choice' || l.kind === 'multiple_choice') {\n l.children.forEach((c) => visit(c, depth + 1));\n } else if (l.kind === 'text_input' || l.kind === 'scale_input') {\n l.children?.forEach((c) => visit(c, depth + 1));\n } else if (l.kind === 'oauth_login') {\n l.children.forEach((c) => visit(c, depth + 1));\n } else if (l.kind === 'oauth_provider' && l.variant === 'custom') {\n l.children.forEach((c) => visit(c, depth + 1));\n } else if (l.kind === 'email_password_auth') {\n l.children.forEach((c) => visit(c, depth + 1));\n } else if (l.kind === 'email_password_field') {\n l.children?.forEach((c) => visit(c, depth + 1));\n } else if (l.kind === 'email_password_submit') {\n l.children.forEach((c) => visit(c, depth + 1));\n }\n };\n visit(root, 0);\n};\n\n/** Walk every layer in a screen's regions (header → body → footer). */\nexport const walkScreen = (screen: Screen, fn: (l: Layer) => void): void => {\n if (screen.regions.header) walkLayers(screen.regions.header, fn);\n walkLayers(screen.regions.body, fn);\n if (screen.regions.footer) walkLayers(screen.regions.footer, fn);\n};\n\n/** Find the screen's lone input layer (if any). Schema enforces ≤1. */\nexport const findInputLayer = (screen: Screen): InputLayer | null => {\n let found: InputLayer | null = null;\n walkScreen(screen, (l) => {\n if (!found && isInputLayer(l)) found = l;\n });\n return found;\n};\n\n/** Input kinds that use a screen draft and require an explicit Continue to submit. */\nexport const findManualSubmitInputLayer = (\n screen: Screen,\n): MultipleChoiceLayer | TextInputLayer | ScaleInputLayer | null => {\n const input = findInputLayer(screen);\n if (!input) return null;\n if (input.kind === 'multiple_choice' || input.kind === 'text_input' || input.kind === 'scale_input') {\n return input;\n }\n return null;\n};\n\n/**\n * Whether the screen contains any Button layer that submits the screen\n * (i.e. `action.kind === 'continue'`). Used by input layers to decide\n * between auto-submit-on-tap (legacy behaviour for choice-only screens)\n * and writing into the screen-level draft for a Button to submit.\n */\nexport const screenHasContinueButton = (screen: Screen): boolean => {\n let found = false;\n walkScreen(screen, (l) => {\n if (l.kind === 'button' && l.action.kind === 'continue') found = true;\n });\n return found;\n};\n\n/**\n * Resolve a choice layer's option stack by stable optionId via its\n * binding. Returns null when the binding is missing or the bound child\n * was removed (manifest validation rejects that, but runtime stays safe).\n */\nexport const findOptionStackForChoice = (\n layer: SingleChoiceLayer | MultipleChoiceLayer,\n optionId: string,\n): StackLayer | null => {\n const binding = layer.optionBindings.find((b) => b.optionId === optionId);\n if (!binding) return null;\n const stack = layer.children.find((c) => c.id === binding.rootLayerId);\n return stack ?? null;\n};\n\n/**\n * Best-effort textual label for a choice option, used by interpolation\n * (e.g. `{{ goal }}` rendering the chosen option's label) and by editor\n * surfaces that show option rows. Walks the option's child subtree\n * depth-first and returns the first `text` layer's content; falls back\n * to the option's stable id when no text is present.\n */\nexport const choiceOptionLabel = (\n layer: SingleChoiceLayer | MultipleChoiceLayer,\n optionId: string,\n locale: string,\n): string => {\n const stack = findOptionStackForChoice(layer, optionId);\n if (!stack) return '';\n let foundText: LocalizedText | null = null;\n walkLayers(stack, (l) => {\n if (foundText) return;\n if (l.kind === 'text') foundText = l.text;\n });\n if (foundText) return resolveLocalizedText(foundText, locale);\n return optionId;\n};\n\n/** Find a layer in a screen by id, including nested children/slides. */\nexport const findLayerById = (screen: Screen, id: string): Layer | null => {\n let found: Layer | null = null;\n walkScreen(screen, (l) => {\n if (!found && l.id === id) found = l;\n });\n return found;\n};\n\n/** Collect all input fieldKeys across a manifest. */\nexport const collectFieldKeys = (manifest: FlowManifest): { fieldKey: string; screenId: string }[] => {\n const out: { fieldKey: string; screenId: string }[] = [];\n for (const screen of manifest.screens) {\n walkScreen(screen as unknown as Screen, (l) => {\n if (isInputLayer(l)) out.push({ fieldKey: l.fieldKey, screenId: screen.id });\n if (l.kind === 'checkbox') out.push({ fieldKey: l.fieldKey, screenId: screen.id });\n if (l.kind === 'email_password_auth') {\n out.push({ fieldKey: l.fieldKey, screenId: screen.id });\n }\n });\n }\n return out;\n};\n\n/**\n * Pick a snake_case field key starting from `base` that is not in `used`\n * (e.g. `text` → `text_2` → `text_3` when `text` is taken).\n */\nexport const nextUniqueFieldKey = (base: string, used: Iterable<string>): string => {\n const set = used instanceof Set ? used : new Set(used);\n if (!set.has(base)) return base;\n let n = 2;\n while (set.has(`${base}_${n}`)) n += 1;\n return `${base}_${n}`;\n};\n\n/**\n * Resolve a token reference like `$primary` to a literal value from `theme`.\n * Pass-through for non-token strings; returns undefined for `undefined`.\n */\nexport const resolveTokens = <T extends string | undefined>(\n theme: Theme | undefined,\n value: T,\n): T | string => {\n if (value === undefined) return value;\n if (typeof value !== 'string' || !value.startsWith('$')) return value;\n const key = value.slice(1) as keyof Theme;\n const literal = theme?.[key];\n if (typeof literal === 'string') return literal;\n return value;\n};\n\n/**\n * Resolve a layer color for the current appearance (`light` | `dark`).\n * Plain string uses `resolveTokens` for both modes (legacy). Object form\n * picks `light` / `dark` with fallback to the other key when one is omitted.\n */\nexport const resolveThemedColor = (\n theme: Theme | undefined,\n palette: 'light' | 'dark',\n value: ThemedColor | undefined,\n): string | undefined => {\n if (value === undefined) return undefined;\n if (typeof value === 'string') return resolveTokens(theme, value) as string;\n const raw = palette === 'dark' ? (value.dark ?? value.light) : (value.light ?? value.dark);\n if (raw === undefined) return undefined;\n return resolveTokens(theme, raw) as string;\n};\n\n/**\n * Resolve a themed value used for CSS `background` (or RN background fill).\n * Supports `$brandGradient:<uuid>` when branding presets are provided; other values match {@link resolveThemedColor}.\n */\nexport const resolveThemedBackground = (\n theme: Theme | undefined,\n branding: Branding | undefined,\n palette: 'light' | 'dark',\n value: ThemedColor | undefined,\n): string | undefined => {\n if (value === undefined) return undefined;\n if (typeof value === 'string') {\n if (value.startsWith('$brandGradient:')) {\n return resolveBrandGradientToken(branding, value);\n }\n return resolveTokens(theme, value) as string;\n }\n const raw = palette === 'dark' ? (value.dark ?? value.light) : (value.light ?? value.dark);\n if (raw === undefined) return undefined;\n if (raw.startsWith('$brandGradient:')) {\n return resolveBrandGradientToken(branding, raw);\n }\n return resolveTokens(theme, raw) as string;\n};\n\nexport const nativeBrandBackgroundFromThemedColor = (\n theme: Theme | undefined,\n branding: Branding | undefined,\n palette: 'light' | 'dark',\n value: ThemedColor | undefined,\n): { solid?: string; linear?: BrandGradientNativeLinear } => {\n const preset = brandGradientFromThemedColor(branding, palette, value);\n if (preset) {\n const lin = brandGradientNativeLinear(preset);\n if (lin) return { linear: lin };\n return { solid: brandGradientSolidFallback(preset) };\n }\n const bg = resolveThemedBackground(theme, branding, palette, value) as string | undefined;\n if (!bg) return {};\n const parsed = parseLinearGradientCss(bg);\n if (parsed) {\n return {\n linear: nativeLinearFromAngleAndStops(\n parsed.angleDeg,\n parsed.stops.map((s) => ({ color: s.color, offsetPct: s.offsetPct })),\n ),\n };\n }\n if (isStoredLinearGradientCss(bg)) {\n const first = bg.match(/#[0-9a-fA-F]{3,8}/);\n return { solid: first ? first[0] : '#808080' };\n }\n return { solid: bg };\n};\n","import type { FlowPreview } from '@getrheo/contracts/dashboard';\nimport type { FlowManifest } from '@getrheo/contracts/manifest';\nimport type { Screen } from '@getrheo/contracts/screens';\nimport { findInputLayer } from './layers';\n\n/** Canvas thumbnail nodes/edges for dashboard flow list and template previews. */\nexport const buildFlowPreview = (manifest: FlowManifest): FlowPreview => {\n const screens = Array.isArray(manifest?.screens) ? manifest.screens : [];\n const stored =\n (manifest?.builderMeta as\n | { layout?: { nodes?: { id: string; x: number; y: number }[] } }\n | undefined)?.layout?.nodes ?? [];\n const positions = new Map(stored.map((n) => [n.id, { x: n.x, y: n.y }]));\n\n const nodes = screens.map((screen, idx) => {\n const pos = positions.get(screen.id) ?? { x: 80 + idx * 360, y: 120 };\n return {\n id: screen.id,\n x: pos.x,\n y: pos.y,\n isEntry: manifest?.entryScreenId === screen.id,\n };\n });\n\n const edges: FlowPreview['edges'] = [];\n for (const screen of screens as unknown as Screen[]) {\n const input = findInputLayer(screen);\n const branchingOn =\n input &&\n (input.kind === 'single_choice' || input.kind === 'multiple_choice') &&\n input.branching.enabled;\n const nextDefault = screen.next?.default;\n\n if (branchingOn) {\n for (const cond of input.branching.conditions) {\n if (cond.goTo) {\n edges.push({ source: screen.id, target: cond.goTo, branching: true });\n }\n }\n if (nextDefault) {\n edges.push({ source: screen.id, target: nextDefault, branching: true });\n }\n } else if (nextDefault) {\n edges.push({ source: screen.id, target: nextDefault });\n }\n }\n\n return { nodes, edges };\n};\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ButtonLayerVariant, ButtonStyle } from '@getrheo/contracts/layers';
|
|
2
|
+
|
|
3
|
+
type ResolvedButtonVariantChrome = {
|
|
4
|
+
bg: string;
|
|
5
|
+
color: string;
|
|
6
|
+
border: string;
|
|
7
|
+
};
|
|
8
|
+
/** Default fill, label, and outline for a preset — used by web sim and native previews. */
|
|
9
|
+
declare const buttonVariantChromeForTheme: (variant: ButtonLayerVariant, theme: "light" | "dark") => ResolvedButtonVariantChrome;
|
|
10
|
+
/**
|
|
11
|
+
* Full variant chrome for manifests and variant-switch patches: themed fill/label/outline
|
|
12
|
+
* plus layout/type tokens that match web sim `buttonBaseStyle` / native `buttonPalette` rows.
|
|
13
|
+
*/
|
|
14
|
+
declare const buttonVariantAuthoringStyleDefaults: (variant: ButtonLayerVariant) => Partial<ButtonStyle>;
|
|
15
|
+
/**
|
|
16
|
+
* Deep-merge variant chrome under an authored `style` so manifests include everything
|
|
17
|
+
* the sim paints by default (padding and other keys from `style` win on conflict).
|
|
18
|
+
*/
|
|
19
|
+
declare const mergeAuthoringButtonStyleWithLayer: (variant: ButtonLayerVariant, style: ButtonStyle | undefined) => ButtonStyle;
|
|
20
|
+
/** Variant outline fallback when authored style omits `border` (flat iOS alert rows use transparent fill). */
|
|
21
|
+
declare const buttonPaletteBorderFallback: (variant: ButtonLayerVariant, theme: "light" | "dark", authoredStyle: Pick<ButtonStyle, "border" | "background"> | undefined, resolvedBackground: string | undefined) => {
|
|
22
|
+
borderWidth: number;
|
|
23
|
+
borderColor?: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export { type ResolvedButtonVariantChrome, buttonPaletteBorderFallback, buttonVariantAuthoringStyleDefaults, buttonVariantChromeForTheme, mergeAuthoringButtonStyleWithLayer };
|