@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
package/dist/layers.js
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { resolveLocalizedText } from '@getrheo/contracts/localized';
|
|
2
|
+
import { isInputLayer } from '@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 rawThemedString = (palette, value) => {
|
|
22
|
+
if (value === void 0) return void 0;
|
|
23
|
+
if (typeof value === "string") return value;
|
|
24
|
+
return palette === "dark" ? value.dark ?? value.light : value.light ?? value.dark;
|
|
25
|
+
};
|
|
26
|
+
var brandGradientFromThemedColor = (branding, palette, value) => {
|
|
27
|
+
const raw = rawThemedString(palette, value);
|
|
28
|
+
if (raw === void 0 || !isBrandGradientToken(raw)) return void 0;
|
|
29
|
+
const id = raw.slice(BRAND_GRADIENT_PREFIX.length);
|
|
30
|
+
return branding?.gradientPresets.find((x) => x.id === id);
|
|
31
|
+
};
|
|
32
|
+
var brandGradientNativeLinear = (g) => {
|
|
33
|
+
if (g.type !== "linear") return null;
|
|
34
|
+
const angleDeg = g.angle ?? 180;
|
|
35
|
+
const \u03B8 = angleDeg * Math.PI / 180;
|
|
36
|
+
const ux = Math.sin(\u03B8);
|
|
37
|
+
const uy = -Math.cos(\u03B8);
|
|
38
|
+
return {
|
|
39
|
+
colors: g.stops.map((s) => s.color),
|
|
40
|
+
locations: g.stops.map((s) => s.offset),
|
|
41
|
+
start: { x: 0.5 - ux * 0.5, y: 0.5 - uy * 0.5 },
|
|
42
|
+
end: { x: 0.5 + ux * 0.5, y: 0.5 + uy * 0.5 }
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
var brandGradientSolidFallback = (g) => g.stops[0]?.color ?? "#808080";
|
|
46
|
+
var HEX_FOR_GRADIENT = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
|
|
47
|
+
var normalizeHexForGradient = (hex) => {
|
|
48
|
+
const t = hex.trim();
|
|
49
|
+
if (!HEX_FOR_GRADIENT.test(t)) return t;
|
|
50
|
+
if (t.length === 4) {
|
|
51
|
+
const [, r, g, b] = t;
|
|
52
|
+
return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();
|
|
53
|
+
}
|
|
54
|
+
if (t.length === 9) return t.slice(0, 7).toLowerCase();
|
|
55
|
+
return t.toLowerCase();
|
|
56
|
+
};
|
|
57
|
+
var clampPct = (n) => Math.min(100, Math.max(0, n));
|
|
58
|
+
var isStoredLinearGradientCss = (s) => /^\s*linear-gradient\s*\(/i.test(s.trim());
|
|
59
|
+
var parseLinearGradientCss = (s) => {
|
|
60
|
+
const t = s.trim();
|
|
61
|
+
const head = t.match(/^\s*linear-gradient\s*\(\s*([-0-9.]+)\s*deg\s*,\s*(.*)\)\s*$/is);
|
|
62
|
+
if (!head) return null;
|
|
63
|
+
const angleStr = head[1];
|
|
64
|
+
const innerRaw = head[2];
|
|
65
|
+
if (angleStr === void 0 || innerRaw === void 0) return null;
|
|
66
|
+
const angleDeg = Number(angleStr);
|
|
67
|
+
if (!Number.isFinite(angleDeg)) return null;
|
|
68
|
+
const inner = innerRaw.trim();
|
|
69
|
+
if (!inner) return null;
|
|
70
|
+
const parts = inner.split(/,(?=\s*#)/);
|
|
71
|
+
const stops = [];
|
|
72
|
+
for (const part of parts) {
|
|
73
|
+
const p = part.trim();
|
|
74
|
+
const m = p.match(/^(#[0-9a-fA-F]{3,8})\s+([-0-9.]+)\s*%$/i);
|
|
75
|
+
if (!m) return null;
|
|
76
|
+
const hex = m[1];
|
|
77
|
+
const offsetStr = m[2];
|
|
78
|
+
if (hex === void 0 || offsetStr === void 0) return null;
|
|
79
|
+
const color = normalizeHexForGradient(hex);
|
|
80
|
+
const offsetPct = Number(offsetStr);
|
|
81
|
+
if (!Number.isFinite(offsetPct)) return null;
|
|
82
|
+
if (!HEX_FOR_GRADIENT.test(color)) return null;
|
|
83
|
+
stops.push({ color, offsetPct });
|
|
84
|
+
}
|
|
85
|
+
if (stops.length < 2) return null;
|
|
86
|
+
return { angleDeg, stops };
|
|
87
|
+
};
|
|
88
|
+
var nativeLinearFromAngleAndStops = (angleDeg, stops) => {
|
|
89
|
+
const sorted = [...stops].map((s) => ({
|
|
90
|
+
color: normalizeHexForGradient(s.color),
|
|
91
|
+
offsetPct: clampPct(Number.isFinite(s.offsetPct) ? s.offsetPct : 0)
|
|
92
|
+
})).sort((a, b) => a.offsetPct - b.offsetPct);
|
|
93
|
+
const \u03B8 = angleDeg * Math.PI / 180;
|
|
94
|
+
const ux = Math.sin(\u03B8);
|
|
95
|
+
const uy = -Math.cos(\u03B8);
|
|
96
|
+
return {
|
|
97
|
+
colors: sorted.map((s) => s.color),
|
|
98
|
+
locations: sorted.map((s) => s.offsetPct / 100),
|
|
99
|
+
start: { x: 0.5 - ux * 0.5, y: 0.5 - uy * 0.5 },
|
|
100
|
+
end: { x: 0.5 + ux * 0.5, y: 0.5 + uy * 0.5 }
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
var walkLayers = (root, fn) => {
|
|
104
|
+
const visit = (l, depth) => {
|
|
105
|
+
fn(l, depth);
|
|
106
|
+
if (l.kind === "stack") l.children.forEach((c) => visit(c, depth + 1));
|
|
107
|
+
else if (l.kind === "carousel") l.slides.forEach((c) => visit(c, depth + 1));
|
|
108
|
+
else if (l.kind === "button") l.children.forEach((c) => visit(c, depth + 1));
|
|
109
|
+
else if (l.kind === "back_button") l.children.forEach((c) => visit(c, depth + 1));
|
|
110
|
+
else if (l.kind === "hyperlink") l.children.forEach((c) => visit(c, depth + 1));
|
|
111
|
+
else if (l.kind === "single_choice" || l.kind === "multiple_choice") {
|
|
112
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
113
|
+
} else if (l.kind === "text_input" || l.kind === "scale_input") {
|
|
114
|
+
l.children?.forEach((c) => visit(c, depth + 1));
|
|
115
|
+
} else if (l.kind === "oauth_login") {
|
|
116
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
117
|
+
} else if (l.kind === "oauth_provider" && l.variant === "custom") {
|
|
118
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
119
|
+
} else if (l.kind === "email_password_auth") {
|
|
120
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
121
|
+
} else if (l.kind === "email_password_field") {
|
|
122
|
+
l.children?.forEach((c) => visit(c, depth + 1));
|
|
123
|
+
} else if (l.kind === "email_password_submit") {
|
|
124
|
+
l.children.forEach((c) => visit(c, depth + 1));
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
visit(root, 0);
|
|
128
|
+
};
|
|
129
|
+
var walkScreen = (screen, fn) => {
|
|
130
|
+
if (screen.regions.header) walkLayers(screen.regions.header, fn);
|
|
131
|
+
walkLayers(screen.regions.body, fn);
|
|
132
|
+
if (screen.regions.footer) walkLayers(screen.regions.footer, fn);
|
|
133
|
+
};
|
|
134
|
+
var findInputLayer = (screen) => {
|
|
135
|
+
let found = null;
|
|
136
|
+
walkScreen(screen, (l) => {
|
|
137
|
+
if (!found && isInputLayer(l)) found = l;
|
|
138
|
+
});
|
|
139
|
+
return found;
|
|
140
|
+
};
|
|
141
|
+
var findManualSubmitInputLayer = (screen) => {
|
|
142
|
+
const input = findInputLayer(screen);
|
|
143
|
+
if (!input) return null;
|
|
144
|
+
if (input.kind === "multiple_choice" || input.kind === "text_input" || input.kind === "scale_input") {
|
|
145
|
+
return input;
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
148
|
+
};
|
|
149
|
+
var screenHasContinueButton = (screen) => {
|
|
150
|
+
let found = false;
|
|
151
|
+
walkScreen(screen, (l) => {
|
|
152
|
+
if (l.kind === "button" && l.action.kind === "continue") found = true;
|
|
153
|
+
});
|
|
154
|
+
return found;
|
|
155
|
+
};
|
|
156
|
+
var findOptionStackForChoice = (layer, optionId) => {
|
|
157
|
+
const binding = layer.optionBindings.find((b) => b.optionId === optionId);
|
|
158
|
+
if (!binding) return null;
|
|
159
|
+
const stack = layer.children.find((c) => c.id === binding.rootLayerId);
|
|
160
|
+
return stack ?? null;
|
|
161
|
+
};
|
|
162
|
+
var choiceOptionLabel = (layer, optionId, locale) => {
|
|
163
|
+
const stack = findOptionStackForChoice(layer, optionId);
|
|
164
|
+
if (!stack) return "";
|
|
165
|
+
let foundText = null;
|
|
166
|
+
walkLayers(stack, (l) => {
|
|
167
|
+
if (foundText) return;
|
|
168
|
+
if (l.kind === "text") foundText = l.text;
|
|
169
|
+
});
|
|
170
|
+
if (foundText) return resolveLocalizedText(foundText, locale);
|
|
171
|
+
return optionId;
|
|
172
|
+
};
|
|
173
|
+
var findLayerById = (screen, id) => {
|
|
174
|
+
let found = null;
|
|
175
|
+
walkScreen(screen, (l) => {
|
|
176
|
+
if (!found && l.id === id) found = l;
|
|
177
|
+
});
|
|
178
|
+
return found;
|
|
179
|
+
};
|
|
180
|
+
var collectFieldKeys = (manifest) => {
|
|
181
|
+
const out = [];
|
|
182
|
+
for (const screen of manifest.screens) {
|
|
183
|
+
walkScreen(screen, (l) => {
|
|
184
|
+
if (isInputLayer(l)) out.push({ fieldKey: l.fieldKey, screenId: screen.id });
|
|
185
|
+
if (l.kind === "checkbox") out.push({ fieldKey: l.fieldKey, screenId: screen.id });
|
|
186
|
+
if (l.kind === "email_password_auth") {
|
|
187
|
+
out.push({ fieldKey: l.fieldKey, screenId: screen.id });
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
return out;
|
|
192
|
+
};
|
|
193
|
+
var nextUniqueFieldKey = (base, used) => {
|
|
194
|
+
const set = used instanceof Set ? used : new Set(used);
|
|
195
|
+
if (!set.has(base)) return base;
|
|
196
|
+
let n = 2;
|
|
197
|
+
while (set.has(`${base}_${n}`)) n += 1;
|
|
198
|
+
return `${base}_${n}`;
|
|
199
|
+
};
|
|
200
|
+
var resolveTokens = (theme, value) => {
|
|
201
|
+
if (value === void 0) return value;
|
|
202
|
+
if (typeof value !== "string" || !value.startsWith("$")) return value;
|
|
203
|
+
const key = value.slice(1);
|
|
204
|
+
const literal = theme?.[key];
|
|
205
|
+
if (typeof literal === "string") return literal;
|
|
206
|
+
return value;
|
|
207
|
+
};
|
|
208
|
+
var resolveThemedColor = (theme, palette, value) => {
|
|
209
|
+
if (value === void 0) return void 0;
|
|
210
|
+
if (typeof value === "string") return resolveTokens(theme, value);
|
|
211
|
+
const raw = palette === "dark" ? value.dark ?? value.light : value.light ?? value.dark;
|
|
212
|
+
if (raw === void 0) return void 0;
|
|
213
|
+
return resolveTokens(theme, raw);
|
|
214
|
+
};
|
|
215
|
+
var resolveThemedBackground = (theme, branding, palette, value) => {
|
|
216
|
+
if (value === void 0) return void 0;
|
|
217
|
+
if (typeof value === "string") {
|
|
218
|
+
if (value.startsWith("$brandGradient:")) {
|
|
219
|
+
return resolveBrandGradientToken(branding, value);
|
|
220
|
+
}
|
|
221
|
+
return resolveTokens(theme, value);
|
|
222
|
+
}
|
|
223
|
+
const raw = palette === "dark" ? value.dark ?? value.light : value.light ?? value.dark;
|
|
224
|
+
if (raw === void 0) return void 0;
|
|
225
|
+
if (raw.startsWith("$brandGradient:")) {
|
|
226
|
+
return resolveBrandGradientToken(branding, raw);
|
|
227
|
+
}
|
|
228
|
+
return resolveTokens(theme, raw);
|
|
229
|
+
};
|
|
230
|
+
var nativeBrandBackgroundFromThemedColor = (theme, branding, palette, value) => {
|
|
231
|
+
const preset = brandGradientFromThemedColor(branding, palette, value);
|
|
232
|
+
if (preset) {
|
|
233
|
+
const lin = brandGradientNativeLinear(preset);
|
|
234
|
+
if (lin) return { linear: lin };
|
|
235
|
+
return { solid: brandGradientSolidFallback(preset) };
|
|
236
|
+
}
|
|
237
|
+
const bg = resolveThemedBackground(theme, branding, palette, value);
|
|
238
|
+
if (!bg) return {};
|
|
239
|
+
const parsed = parseLinearGradientCss(bg);
|
|
240
|
+
if (parsed) {
|
|
241
|
+
return {
|
|
242
|
+
linear: nativeLinearFromAngleAndStops(
|
|
243
|
+
parsed.angleDeg,
|
|
244
|
+
parsed.stops.map((s) => ({ color: s.color, offsetPct: s.offsetPct }))
|
|
245
|
+
)
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
if (isStoredLinearGradientCss(bg)) {
|
|
249
|
+
const first = bg.match(/#[0-9a-fA-F]{3,8}/);
|
|
250
|
+
return { solid: first ? first[0] : "#808080" };
|
|
251
|
+
}
|
|
252
|
+
return { solid: bg };
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
export { choiceOptionLabel, collectFieldKeys, findInputLayer, findLayerById, findManualSubmitInputLayer, findOptionStackForChoice, nativeBrandBackgroundFromThemedColor, nextUniqueFieldKey, resolveThemedBackground, resolveThemedColor, resolveTokens, screenHasContinueButton, walkLayers, walkScreen };
|
|
256
|
+
//# sourceMappingURL=layers.js.map
|
|
257
|
+
//# sourceMappingURL=layers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/brandGradient.ts","../src/layers.ts"],"names":[],"mappings":"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","file":"layers.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"]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { WidthValue, CommonLayoutHeight, LayerKind, LoaderLayer, CommonStyle } from '@getrheo/contracts/layers';
|
|
2
|
+
import { FlowManifest } from '@getrheo/contracts/manifest';
|
|
3
|
+
|
|
4
|
+
type AuthoringLayoutDefaults = {
|
|
5
|
+
width: WidthValue;
|
|
6
|
+
height: CommonLayoutHeight;
|
|
7
|
+
};
|
|
8
|
+
/** Explicit width/height for new layers (inspector always shows a selected mode). */
|
|
9
|
+
declare const defaultLayoutStyleForKind: (kind: LayerKind) => AuthoringLayoutDefaults | null;
|
|
10
|
+
declare const mergeLayoutDefaultsIntoStyle: <T extends Record<string, unknown>>(kind: LayerKind, style: T | undefined) => T;
|
|
11
|
+
|
|
12
|
+
/** Minimal shape every layer satisfies: `kind` plus optional layout fields. */
|
|
13
|
+
type LayerLike = {
|
|
14
|
+
kind?: unknown;
|
|
15
|
+
style?: unknown;
|
|
16
|
+
gap?: unknown;
|
|
17
|
+
variant?: unknown;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Backfill explicit sizing for a single layer based on its kind: `width`/
|
|
21
|
+
* `height` axis modes, per-kind child spacing (`gap`), and feedback scalar
|
|
22
|
+
* dimensions. Existing values always win; kinds without a default (e.g.
|
|
23
|
+
* `carousel`) are left untouched. Loose-typed so it runs on validated `Layer`
|
|
24
|
+
* trees and on JSON-shaped layers (pre-validation AI / import).
|
|
25
|
+
*/
|
|
26
|
+
declare const applyLayoutDefaultsToLayerInPlace: (layer: LayerLike) => void;
|
|
27
|
+
/**
|
|
28
|
+
* Backfill explicit sizing for a layer and its descendants in place.
|
|
29
|
+
* Recursion mirrors the manifest migrate tree walk (stack/button/back_button/
|
|
30
|
+
* carousel/choice/input/oauth/email-password/hyperlink children).
|
|
31
|
+
*/
|
|
32
|
+
declare const normalizeLayerLayoutInPlace: (layer: Record<string, unknown>) => void;
|
|
33
|
+
/** Backfill explicit sizing across a manifest's screens, in place. */
|
|
34
|
+
declare const normalizeManifestLayoutInPlace: (manifest: FlowManifest) => void;
|
|
35
|
+
|
|
36
|
+
/** Bar thickness (px) for a linear progress bar when `style.height` is omitted. */
|
|
37
|
+
declare const DEFAULT_PROGRESS_LINEAR_HEIGHT_PX = 6;
|
|
38
|
+
/** Bar thickness (px) for a linear loader when `style.height` is omitted. */
|
|
39
|
+
declare const DEFAULT_LOADER_LINEAR_HEIGHT_PX = 6;
|
|
40
|
+
/** Diameter (px) for a circular loader when `style.width`/`style.height` are omitted. */
|
|
41
|
+
declare const DEFAULT_LOADER_CIRCULAR_SIZE_PX = 48;
|
|
42
|
+
/** Ring thickness (px) for a circular loader when `style.strokeWidth` is omitted. */
|
|
43
|
+
declare const DEFAULT_LOADER_STROKE_WIDTH_PX = 4;
|
|
44
|
+
declare const defaultGapForLayerKind: (kind: LayerKind) => number | null;
|
|
45
|
+
/**
|
|
46
|
+
* Explicit scalar dimensions for feedback layers (progress / loader) whose
|
|
47
|
+
* sizing lives directly on `style` as pixel values. Used by ingress
|
|
48
|
+
* normalization to backfill omitted dimensions and by the inspector to show
|
|
49
|
+
* the effective size. Renderers keep their own safety nets via the resolvers
|
|
50
|
+
* in `responsive/layerResolve`.
|
|
51
|
+
*/
|
|
52
|
+
declare const defaultFeedbackStyleScalars: (kind: "progress" | "loader", variant?: LoaderLayer["variant"]) => Partial<CommonStyle> | null;
|
|
53
|
+
|
|
54
|
+
/** Whether a stack should grow on the parent stack main axis (web/RN StackView parity with SwiftUI). */
|
|
55
|
+
declare const stackMainAxisFillHeight: (height: CommonLayoutHeight | undefined) => boolean;
|
|
56
|
+
|
|
57
|
+
export { type AuthoringLayoutDefaults, DEFAULT_LOADER_CIRCULAR_SIZE_PX, DEFAULT_LOADER_LINEAR_HEIGHT_PX, DEFAULT_LOADER_STROKE_WIDTH_PX, DEFAULT_PROGRESS_LINEAR_HEIGHT_PX, applyLayoutDefaultsToLayerInPlace, defaultFeedbackStyleScalars, defaultGapForLayerKind, defaultLayoutStyleForKind, mergeLayoutDefaultsIntoStyle, normalizeLayerLayoutInPlace, normalizeManifestLayoutInPlace, stackMainAxisFillHeight };
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// src/layout/scalarLayoutDefaults.ts
|
|
2
|
+
var DEFAULT_PROGRESS_LINEAR_HEIGHT_PX = 6;
|
|
3
|
+
var DEFAULT_LOADER_LINEAR_HEIGHT_PX = 6;
|
|
4
|
+
var DEFAULT_LOADER_CIRCULAR_SIZE_PX = 48;
|
|
5
|
+
var DEFAULT_LOADER_STROKE_WIDTH_PX = 4;
|
|
6
|
+
var GAP_BY_KIND = {
|
|
7
|
+
stack: 12,
|
|
8
|
+
single_choice: 8,
|
|
9
|
+
multiple_choice: 8,
|
|
10
|
+
oauth_login: 8,
|
|
11
|
+
email_password_auth: 8,
|
|
12
|
+
email_password_submit: 8,
|
|
13
|
+
button: 8,
|
|
14
|
+
back_button: 8,
|
|
15
|
+
oauth_provider: 8,
|
|
16
|
+
hyperlink: 0
|
|
17
|
+
};
|
|
18
|
+
var defaultGapForLayerKind = (kind) => GAP_BY_KIND[kind] ?? null;
|
|
19
|
+
var defaultFeedbackStyleScalars = (kind, variant) => {
|
|
20
|
+
if (kind === "progress") {
|
|
21
|
+
return { height: DEFAULT_PROGRESS_LINEAR_HEIGHT_PX };
|
|
22
|
+
}
|
|
23
|
+
if (variant === "circular") {
|
|
24
|
+
return {
|
|
25
|
+
width: DEFAULT_LOADER_CIRCULAR_SIZE_PX,
|
|
26
|
+
height: DEFAULT_LOADER_CIRCULAR_SIZE_PX,
|
|
27
|
+
strokeWidth: DEFAULT_LOADER_STROKE_WIDTH_PX
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return { height: DEFAULT_LOADER_LINEAR_HEIGHT_PX };
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// src/layout/authoringLayoutDefaults.ts
|
|
34
|
+
var LAYOUT_FULL_HUG = { width: "full", height: "auto" };
|
|
35
|
+
var LAYOUT_FULL_FILL = { width: "full", height: "fill" };
|
|
36
|
+
var LAYOUT_HUG_HUG = { width: "auto", height: "auto" };
|
|
37
|
+
var LAYOUT_FULL_FIXED_H160 = { width: "full", height: 160 };
|
|
38
|
+
var LAYOUT_PROGRESS = {
|
|
39
|
+
width: "full",
|
|
40
|
+
height: DEFAULT_PROGRESS_LINEAR_HEIGHT_PX
|
|
41
|
+
};
|
|
42
|
+
var LAYOUT_LOADER_LINEAR = {
|
|
43
|
+
width: "full",
|
|
44
|
+
height: DEFAULT_LOADER_LINEAR_HEIGHT_PX
|
|
45
|
+
};
|
|
46
|
+
var defaultLayoutStyleForKind = (kind) => {
|
|
47
|
+
switch (kind) {
|
|
48
|
+
case "stack":
|
|
49
|
+
return LAYOUT_FULL_FILL;
|
|
50
|
+
case "text":
|
|
51
|
+
case "counter":
|
|
52
|
+
return LAYOUT_HUG_HUG;
|
|
53
|
+
case "hyperlink":
|
|
54
|
+
return LAYOUT_HUG_HUG;
|
|
55
|
+
case "image":
|
|
56
|
+
case "lottie":
|
|
57
|
+
case "video":
|
|
58
|
+
return LAYOUT_FULL_FIXED_H160;
|
|
59
|
+
case "icon":
|
|
60
|
+
return LAYOUT_HUG_HUG;
|
|
61
|
+
case "button":
|
|
62
|
+
case "back_button":
|
|
63
|
+
case "oauth_provider":
|
|
64
|
+
case "email_password_submit":
|
|
65
|
+
return LAYOUT_FULL_HUG;
|
|
66
|
+
case "text_input":
|
|
67
|
+
case "scale_input":
|
|
68
|
+
case "email_password_auth":
|
|
69
|
+
case "email_password_field":
|
|
70
|
+
case "oauth_login":
|
|
71
|
+
return LAYOUT_FULL_FILL;
|
|
72
|
+
case "progress":
|
|
73
|
+
return LAYOUT_PROGRESS;
|
|
74
|
+
case "loader":
|
|
75
|
+
return LAYOUT_LOADER_LINEAR;
|
|
76
|
+
case "checkbox":
|
|
77
|
+
case "single_choice":
|
|
78
|
+
case "multiple_choice":
|
|
79
|
+
return LAYOUT_FULL_HUG;
|
|
80
|
+
case "carousel":
|
|
81
|
+
return null;
|
|
82
|
+
default:
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
var mergeLayoutDefaultsIntoStyle = (kind, style) => {
|
|
87
|
+
const defaults = defaultLayoutStyleForKind(kind);
|
|
88
|
+
if (!defaults) return style ?? {};
|
|
89
|
+
return { ...defaults, ...style };
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// src/layout/normalizeLayerLayout.ts
|
|
93
|
+
var isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
94
|
+
var applyAxisDefaultsInPlace = (layer, kind) => {
|
|
95
|
+
const current = isObj(layer.style) ? layer.style : void 0;
|
|
96
|
+
if (kind === "loader" && layer.variant === "circular") {
|
|
97
|
+
const feedback = defaultFeedbackStyleScalars("loader", "circular");
|
|
98
|
+
layer.style = { ...feedback, ...current ?? {} };
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (!defaultLayoutStyleForKind(kind)) return;
|
|
102
|
+
layer.style = mergeLayoutDefaultsIntoStyle(kind, current);
|
|
103
|
+
};
|
|
104
|
+
var applyGapDefaultInPlace = (layer, kind) => {
|
|
105
|
+
const gapDefault = defaultGapForLayerKind(kind);
|
|
106
|
+
if (gapDefault === null) return;
|
|
107
|
+
if (kind === "oauth_provider" && layer.variant !== "custom") return;
|
|
108
|
+
if (layer.gap === void 0) layer.gap = gapDefault;
|
|
109
|
+
};
|
|
110
|
+
var applyLayoutDefaultsToLayerInPlace = (layer) => {
|
|
111
|
+
if (typeof layer.kind !== "string") return;
|
|
112
|
+
const kind = layer.kind;
|
|
113
|
+
applyAxisDefaultsInPlace(layer, kind);
|
|
114
|
+
applyGapDefaultInPlace(layer, kind);
|
|
115
|
+
};
|
|
116
|
+
var recurseChildren = (parent, key) => {
|
|
117
|
+
const kids = parent[key];
|
|
118
|
+
if (!Array.isArray(kids)) return;
|
|
119
|
+
for (const child of kids) {
|
|
120
|
+
if (isObj(child)) normalizeLayerLayoutInPlace(child);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
var normalizeLayerLayoutInPlace = (layer) => {
|
|
124
|
+
applyLayoutDefaultsToLayerInPlace(layer);
|
|
125
|
+
const kind = layer.kind;
|
|
126
|
+
if (kind === "carousel") {
|
|
127
|
+
recurseChildren(layer, "slides");
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
recurseChildren(layer, "children");
|
|
131
|
+
};
|
|
132
|
+
var normalizeManifestLayoutInPlace = (manifest) => {
|
|
133
|
+
const screens = manifest.screens;
|
|
134
|
+
if (!Array.isArray(screens)) return;
|
|
135
|
+
for (const screen of screens) {
|
|
136
|
+
if (!isObj(screen)) continue;
|
|
137
|
+
const regions = screen.regions;
|
|
138
|
+
if (!isObj(regions)) continue;
|
|
139
|
+
for (const key of ["header", "body", "footer"]) {
|
|
140
|
+
const region = regions[key];
|
|
141
|
+
if (isObj(region)) normalizeLayerLayoutInPlace(region);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// src/layout/stackFlexGrow.ts
|
|
147
|
+
var stackMainAxisFillHeight = (height) => height === "fill" || height === "full";
|
|
148
|
+
|
|
149
|
+
export { DEFAULT_LOADER_CIRCULAR_SIZE_PX, DEFAULT_LOADER_LINEAR_HEIGHT_PX, DEFAULT_LOADER_STROKE_WIDTH_PX, DEFAULT_PROGRESS_LINEAR_HEIGHT_PX, applyLayoutDefaultsToLayerInPlace, defaultFeedbackStyleScalars, defaultGapForLayerKind, defaultLayoutStyleForKind, mergeLayoutDefaultsIntoStyle, normalizeLayerLayoutInPlace, normalizeManifestLayoutInPlace, stackMainAxisFillHeight };
|
|
150
|
+
//# sourceMappingURL=index.js.map
|
|
151
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/layout/scalarLayoutDefaults.ts","../../src/layout/authoringLayoutDefaults.ts","../../src/layout/normalizeLayerLayout.ts","../../src/layout/stackFlexGrow.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { CommonStyle, LayerKind, LoaderLayer } from '@getrheo/contracts/layers';\n\n/** Bar thickness (px) for a linear progress bar when `style.height` is omitted. */\nexport const DEFAULT_PROGRESS_LINEAR_HEIGHT_PX = 6;\n/** Bar thickness (px) for a linear loader when `style.height` is omitted. */\nexport const DEFAULT_LOADER_LINEAR_HEIGHT_PX = 6;\n/** Diameter (px) for a circular loader when `style.width`/`style.height` are omitted. */\nexport const DEFAULT_LOADER_CIRCULAR_SIZE_PX = 48;\n/** Ring thickness (px) for a circular loader when `style.strokeWidth` is omitted. */\nexport const DEFAULT_LOADER_STROKE_WIDTH_PX = 4;\n\n/**\n * Standard child spacing (px) for kinds that lay out children in a flex\n * container. Mirrors the authoring defaults in `createLayer*` and the\n * historical renderer fallbacks (`?? 8` / `?? 0`). Kinds without a `gap`\n * field, or where spacing does not apply, are absent (→ `null`).\n */\nconst GAP_BY_KIND: Partial<Record<LayerKind, number>> = {\n stack: 12,\n single_choice: 8,\n multiple_choice: 8,\n oauth_login: 8,\n email_password_auth: 8,\n email_password_submit: 8,\n button: 8,\n back_button: 8,\n oauth_provider: 8,\n hyperlink: 0,\n};\n\nexport const defaultGapForLayerKind = (kind: LayerKind): number | null =>\n GAP_BY_KIND[kind] ?? null;\n\n/**\n * Explicit scalar dimensions for feedback layers (progress / loader) whose\n * sizing lives directly on `style` as pixel values. Used by ingress\n * normalization to backfill omitted dimensions and by the inspector to show\n * the effective size. Renderers keep their own safety nets via the resolvers\n * in `responsive/layerResolve`.\n */\nexport const defaultFeedbackStyleScalars = (\n kind: 'progress' | 'loader',\n variant?: LoaderLayer['variant'],\n): Partial<CommonStyle> | null => {\n if (kind === 'progress') {\n return { height: DEFAULT_PROGRESS_LINEAR_HEIGHT_PX };\n }\n if (variant === 'circular') {\n return {\n width: DEFAULT_LOADER_CIRCULAR_SIZE_PX,\n height: DEFAULT_LOADER_CIRCULAR_SIZE_PX,\n strokeWidth: DEFAULT_LOADER_STROKE_WIDTH_PX,\n };\n }\n return { height: DEFAULT_LOADER_LINEAR_HEIGHT_PX };\n};\n","import type { CommonLayoutHeight, LayerKind, WidthValue } from '@getrheo/contracts/layers';\nimport {\n DEFAULT_LOADER_LINEAR_HEIGHT_PX,\n DEFAULT_PROGRESS_LINEAR_HEIGHT_PX,\n} from './scalarLayoutDefaults';\n\nexport type AuthoringLayoutDefaults = {\n width: WidthValue;\n height: CommonLayoutHeight;\n};\n\nconst LAYOUT_FULL_HUG: AuthoringLayoutDefaults = { width: 'full', height: 'auto' };\nconst LAYOUT_FULL_FILL: AuthoringLayoutDefaults = { width: 'full', height: 'fill' };\nconst LAYOUT_HUG_HUG: AuthoringLayoutDefaults = { width: 'auto', height: 'auto' };\nconst LAYOUT_FULL_FIXED_H160: AuthoringLayoutDefaults = { width: 'full', height: 160 };\n// Feedback bars span their container width but use a fixed px thickness; the\n// circular loader's square sizing is handled by `defaultFeedbackStyleScalars`.\nconst LAYOUT_PROGRESS: AuthoringLayoutDefaults = {\n width: 'full',\n height: DEFAULT_PROGRESS_LINEAR_HEIGHT_PX,\n};\nconst LAYOUT_LOADER_LINEAR: AuthoringLayoutDefaults = {\n width: 'full',\n height: DEFAULT_LOADER_LINEAR_HEIGHT_PX,\n};\n\n/** Explicit width/height for new layers (inspector always shows a selected mode). */\nexport const defaultLayoutStyleForKind = (kind: LayerKind): AuthoringLayoutDefaults | null => {\n switch (kind) {\n case 'stack':\n return LAYOUT_FULL_FILL;\n case 'text':\n case 'counter':\n return LAYOUT_HUG_HUG;\n case 'hyperlink':\n return LAYOUT_HUG_HUG;\n case 'image':\n case 'lottie':\n case 'video':\n return LAYOUT_FULL_FIXED_H160;\n case 'icon':\n return LAYOUT_HUG_HUG;\n case 'button':\n case 'back_button':\n case 'oauth_provider':\n case 'email_password_submit':\n return LAYOUT_FULL_HUG;\n case 'text_input':\n case 'scale_input':\n case 'email_password_auth':\n case 'email_password_field':\n case 'oauth_login':\n return LAYOUT_FULL_FILL;\n case 'progress':\n return LAYOUT_PROGRESS;\n case 'loader':\n return LAYOUT_LOADER_LINEAR;\n case 'checkbox':\n case 'single_choice':\n case 'multiple_choice':\n return LAYOUT_FULL_HUG;\n case 'carousel':\n return null;\n default:\n return null;\n }\n};\n\nexport const mergeLayoutDefaultsIntoStyle = <T extends Record<string, unknown>>(\n kind: LayerKind,\n style: T | undefined,\n): T => {\n const defaults = defaultLayoutStyleForKind(kind);\n if (!defaults) return (style ?? {}) as T;\n return { ...defaults, ...style } as unknown as T;\n};\n","import type { LayerKind } from '@getrheo/contracts/layers';\nimport type { FlowManifest } from '@getrheo/contracts/manifest';\nimport { defaultLayoutStyleForKind, mergeLayoutDefaultsIntoStyle } from './authoringLayoutDefaults';\nimport { defaultFeedbackStyleScalars, defaultGapForLayerKind } from './scalarLayoutDefaults';\n\n/** Minimal shape every layer satisfies: `kind` plus optional layout fields. */\ntype LayerLike = { kind?: unknown; style?: unknown; gap?: unknown; variant?: unknown };\n\nconst isObj = (v: unknown): v is Record<string, unknown> =>\n typeof v === 'object' && v !== null && !Array.isArray(v);\n\n/** Backfill explicit `width`/`height` (and circular-loader scalars). */\nconst applyAxisDefaultsInPlace = (layer: LayerLike, kind: LayerKind): void => {\n const current = isObj(layer.style) ? layer.style : undefined;\n if (kind === 'loader' && layer.variant === 'circular') {\n const feedback = defaultFeedbackStyleScalars('loader', 'circular');\n layer.style = { ...feedback, ...(current ?? {}) };\n return;\n }\n if (!defaultLayoutStyleForKind(kind)) return;\n layer.style = mergeLayoutDefaultsIntoStyle(kind, current);\n};\n\n/** Backfill the per-kind child spacing default when `gap` is omitted. */\nconst applyGapDefaultInPlace = (layer: LayerLike, kind: LayerKind): void => {\n const gapDefault = defaultGapForLayerKind(kind);\n if (gapDefault === null) return;\n // Preset OAuth provider rows have no `gap` field; only custom rows do.\n if (kind === 'oauth_provider' && layer.variant !== 'custom') return;\n if (layer.gap === undefined) layer.gap = gapDefault;\n};\n\n/**\n * Backfill explicit sizing for a single layer based on its kind: `width`/\n * `height` axis modes, per-kind child spacing (`gap`), and feedback scalar\n * dimensions. Existing values always win; kinds without a default (e.g.\n * `carousel`) are left untouched. Loose-typed so it runs on validated `Layer`\n * trees and on JSON-shaped layers (pre-validation AI / import).\n */\nexport const applyLayoutDefaultsToLayerInPlace = (layer: LayerLike): void => {\n if (typeof layer.kind !== 'string') return;\n const kind = layer.kind as LayerKind;\n applyAxisDefaultsInPlace(layer, kind);\n applyGapDefaultInPlace(layer, kind);\n};\n\nconst recurseChildren = (parent: Record<string, unknown>, key: 'children' | 'slides'): void => {\n const kids = parent[key];\n if (!Array.isArray(kids)) return;\n for (const child of kids) {\n if (isObj(child)) normalizeLayerLayoutInPlace(child);\n }\n};\n\n/**\n * Backfill explicit sizing for a layer and its descendants in place.\n * Recursion mirrors the manifest migrate tree walk (stack/button/back_button/\n * carousel/choice/input/oauth/email-password/hyperlink children).\n */\nexport const normalizeLayerLayoutInPlace = (layer: Record<string, unknown>): void => {\n applyLayoutDefaultsToLayerInPlace(layer as LayerLike);\n const kind = layer.kind;\n if (kind === 'carousel') {\n recurseChildren(layer, 'slides');\n return;\n }\n // Every other container kind nests under `children`; non-containers have none.\n recurseChildren(layer, 'children');\n};\n\n/** Backfill explicit sizing across a manifest's screens, in place. */\nexport const normalizeManifestLayoutInPlace = (manifest: FlowManifest): void => {\n const screens = (manifest as { screens?: unknown }).screens;\n if (!Array.isArray(screens)) return;\n for (const screen of screens) {\n if (!isObj(screen)) continue;\n const regions = screen.regions;\n if (!isObj(regions)) continue;\n for (const key of ['header', 'body', 'footer'] as const) {\n const region = regions[key];\n if (isObj(region)) normalizeLayerLayoutInPlace(region);\n }\n }\n};\n","import type { CommonLayoutHeight } from '@getrheo/contracts/layers';\n\n/** Whether a stack should grow on the parent stack main axis (web/RN StackView parity with SwiftUI). */\nexport const stackMainAxisFillHeight = (\n height: CommonLayoutHeight | undefined,\n): boolean => height === 'fill' || height === 'full';\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FlowManifest } from '@getrheo/contracts/manifest';
|
|
2
|
+
|
|
3
|
+
/** Deep clone manifest JSON shape for SDK responses. */
|
|
4
|
+
declare const cloneManifestForBillingSlice: (m: FlowManifest) => FlowManifest;
|
|
5
|
+
/** Removes per-screen animation clips (timeline / transitions). */
|
|
6
|
+
declare const stripManifestAnimations: (manifest: FlowManifest) => FlowManifest;
|
|
7
|
+
/** Removes screen clips, stagger defaults, and per-layer resting motion. */
|
|
8
|
+
declare const stripManifestMotion: (manifest: FlowManifest) => FlowManifest;
|
|
9
|
+
/** Drops `translations` on every LocalizedText-shaped object; trims locales list to default only. */
|
|
10
|
+
declare const collapseManifestToDefaultLocaleOnly: (manifest: FlowManifest) => FlowManifest;
|
|
11
|
+
declare const manifestHasScreenAnimations: (manifest: FlowManifest) => boolean;
|
|
12
|
+
/** True when manifest carries locale variants editors expect Grow+ for. */
|
|
13
|
+
declare const manifestUsesTranslationsBeyondDefault: (manifest: FlowManifest) => boolean;
|
|
14
|
+
/** True when manifest includes an external integration step with a concrete provider (Grow+). */
|
|
15
|
+
declare const manifestUsesExternalIntegrations: (manifest: FlowManifest) => boolean;
|
|
16
|
+
|
|
17
|
+
export { cloneManifestForBillingSlice, collapseManifestToDefaultLocaleOnly, manifestHasScreenAnimations, manifestUsesExternalIntegrations, manifestUsesTranslationsBeyondDefault, stripManifestAnimations, stripManifestMotion };
|