@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,48 @@
|
|
|
1
|
+
// src/colorAlpha.ts
|
|
2
|
+
var multiplyColorAlpha = (color, factor) => {
|
|
3
|
+
if (color === void 0) return void 0;
|
|
4
|
+
if (factor === void 0 || factor >= 1 - 1e-6) return color;
|
|
5
|
+
if (factor <= 1e-6) return "rgba(0,0,0,0)";
|
|
6
|
+
const hex8 = /^#([0-9a-fA-F]{8})$/;
|
|
7
|
+
const hex6 = /^#([0-9a-fA-F]{6})$/;
|
|
8
|
+
const hex3 = /^#([0-9a-fA-F]{3})$/;
|
|
9
|
+
const rgba = /^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*([\d.]+))?\s*\)$/;
|
|
10
|
+
let r;
|
|
11
|
+
let g;
|
|
12
|
+
let b;
|
|
13
|
+
let a = 1;
|
|
14
|
+
const m8 = color.match(hex8);
|
|
15
|
+
const m6 = color.match(hex6);
|
|
16
|
+
const m3 = color.match(hex3);
|
|
17
|
+
const mr = color.match(rgba);
|
|
18
|
+
if (m8) {
|
|
19
|
+
const h = m8[1];
|
|
20
|
+
r = parseInt(h.slice(0, 2), 16);
|
|
21
|
+
g = parseInt(h.slice(2, 4), 16);
|
|
22
|
+
b = parseInt(h.slice(4, 6), 16);
|
|
23
|
+
a = parseInt(h.slice(6, 8), 16) / 255;
|
|
24
|
+
} else if (m6) {
|
|
25
|
+
const h = m6[1];
|
|
26
|
+
r = parseInt(h.slice(0, 2), 16);
|
|
27
|
+
g = parseInt(h.slice(2, 4), 16);
|
|
28
|
+
b = parseInt(h.slice(4, 6), 16);
|
|
29
|
+
} else if (m3) {
|
|
30
|
+
const h = m3[1];
|
|
31
|
+
r = parseInt(h[0] + h[0], 16);
|
|
32
|
+
g = parseInt(h[1] + h[1], 16);
|
|
33
|
+
b = parseInt(h[2] + h[2], 16);
|
|
34
|
+
} else if (mr) {
|
|
35
|
+
r = Number(mr[1]);
|
|
36
|
+
g = Number(mr[2]);
|
|
37
|
+
b = Number(mr[3]);
|
|
38
|
+
if (mr[4] !== void 0) a = Number(mr[4]);
|
|
39
|
+
} else {
|
|
40
|
+
return color;
|
|
41
|
+
}
|
|
42
|
+
const outA = Math.min(1, Math.max(0, a * factor));
|
|
43
|
+
return `rgba(${r},${g},${b},${outA})`;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { multiplyColorAlpha };
|
|
47
|
+
//# sourceMappingURL=colorAlpha.js.map
|
|
48
|
+
//# sourceMappingURL=colorAlpha.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/colorAlpha.ts"],"names":[],"mappings":"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","file":"colorAlpha.js","sourcesContent":["/**\n * Multiply the alpha of a resolved CSS color by `factor` (0–1).\n * Used so text layers can dim only the background fill without applying `opacity` to the whole node.\n * Supports #RGB, #RRGGBB, #RRGGBBAA, rgb(), rgba(). Unrecognized strings are returned as-is (no alpha change).\n */\nexport const multiplyColorAlpha = (\n color: string | undefined,\n factor: number | undefined,\n): string | undefined => {\n if (color === undefined) return undefined;\n if (factor === undefined || factor >= 1 - 1e-6) return color;\n if (factor <= 1e-6) return 'rgba(0,0,0,0)';\n\n const hex8 = /^#([0-9a-fA-F]{8})$/;\n const hex6 = /^#([0-9a-fA-F]{6})$/;\n const hex3 = /^#([0-9a-fA-F]{3})$/;\n const rgba = /^rgba?\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*,\\s*([\\d.]+)(?:\\s*,\\s*([\\d.]+))?\\s*\\)$/;\n\n let r: number;\n let g: number;\n let b: number;\n let a = 1;\n\n const m8 = color.match(hex8);\n const m6 = color.match(hex6);\n const m3 = color.match(hex3);\n const mr = color.match(rgba);\n\n if (m8) {\n const h = m8[1]!;\n r = parseInt(h.slice(0, 2), 16);\n g = parseInt(h.slice(2, 4), 16);\n b = parseInt(h.slice(4, 6), 16);\n a = parseInt(h.slice(6, 8), 16) / 255;\n } else if (m6) {\n const h = m6[1]!;\n r = parseInt(h.slice(0, 2), 16);\n g = parseInt(h.slice(2, 4), 16);\n b = parseInt(h.slice(4, 6), 16);\n } else if (m3) {\n const h = m3[1]!;\n r = parseInt(h[0]! + h[0]!, 16);\n g = parseInt(h[1]! + h[1]!, 16);\n b = parseInt(h[2]! + h[2]!, 16);\n } else if (mr) {\n r = Number(mr[1]);\n g = Number(mr[2]);\n b = Number(mr[3]);\n if (mr[4] !== undefined) a = Number(mr[4]);\n } else {\n return color;\n }\n\n const outA = Math.min(1, Math.max(0, a * factor));\n return `rgba(${r},${g},${b},${outA})`;\n};\n"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { CounterDisplayKind, CounterTimeFormat } from '@getrheo/contracts/layers';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pretty-print animated counter values for display (web + native).
|
|
5
|
+
* `decimalPlaces` is clamped to 0–20. Trailing fractional zeros are trimmed
|
|
6
|
+
* except when `decimalPlaces === 0` (integer rounding via `toFixed(0)`).
|
|
7
|
+
*/
|
|
8
|
+
declare const formatCounterLayerValue: (n: number, decimalPlaces?: number) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Format a non-negative whole-second count as M:SS, H:MM:SS, or D:HH:MM:SS.
|
|
11
|
+
* Fractional input uses `floor`; negative totals clamp to zero.
|
|
12
|
+
*/
|
|
13
|
+
declare const formatCounterAsTime: (totalSeconds: number, format: CounterTimeFormat) => string;
|
|
14
|
+
type CounterLayerDisplayOpts = {
|
|
15
|
+
displayKind?: CounterDisplayKind;
|
|
16
|
+
decimalPlaces?: number;
|
|
17
|
+
timeFormat?: CounterTimeFormat;
|
|
18
|
+
};
|
|
19
|
+
/** Routes to numeric or time formatting based on layer display settings. */
|
|
20
|
+
declare const formatCounterLayerDisplay: (n: number, opts: CounterLayerDisplayOpts) => string;
|
|
21
|
+
/** Components for the counter inspector when editing time mode (all non‑negative integers). */
|
|
22
|
+
type CounterTimeParts = {
|
|
23
|
+
days: number;
|
|
24
|
+
hours: number;
|
|
25
|
+
minutes: number;
|
|
26
|
+
seconds: number;
|
|
27
|
+
};
|
|
28
|
+
declare const splitSecondsForTimeFormat: (totalSeconds: number, format: CounterTimeFormat) => CounterTimeParts;
|
|
29
|
+
/** Compose UI units into total seconds (matches {@link splitSecondsForTimeFormat}). */
|
|
30
|
+
declare const mergePartsForTimeFormat: (parts: CounterTimeParts, format: CounterTimeFormat) => number;
|
|
31
|
+
/**
|
|
32
|
+
* Time mode advances one displayed second per real second over |end − start|.
|
|
33
|
+
* Number mode uses authored `durationMs` (default 3000).
|
|
34
|
+
*/
|
|
35
|
+
declare const resolveCounterAnimationDurationMs: (opts: {
|
|
36
|
+
displayKind?: CounterDisplayKind;
|
|
37
|
+
durationMs?: number;
|
|
38
|
+
startValue: number;
|
|
39
|
+
endValue: number;
|
|
40
|
+
}) => number;
|
|
41
|
+
|
|
42
|
+
export { type CounterLayerDisplayOpts, type CounterTimeParts, formatCounterAsTime, formatCounterLayerDisplay, formatCounterLayerValue, mergePartsForTimeFormat, resolveCounterAnimationDurationMs, splitSecondsForTimeFormat };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// src/counterLayer.ts
|
|
2
|
+
var formatCounterLayerValue = (n, decimalPlaces = 0) => {
|
|
3
|
+
if (!Number.isFinite(n)) return "";
|
|
4
|
+
const p = Math.max(0, Math.min(20, Math.trunc(decimalPlaces)));
|
|
5
|
+
const s = n.toFixed(p);
|
|
6
|
+
if (p === 0) return s;
|
|
7
|
+
const trimmed = s.replace(/\.?0+$/, "");
|
|
8
|
+
return trimmed === "" || trimmed === "-" ? "0" : trimmed;
|
|
9
|
+
};
|
|
10
|
+
var pad2 = (n) => String(n).padStart(2, "0");
|
|
11
|
+
var formatCounterAsTime = (totalSeconds, format) => {
|
|
12
|
+
if (!Number.isFinite(totalSeconds)) return "";
|
|
13
|
+
const whole = Math.max(0, Math.floor(totalSeconds));
|
|
14
|
+
switch (format) {
|
|
15
|
+
case "mm_ss": {
|
|
16
|
+
const minutes = Math.floor(whole / 60);
|
|
17
|
+
const seconds = whole % 60;
|
|
18
|
+
return `${minutes}:${pad2(seconds)}`;
|
|
19
|
+
}
|
|
20
|
+
case "hh_mm_ss": {
|
|
21
|
+
const hours = Math.floor(whole / 3600);
|
|
22
|
+
const minutes = Math.floor(whole % 3600 / 60);
|
|
23
|
+
const seconds = whole % 60;
|
|
24
|
+
return `${hours}:${pad2(minutes)}:${pad2(seconds)}`;
|
|
25
|
+
}
|
|
26
|
+
case "dd_hh_mm_ss": {
|
|
27
|
+
const days = Math.floor(whole / 86400);
|
|
28
|
+
const hours = Math.floor(whole % 86400 / 3600);
|
|
29
|
+
const minutes = Math.floor(whole % 3600 / 60);
|
|
30
|
+
const seconds = whole % 60;
|
|
31
|
+
return `${days}:${pad2(hours)}:${pad2(minutes)}:${pad2(seconds)}`;
|
|
32
|
+
}
|
|
33
|
+
default:
|
|
34
|
+
return "";
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var formatCounterLayerDisplay = (n, opts) => {
|
|
38
|
+
const kind = opts.displayKind ?? "number";
|
|
39
|
+
if (kind === "time") {
|
|
40
|
+
const tf = opts.timeFormat ?? "mm_ss";
|
|
41
|
+
return formatCounterAsTime(n, tf);
|
|
42
|
+
}
|
|
43
|
+
return formatCounterLayerValue(n, opts.decimalPlaces ?? 0);
|
|
44
|
+
};
|
|
45
|
+
var splitSecondsForTimeFormat = (totalSeconds, format) => {
|
|
46
|
+
const whole = Math.max(0, Math.floor(Number.isFinite(totalSeconds) ? totalSeconds : 0));
|
|
47
|
+
switch (format) {
|
|
48
|
+
case "mm_ss":
|
|
49
|
+
return {
|
|
50
|
+
days: 0,
|
|
51
|
+
hours: 0,
|
|
52
|
+
minutes: Math.floor(whole / 60),
|
|
53
|
+
seconds: whole % 60
|
|
54
|
+
};
|
|
55
|
+
case "hh_mm_ss": {
|
|
56
|
+
const hours = Math.floor(whole / 3600);
|
|
57
|
+
const minutes = Math.floor(whole % 3600 / 60);
|
|
58
|
+
const seconds = whole % 60;
|
|
59
|
+
return { days: 0, hours, minutes, seconds };
|
|
60
|
+
}
|
|
61
|
+
case "dd_hh_mm_ss": {
|
|
62
|
+
const days = Math.floor(whole / 86400);
|
|
63
|
+
const hours = Math.floor(whole % 86400 / 3600);
|
|
64
|
+
const minutes = Math.floor(whole % 3600 / 60);
|
|
65
|
+
const seconds = whole % 60;
|
|
66
|
+
return { days, hours, minutes, seconds };
|
|
67
|
+
}
|
|
68
|
+
default:
|
|
69
|
+
return { days: 0, hours: 0, minutes: 0, seconds: 0 };
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var clamp59 = (n) => Math.max(0, Math.min(59, Math.trunc(Number.isFinite(n) ? n : 0)));
|
|
73
|
+
var clampHour23 = (n) => Math.max(0, Math.min(23, Math.trunc(Number.isFinite(n) ? n : 0)));
|
|
74
|
+
var mergePartsForTimeFormat = (parts, format) => {
|
|
75
|
+
switch (format) {
|
|
76
|
+
case "mm_ss":
|
|
77
|
+
return Math.max(0, Math.trunc(Number.isFinite(parts.minutes) ? parts.minutes : 0)) * 60 + clamp59(parts.seconds);
|
|
78
|
+
case "hh_mm_ss":
|
|
79
|
+
return Math.max(0, Math.trunc(Number.isFinite(parts.hours) ? parts.hours : 0)) * 3600 + clamp59(parts.minutes) * 60 + clamp59(parts.seconds);
|
|
80
|
+
case "dd_hh_mm_ss":
|
|
81
|
+
return Math.max(0, Math.trunc(Number.isFinite(parts.days) ? parts.days : 0)) * 86400 + clampHour23(parts.hours) * 3600 + clamp59(parts.minutes) * 60 + clamp59(parts.seconds);
|
|
82
|
+
default:
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
var resolveCounterAnimationDurationMs = (opts) => {
|
|
87
|
+
if ((opts.displayKind ?? "number") === "time") {
|
|
88
|
+
return Math.max(0, Math.round(Math.abs(opts.endValue - opts.startValue) * 1e3));
|
|
89
|
+
}
|
|
90
|
+
return opts.durationMs ?? 3e3;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export { formatCounterAsTime, formatCounterLayerDisplay, formatCounterLayerValue, mergePartsForTimeFormat, resolveCounterAnimationDurationMs, splitSecondsForTimeFormat };
|
|
94
|
+
//# sourceMappingURL=counterLayer.js.map
|
|
95
|
+
//# sourceMappingURL=counterLayer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/counterLayer.ts"],"names":[],"mappings":"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","file":"counterLayer.js","sourcesContent":["import type { CounterDisplayKind, CounterTimeFormat } from '@getrheo/contracts/layers';\n\n/**\n * Pretty-print animated counter values for display (web + native).\n * `decimalPlaces` is clamped to 0–20. Trailing fractional zeros are trimmed\n * except when `decimalPlaces === 0` (integer rounding via `toFixed(0)`).\n */\nexport const formatCounterLayerValue = (n: number, decimalPlaces = 0): string => {\n if (!Number.isFinite(n)) return '';\n const p = Math.max(0, Math.min(20, Math.trunc(decimalPlaces)));\n const s = n.toFixed(p);\n if (p === 0) return s;\n const trimmed = s.replace(/\\.?0+$/, '');\n return trimmed === '' || trimmed === '-' ? '0' : trimmed;\n};\n\nconst pad2 = (n: number): string => String(n).padStart(2, '0');\n\n/**\n * Format a non-negative whole-second count as M:SS, H:MM:SS, or D:HH:MM:SS.\n * Fractional input uses `floor`; negative totals clamp to zero.\n */\nexport const formatCounterAsTime = (totalSeconds: number, format: CounterTimeFormat): string => {\n if (!Number.isFinite(totalSeconds)) return '';\n const whole = Math.max(0, Math.floor(totalSeconds));\n\n switch (format) {\n case 'mm_ss': {\n const minutes = Math.floor(whole / 60);\n const seconds = whole % 60;\n return `${minutes}:${pad2(seconds)}`;\n }\n case 'hh_mm_ss': {\n const hours = Math.floor(whole / 3600);\n const minutes = Math.floor((whole % 3600) / 60);\n const seconds = whole % 60;\n return `${hours}:${pad2(minutes)}:${pad2(seconds)}`;\n }\n case 'dd_hh_mm_ss': {\n const days = Math.floor(whole / 86400);\n const hours = Math.floor((whole % 86400) / 3600);\n const minutes = Math.floor((whole % 3600) / 60);\n const seconds = whole % 60;\n return `${days}:${pad2(hours)}:${pad2(minutes)}:${pad2(seconds)}`;\n }\n default:\n return '';\n }\n};\n\nexport type CounterLayerDisplayOpts = {\n displayKind?: CounterDisplayKind;\n decimalPlaces?: number;\n timeFormat?: CounterTimeFormat;\n};\n\n/** Routes to numeric or time formatting based on layer display settings. */\nexport const formatCounterLayerDisplay = (n: number, opts: CounterLayerDisplayOpts): string => {\n const kind = opts.displayKind ?? 'number';\n if (kind === 'time') {\n const tf = opts.timeFormat ?? 'mm_ss';\n return formatCounterAsTime(n, tf);\n }\n return formatCounterLayerValue(n, opts.decimalPlaces ?? 0);\n};\n\n/** Components for the counter inspector when editing time mode (all non‑negative integers). */\nexport type CounterTimeParts = {\n days: number;\n hours: number;\n minutes: number;\n seconds: number;\n};\n\nexport const splitSecondsForTimeFormat = (\n totalSeconds: number,\n format: CounterTimeFormat,\n): CounterTimeParts => {\n const whole = Math.max(0, Math.floor(Number.isFinite(totalSeconds) ? totalSeconds : 0));\n switch (format) {\n case 'mm_ss':\n return {\n days: 0,\n hours: 0,\n minutes: Math.floor(whole / 60),\n seconds: whole % 60,\n };\n case 'hh_mm_ss': {\n const hours = Math.floor(whole / 3600);\n const minutes = Math.floor((whole % 3600) / 60);\n const seconds = whole % 60;\n return { days: 0, hours, minutes, seconds };\n }\n case 'dd_hh_mm_ss': {\n const days = Math.floor(whole / 86400);\n const hours = Math.floor((whole % 86400) / 3600);\n const minutes = Math.floor((whole % 3600) / 60);\n const seconds = whole % 60;\n return { days, hours, minutes, seconds };\n }\n default:\n return { days: 0, hours: 0, minutes: 0, seconds: 0 };\n }\n};\n\nconst clamp59 = (n: number): number =>\n Math.max(0, Math.min(59, Math.trunc(Number.isFinite(n) ? n : 0)));\n\nconst clampHour23 = (n: number): number =>\n Math.max(0, Math.min(23, Math.trunc(Number.isFinite(n) ? n : 0)));\n\n/** Compose UI units into total seconds (matches {@link splitSecondsForTimeFormat}). */\nexport const mergePartsForTimeFormat = (parts: CounterTimeParts, format: CounterTimeFormat): number => {\n switch (format) {\n case 'mm_ss':\n return Math.max(0, Math.trunc(Number.isFinite(parts.minutes) ? parts.minutes : 0)) * 60 +\n clamp59(parts.seconds);\n case 'hh_mm_ss':\n return (\n Math.max(0, Math.trunc(Number.isFinite(parts.hours) ? parts.hours : 0)) * 3600 +\n clamp59(parts.minutes) * 60 +\n clamp59(parts.seconds)\n );\n case 'dd_hh_mm_ss':\n return (\n Math.max(0, Math.trunc(Number.isFinite(parts.days) ? parts.days : 0)) * 86400 +\n clampHour23(parts.hours) * 3600 +\n clamp59(parts.minutes) * 60 +\n clamp59(parts.seconds)\n );\n default:\n return 0;\n }\n};\n\n/**\n * Time mode advances one displayed second per real second over |end − start|.\n * Number mode uses authored `durationMs` (default 3000).\n */\nexport const resolveCounterAnimationDurationMs = (opts: {\n displayKind?: CounterDisplayKind;\n durationMs?: number;\n startValue: number;\n endValue: number;\n}): number => {\n if ((opts.displayKind ?? 'number') === 'time') {\n return Math.max(0, Math.round(Math.abs(opts.endValue - opts.startValue) * 1000));\n }\n return opts.durationMs ?? 3000;\n};\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { FlowManifest } from '@getrheo/contracts/manifest';
|
|
2
|
+
import { DecisionExpr, DecisionNode, FlowJumpTarget } from '@getrheo/contracts/decisions';
|
|
3
|
+
|
|
4
|
+
type DecisionEvaluationTelemetry = {
|
|
5
|
+
decisionNodeId: string;
|
|
6
|
+
/** Matched segment id, or null when no case matched (else branch). */
|
|
7
|
+
matchedCaseId: string | null;
|
|
8
|
+
clauseDigest: string;
|
|
9
|
+
};
|
|
10
|
+
declare const findDecisionNode: (manifest: FlowManifest, id: string) => DecisionNode | undefined;
|
|
11
|
+
declare const decisionTargetIds: (manifest: FlowManifest) => Set<string>;
|
|
12
|
+
/** Stable digest of the expression shape and literal predicate values (not runtime answers). */
|
|
13
|
+
declare const digestDecisionExpression: (expr: DecisionExpr) => string;
|
|
14
|
+
type EvalCtx = {
|
|
15
|
+
locale: string;
|
|
16
|
+
platform: string;
|
|
17
|
+
sdkAttributes: Record<string, unknown>;
|
|
18
|
+
responses: Record<string, unknown>;
|
|
19
|
+
};
|
|
20
|
+
declare const evaluateDecisionExpression: (expr: DecisionExpr, ctx: EvalCtx) => boolean;
|
|
21
|
+
declare const evaluateDecisionNode: (node: DecisionNode, ctx: EvalCtx) => {
|
|
22
|
+
matchedCaseId: string | null;
|
|
23
|
+
next: FlowJumpTarget;
|
|
24
|
+
clauseDigest: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export { type DecisionEvaluationTelemetry, decisionTargetIds, digestDecisionExpression, evaluateDecisionExpression, evaluateDecisionNode, findDecisionNode };
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// src/decisionEval.ts
|
|
2
|
+
var findDecisionNode = (manifest, id) => (manifest.decisionNodes ?? []).find((d) => d.id === id);
|
|
3
|
+
var decisionTargetIds = (manifest) => new Set((manifest.decisionNodes ?? []).map((d) => d.id));
|
|
4
|
+
var stableSerialize = (value) => {
|
|
5
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
6
|
+
if (Array.isArray(value)) return `[${value.map(stableSerialize).join(",")}]`;
|
|
7
|
+
const keys = Object.keys(value).sort();
|
|
8
|
+
const parts = keys.map((k) => `${JSON.stringify(k)}:${stableSerialize(value[k])}`);
|
|
9
|
+
return `{${parts.join(",")}}`;
|
|
10
|
+
};
|
|
11
|
+
var digestDecisionExpression = (expr) => {
|
|
12
|
+
const s = stableSerialize(expr);
|
|
13
|
+
let h = 5381;
|
|
14
|
+
for (let i = 0; i < s.length; i += 1) {
|
|
15
|
+
h = h * 33 ^ s.charCodeAt(i);
|
|
16
|
+
}
|
|
17
|
+
return `d${(h >>> 0).toString(16)}`;
|
|
18
|
+
};
|
|
19
|
+
var responseForField = (fieldKey, responses) => responses[fieldKey];
|
|
20
|
+
var normalizeResponseValue = (r) => {
|
|
21
|
+
if (!r || typeof r !== "object") return void 0;
|
|
22
|
+
const o = r;
|
|
23
|
+
switch (o.kind) {
|
|
24
|
+
case "choice":
|
|
25
|
+
return typeof o.choiceId === "string" ? o.choiceId : void 0;
|
|
26
|
+
case "multiChoice":
|
|
27
|
+
return Array.isArray(o.choiceIds) ? o.choiceIds : void 0;
|
|
28
|
+
case "text":
|
|
29
|
+
return typeof o.value === "string" ? o.value : void 0;
|
|
30
|
+
case "scale":
|
|
31
|
+
return typeof o.value === "number" ? o.value : void 0;
|
|
32
|
+
case "checkbox":
|
|
33
|
+
return typeof o.value === "boolean" ? o.value : void 0;
|
|
34
|
+
default:
|
|
35
|
+
return void 0;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var normalizeScalarForStringPred = (raw) => {
|
|
39
|
+
if (raw === void 0 || raw === null) return void 0;
|
|
40
|
+
if (typeof raw === "string") return raw;
|
|
41
|
+
if (typeof raw === "number" && Number.isFinite(raw)) return String(raw);
|
|
42
|
+
return void 0;
|
|
43
|
+
};
|
|
44
|
+
var normalizeNumber = (raw) => {
|
|
45
|
+
if (typeof raw !== "number" || !Number.isFinite(raw)) return void 0;
|
|
46
|
+
return raw;
|
|
47
|
+
};
|
|
48
|
+
var normalizeChoiceId = (raw) => typeof raw === "string" && raw.length > 0 ? raw : void 0;
|
|
49
|
+
var normalizeChoiceIds = (raw) => {
|
|
50
|
+
if (!Array.isArray(raw)) return void 0;
|
|
51
|
+
const ids = raw.filter((x) => typeof x === "string" && x.length > 0);
|
|
52
|
+
return ids;
|
|
53
|
+
};
|
|
54
|
+
var normalizeBoolean = (raw) => {
|
|
55
|
+
if (typeof raw === "boolean") return raw;
|
|
56
|
+
if (typeof raw === "number" && Number.isFinite(raw)) return raw !== 0;
|
|
57
|
+
if (typeof raw === "string") {
|
|
58
|
+
const s = raw.trim().toLowerCase();
|
|
59
|
+
if (s === "true" || s === "1" || s === "yes") return true;
|
|
60
|
+
if (s === "false" || s === "0" || s === "no") return false;
|
|
61
|
+
}
|
|
62
|
+
return void 0;
|
|
63
|
+
};
|
|
64
|
+
var resolveVariableValue = (variable, ctx) => {
|
|
65
|
+
if (variable.kind === "builtin") {
|
|
66
|
+
if (variable.name === "locale") return ctx.locale;
|
|
67
|
+
return ctx.platform;
|
|
68
|
+
}
|
|
69
|
+
if (variable.kind === "sdk") return ctx.sdkAttributes[variable.key];
|
|
70
|
+
const r = responseForField(variable.fieldKey, ctx.responses);
|
|
71
|
+
return normalizeResponseValue(r);
|
|
72
|
+
};
|
|
73
|
+
var evalStringPred = (left, pred) => {
|
|
74
|
+
switch (pred.op) {
|
|
75
|
+
case "eq":
|
|
76
|
+
return left === pred.value;
|
|
77
|
+
case "neq":
|
|
78
|
+
return left !== pred.value;
|
|
79
|
+
case "contains":
|
|
80
|
+
return left.includes(pred.value);
|
|
81
|
+
default:
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
var evalNumberPred = (left, pred) => {
|
|
86
|
+
switch (pred.op) {
|
|
87
|
+
case "eq":
|
|
88
|
+
return left === pred.value;
|
|
89
|
+
case "neq":
|
|
90
|
+
return left !== pred.value;
|
|
91
|
+
case "lt":
|
|
92
|
+
return left < pred.value;
|
|
93
|
+
case "lte":
|
|
94
|
+
return left <= pred.value;
|
|
95
|
+
case "gt":
|
|
96
|
+
return left > pred.value;
|
|
97
|
+
case "gte":
|
|
98
|
+
return left >= pred.value;
|
|
99
|
+
default:
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
var evalChoicePred = (choiceId, pred) => {
|
|
104
|
+
if (pred.op === "eq") return choiceId === pred.optionId;
|
|
105
|
+
return pred.optionIds.includes(choiceId);
|
|
106
|
+
};
|
|
107
|
+
var setIntersect = (a, b) => {
|
|
108
|
+
const bs = new Set(b);
|
|
109
|
+
return a.filter((x) => bs.has(x));
|
|
110
|
+
};
|
|
111
|
+
var evalBooleanPred = (left, pred) => {
|
|
112
|
+
if (pred.op === "eq") return left === pred.value;
|
|
113
|
+
return left !== pred.value;
|
|
114
|
+
};
|
|
115
|
+
var evalMultiPred = (selected, pred) => {
|
|
116
|
+
const required = pred.optionIds;
|
|
117
|
+
switch (pred.op) {
|
|
118
|
+
case "intersects":
|
|
119
|
+
return setIntersect(selected, required).length > 0;
|
|
120
|
+
case "contains_all": {
|
|
121
|
+
const sel = new Set(selected);
|
|
122
|
+
return required.every((id) => sel.has(id));
|
|
123
|
+
}
|
|
124
|
+
case "subset_of": {
|
|
125
|
+
const allow = new Set(required);
|
|
126
|
+
return selected.every((id) => allow.has(id));
|
|
127
|
+
}
|
|
128
|
+
default:
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
var evaluateDecisionExpression = (expr, ctx) => {
|
|
133
|
+
if (expr.kind === "empty") return false;
|
|
134
|
+
if (expr.kind === "group") {
|
|
135
|
+
if (expr.op === "and") {
|
|
136
|
+
for (const c of expr.children) {
|
|
137
|
+
if (!evaluateDecisionExpression(c, ctx)) return false;
|
|
138
|
+
}
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
for (const c of expr.children) {
|
|
142
|
+
if (evaluateDecisionExpression(c, ctx)) return true;
|
|
143
|
+
}
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
const raw = resolveVariableValue(expr.variable, ctx);
|
|
147
|
+
const { predicate } = expr;
|
|
148
|
+
switch (predicate.type) {
|
|
149
|
+
case "string": {
|
|
150
|
+
const s = normalizeScalarForStringPred(raw);
|
|
151
|
+
if (s === void 0) return false;
|
|
152
|
+
return evalStringPred(s, predicate.pred);
|
|
153
|
+
}
|
|
154
|
+
case "number": {
|
|
155
|
+
const n = normalizeNumber(raw);
|
|
156
|
+
if (n === void 0) return false;
|
|
157
|
+
return evalNumberPred(n, predicate.pred);
|
|
158
|
+
}
|
|
159
|
+
case "choice": {
|
|
160
|
+
const id = normalizeChoiceId(raw);
|
|
161
|
+
if (!id) return false;
|
|
162
|
+
return evalChoicePred(id, predicate.pred);
|
|
163
|
+
}
|
|
164
|
+
case "multi": {
|
|
165
|
+
const ids = normalizeChoiceIds(raw);
|
|
166
|
+
if (!ids) return false;
|
|
167
|
+
return evalMultiPred(ids, predicate.pred);
|
|
168
|
+
}
|
|
169
|
+
case "boolean": {
|
|
170
|
+
const b = normalizeBoolean(raw);
|
|
171
|
+
if (b === void 0) return false;
|
|
172
|
+
return evalBooleanPred(b, predicate.pred);
|
|
173
|
+
}
|
|
174
|
+
default:
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
var evaluateDecisionNode = (node, ctx) => {
|
|
179
|
+
for (const c of node.cases) {
|
|
180
|
+
if (evaluateDecisionExpression(c.expression, ctx)) {
|
|
181
|
+
return {
|
|
182
|
+
matchedCaseId: c.id,
|
|
183
|
+
next: c.next,
|
|
184
|
+
clauseDigest: digestDecisionExpression(c.expression)
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
matchedCaseId: null,
|
|
190
|
+
next: node.elseNext,
|
|
191
|
+
clauseDigest: "else"
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
export { decisionTargetIds, digestDecisionExpression, evaluateDecisionExpression, evaluateDecisionNode, findDecisionNode };
|
|
196
|
+
//# sourceMappingURL=decisionEval.js.map
|
|
197
|
+
//# sourceMappingURL=decisionEval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/decisionEval.ts"],"names":[],"mappings":"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","file":"decisionEval.js","sourcesContent":["import type { FlowManifest } from '@getrheo/contracts/manifest';\nimport type { DecisionExpr, DecisionNode, FlowJumpTarget } from '@getrheo/contracts/decisions';\n\nexport type DecisionEvaluationTelemetry = {\n decisionNodeId: string;\n /** Matched segment id, or null when no case matched (else branch). */\n matchedCaseId: string | null;\n clauseDigest: string;\n};\n\nexport const findDecisionNode = (manifest: FlowManifest, id: string): DecisionNode | undefined =>\n (manifest.decisionNodes ?? []).find((d) => d.id === id);\n\nexport const decisionTargetIds = (manifest: FlowManifest): Set<string> =>\n new Set((manifest.decisionNodes ?? []).map((d) => d.id));\n\nconst stableSerialize = (value: unknown): string => {\n if (value === null || typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(stableSerialize).join(',')}]`;\n const keys = Object.keys(value as Record<string, unknown>).sort();\n const parts = keys.map((k) => `${JSON.stringify(k)}:${stableSerialize((value as Record<string, unknown>)[k])}`);\n return `{${parts.join(',')}}`;\n};\n\n/** Stable digest of the expression shape and literal predicate values (not runtime answers). */\nexport const digestDecisionExpression = (expr: DecisionExpr): string => {\n const s = stableSerialize(expr);\n let h = 5381;\n for (let i = 0; i < s.length; i += 1) {\n h = (h * 33) ^ s.charCodeAt(i)!;\n }\n return `d${(h >>> 0).toString(16)}`;\n};\n\ntype EvalCtx = {\n locale: string;\n platform: string;\n sdkAttributes: Record<string, unknown>;\n responses: Record<string, unknown>;\n};\n\nconst responseForField = (\n fieldKey: string,\n responses: Record<string, unknown>,\n): unknown => responses[fieldKey];\n\nconst normalizeResponseValue = (r: unknown): unknown => {\n if (!r || typeof r !== 'object') return undefined;\n const o = r as Record<string, unknown>;\n switch (o.kind) {\n case 'choice':\n return typeof o.choiceId === 'string' ? o.choiceId : undefined;\n case 'multiChoice':\n return Array.isArray(o.choiceIds) ? o.choiceIds : undefined;\n case 'text':\n return typeof o.value === 'string' ? o.value : undefined;\n case 'scale':\n return typeof o.value === 'number' ? o.value : undefined;\n case 'checkbox':\n return typeof o.value === 'boolean' ? o.value : undefined;\n default:\n return undefined;\n }\n};\nconst normalizeScalarForStringPred = (raw: unknown): string | undefined => {\n if (raw === undefined || raw === null) return undefined;\n if (typeof raw === 'string') return raw;\n if (typeof raw === 'number' && Number.isFinite(raw)) return String(raw);\n return undefined;\n};\n\nconst normalizeNumber = (raw: unknown): number | undefined => {\n if (typeof raw !== 'number' || !Number.isFinite(raw)) return undefined;\n return raw;\n};\n\nconst normalizeChoiceId = (raw: unknown): string | undefined =>\n typeof raw === 'string' && raw.length > 0 ? raw : undefined;\n\nconst normalizeChoiceIds = (raw: unknown): string[] | undefined => {\n if (!Array.isArray(raw)) return undefined;\n const ids = raw.filter((x): x is string => typeof x === 'string' && x.length > 0);\n return ids;\n};\n\nconst normalizeBoolean = (raw: unknown): boolean | undefined => {\n if (typeof raw === 'boolean') return raw;\n if (typeof raw === 'number' && Number.isFinite(raw)) return raw !== 0;\n if (typeof raw === 'string') {\n const s = raw.trim().toLowerCase();\n if (s === 'true' || s === '1' || s === 'yes') return true;\n if (s === 'false' || s === '0' || s === 'no') return false;\n }\n return undefined;\n};\n\ntype PredicateVariable = Extract<DecisionExpr, { kind: 'predicate' }>['variable'];\n\nconst resolveVariableValue = (variable: PredicateVariable, ctx: EvalCtx): unknown => {\n if (variable.kind === 'builtin') {\n if (variable.name === 'locale') return ctx.locale;\n return ctx.platform;\n }\n if (variable.kind === 'sdk') return ctx.sdkAttributes[variable.key];\n const r = responseForField(variable.fieldKey, ctx.responses);\n return normalizeResponseValue(r);\n};\n\nconst evalStringPred = (left: string, pred: { op: string; value: string }): boolean => {\n switch (pred.op) {\n case 'eq':\n return left === pred.value;\n case 'neq':\n return left !== pred.value;\n case 'contains':\n return left.includes(pred.value);\n default:\n return false;\n }\n};\n\nconst evalNumberPred = (left: number, pred: { op: string; value: number }): boolean => {\n switch (pred.op) {\n case 'eq':\n return left === pred.value;\n case 'neq':\n return left !== pred.value;\n case 'lt':\n return left < pred.value;\n case 'lte':\n return left <= pred.value;\n case 'gt':\n return left > pred.value;\n case 'gte':\n return left >= pred.value;\n default:\n return false;\n }\n};\n\nconst evalChoicePred = (\n choiceId: string,\n pred:\n | { op: 'eq'; optionId: string }\n | { op: 'one_of'; optionIds: string[] },\n): boolean => {\n if (pred.op === 'eq') return choiceId === pred.optionId;\n return pred.optionIds.includes(choiceId);\n};\n\nconst setIntersect = (a: string[], b: string[]): string[] => {\n const bs = new Set(b);\n return a.filter((x) => bs.has(x));\n};\n\nconst evalBooleanPred = (\n left: boolean,\n pred: { op: 'eq' | 'neq'; value: boolean },\n): boolean => {\n if (pred.op === 'eq') return left === pred.value;\n return left !== pred.value;\n};\n\nconst evalMultiPred = (\n selected: string[],\n pred:\n | { op: 'intersects'; optionIds: string[] }\n | { op: 'contains_all'; optionIds: string[] }\n | { op: 'subset_of'; optionIds: string[] },\n): boolean => {\n const required = pred.optionIds;\n switch (pred.op) {\n case 'intersects':\n return setIntersect(selected, required).length > 0;\n case 'contains_all': {\n const sel = new Set(selected);\n return required.every((id) => sel.has(id));\n }\n case 'subset_of': {\n const allow = new Set(required);\n return selected.every((id) => allow.has(id));\n }\n default:\n return false;\n }\n};\n\nexport const evaluateDecisionExpression = (expr: DecisionExpr, ctx: EvalCtx): boolean => {\n if (expr.kind === 'empty') return false;\n if (expr.kind === 'group') {\n if (expr.op === 'and') {\n for (const c of expr.children) {\n if (!evaluateDecisionExpression(c, ctx)) return false;\n }\n return true;\n }\n for (const c of expr.children) {\n if (evaluateDecisionExpression(c, ctx)) return true;\n }\n return false;\n }\n\n const raw = resolveVariableValue(expr.variable, ctx);\n const { predicate } = expr;\n\n switch (predicate.type) {\n case 'string': {\n const s = normalizeScalarForStringPred(raw);\n if (s === undefined) return false;\n return evalStringPred(s, predicate.pred);\n }\n case 'number': {\n const n = normalizeNumber(raw);\n if (n === undefined) return false;\n return evalNumberPred(n, predicate.pred);\n }\n case 'choice': {\n const id = normalizeChoiceId(raw);\n if (!id) return false;\n return evalChoicePred(id, predicate.pred);\n }\n case 'multi': {\n const ids = normalizeChoiceIds(raw);\n if (!ids) return false;\n return evalMultiPred(ids, predicate.pred);\n }\n case 'boolean': {\n const b = normalizeBoolean(raw);\n if (b === undefined) return false;\n return evalBooleanPred(b, predicate.pred);\n }\n default:\n return false;\n }\n};\n\nexport const evaluateDecisionNode = (\n node: DecisionNode,\n ctx: EvalCtx,\n): { matchedCaseId: string | null; next: FlowJumpTarget; clauseDigest: string } => {\n for (const c of node.cases) {\n if (evaluateDecisionExpression(c.expression, ctx)) {\n return {\n matchedCaseId: c.id,\n next: c.next,\n clauseDigest: digestDecisionExpression(c.expression),\n };\n }\n }\n return {\n matchedCaseId: null,\n next: node.elseNext,\n clauseDigest: 'else',\n };\n};\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { DropShadow } from '@getrheo/contracts/layers';
|
|
2
|
+
import { Theme } from '@getrheo/contracts/manifest';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* CSS `boxShadow` string from structured shadow. Returns `undefined` when
|
|
6
|
+
* `shadow` is absent or empty so callers can omit the property.
|
|
7
|
+
*/
|
|
8
|
+
declare const dropShadowToBoxShadow: (sh: DropShadow | undefined, theme: Theme | undefined, palette: "light" | "dark") => string | undefined;
|
|
9
|
+
/** Web `CSSProperties` fragment for `boxShadow`. */
|
|
10
|
+
declare const dropShadowToWebStyle: (sh: DropShadow | undefined, theme: Theme | undefined, palette: "light" | "dark") => {
|
|
11
|
+
boxShadow?: string;
|
|
12
|
+
};
|
|
13
|
+
/** React Native–compatible shadow props (no `react-native` import here). */
|
|
14
|
+
type NativeDropShadowStyle = {
|
|
15
|
+
shadowOffset?: {
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
};
|
|
19
|
+
shadowOpacity?: number;
|
|
20
|
+
shadowRadius?: number;
|
|
21
|
+
shadowColor?: string;
|
|
22
|
+
elevation?: number;
|
|
23
|
+
};
|
|
24
|
+
declare const dropShadowToNativeStyle: (sh: DropShadow | undefined, theme: Theme | undefined, palette: "light" | "dark") => NativeDropShadowStyle;
|
|
25
|
+
|
|
26
|
+
export { type NativeDropShadowStyle, dropShadowToBoxShadow, dropShadowToNativeStyle, dropShadowToWebStyle };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import '@getrheo/contracts/localized';
|
|
2
|
+
import '@getrheo/contracts/layers';
|
|
3
|
+
|
|
4
|
+
// src/layers.ts
|
|
5
|
+
var resolveTokens = (theme, value) => {
|
|
6
|
+
if (value === void 0) return value;
|
|
7
|
+
if (typeof value !== "string" || !value.startsWith("$")) return value;
|
|
8
|
+
const key = value.slice(1);
|
|
9
|
+
const literal = theme?.[key];
|
|
10
|
+
if (typeof literal === "string") return literal;
|
|
11
|
+
return value;
|
|
12
|
+
};
|
|
13
|
+
var resolveThemedColor = (theme, palette, value) => {
|
|
14
|
+
if (value === void 0) return void 0;
|
|
15
|
+
if (typeof value === "string") return resolveTokens(theme, value);
|
|
16
|
+
const raw = palette === "dark" ? value.dark ?? value.light : value.light ?? value.dark;
|
|
17
|
+
if (raw === void 0) return void 0;
|
|
18
|
+
return resolveTokens(theme, raw);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// src/dropShadow.ts
|
|
22
|
+
var clamp01 = (n) => Math.max(0, Math.min(1, n));
|
|
23
|
+
var hexToRgba = (hex, alpha) => {
|
|
24
|
+
const raw = hex.trim().replace(/^#/, "");
|
|
25
|
+
if (!/^([0-9a-f]{3}|[0-9a-f]{6})$/i.test(raw)) return `rgba(0,0,0,${clamp01(alpha)})`;
|
|
26
|
+
const full = raw.length === 3 ? raw.split("").map((c) => c + c).join("") : raw;
|
|
27
|
+
const r = parseInt(full.slice(0, 2), 16);
|
|
28
|
+
const g = parseInt(full.slice(2, 4), 16);
|
|
29
|
+
const b = parseInt(full.slice(4, 6), 16);
|
|
30
|
+
return `rgba(${r},${g},${b},${clamp01(alpha)})`;
|
|
31
|
+
};
|
|
32
|
+
var colorWithOpacity = (resolved, opacity) => {
|
|
33
|
+
const o = clamp01(opacity);
|
|
34
|
+
if (!resolved) return `rgba(0,0,0,${o})`;
|
|
35
|
+
const t = resolved.trim();
|
|
36
|
+
if (t.startsWith("#")) return hexToRgba(t, o);
|
|
37
|
+
const m = t.match(/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/i);
|
|
38
|
+
if (m) return `rgba(${m[1]},${m[2]},${m[3]},${o})`;
|
|
39
|
+
return t;
|
|
40
|
+
};
|
|
41
|
+
var shadowHasAnyField = (sh) => sh !== void 0 && Object.values(sh).some((v) => v !== void 0);
|
|
42
|
+
var dropShadowToBoxShadow = (sh, theme, palette) => {
|
|
43
|
+
if (!shadowHasAnyField(sh)) return void 0;
|
|
44
|
+
const ox = sh.offsetX ?? 0;
|
|
45
|
+
const oy = sh.offsetY ?? 2;
|
|
46
|
+
const blur = sh.blur ?? 8;
|
|
47
|
+
const spread = sh.spread ?? 0;
|
|
48
|
+
const opacity = sh.opacity ?? 0.25;
|
|
49
|
+
const base = resolveThemedColor(theme, palette, sh.color);
|
|
50
|
+
const color = colorWithOpacity(base, opacity);
|
|
51
|
+
return `${ox}px ${oy}px ${blur}px ${spread}px ${color}`;
|
|
52
|
+
};
|
|
53
|
+
var dropShadowToWebStyle = (sh, theme, palette) => {
|
|
54
|
+
const boxShadow = dropShadowToBoxShadow(sh, theme, palette);
|
|
55
|
+
return boxShadow ? { boxShadow } : {};
|
|
56
|
+
};
|
|
57
|
+
var dropShadowToNativeStyle = (sh, theme, palette) => {
|
|
58
|
+
if (!shadowHasAnyField(sh)) return {};
|
|
59
|
+
const ox = sh.offsetX ?? 0;
|
|
60
|
+
const oy = sh.offsetY ?? 2;
|
|
61
|
+
const blur = sh.blur ?? 8;
|
|
62
|
+
const opacity = sh.opacity ?? 0.25;
|
|
63
|
+
const base = resolveThemedColor(theme, palette, sh.color);
|
|
64
|
+
const color = colorWithOpacity(base, opacity);
|
|
65
|
+
return {
|
|
66
|
+
shadowOffset: { width: ox, height: oy },
|
|
67
|
+
shadowOpacity: 1,
|
|
68
|
+
shadowRadius: blur,
|
|
69
|
+
shadowColor: color,
|
|
70
|
+
elevation: Math.min(24, Math.max(0, Math.round(blur / 2 + Math.abs(oy))))
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export { dropShadowToBoxShadow, dropShadowToNativeStyle, dropShadowToWebStyle };
|
|
75
|
+
//# sourceMappingURL=dropShadow.js.map
|
|
76
|
+
//# sourceMappingURL=dropShadow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/layers.ts","../src/dropShadow.ts"],"names":[],"mappings":"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","file":"dropShadow.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 { DropShadow } from '@getrheo/contracts/layers';\nimport type { Theme } from '@getrheo/contracts/manifest';\nimport { resolveThemedColor } from './layers';\n\nconst clamp01 = (n: number) => Math.max(0, Math.min(1, n));\n\nconst hexToRgba = (hex: string, alpha: number): string => {\n const raw = hex.trim().replace(/^#/, '');\n if (!/^([0-9a-f]{3}|[0-9a-f]{6})$/i.test(raw)) return `rgba(0,0,0,${clamp01(alpha)})`;\n const full =\n raw.length === 3\n ? raw\n .split('')\n .map((c) => c + c)\n .join('')\n : raw;\n const r = parseInt(full.slice(0, 2), 16);\n const g = parseInt(full.slice(2, 4), 16);\n const b = parseInt(full.slice(4, 6), 16);\n return `rgba(${r},${g},${b},${clamp01(alpha)})`;\n};\n\nconst colorWithOpacity = (resolved: string | undefined, opacity: number): string => {\n const o = clamp01(opacity);\n if (!resolved) return `rgba(0,0,0,${o})`;\n const t = resolved.trim();\n if (t.startsWith('#')) return hexToRgba(t, o);\n const m = t.match(/^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/i);\n if (m) return `rgba(${m[1]},${m[2]},${m[3]},${o})`;\n return t;\n};\n\nconst shadowHasAnyField = (sh: DropShadow | undefined): boolean =>\n sh !== undefined && Object.values(sh).some((v) => v !== undefined);\n\n/**\n * CSS `boxShadow` string from structured shadow. Returns `undefined` when\n * `shadow` is absent or empty so callers can omit the property.\n */\nexport const dropShadowToBoxShadow = (\n sh: DropShadow | undefined,\n theme: Theme | undefined,\n palette: 'light' | 'dark',\n): string | undefined => {\n if (!shadowHasAnyField(sh)) return undefined;\n const ox = sh!.offsetX ?? 0;\n const oy = sh!.offsetY ?? 2;\n const blur = sh!.blur ?? 8;\n const spread = sh!.spread ?? 0;\n const opacity = sh!.opacity ?? 0.25;\n const base = resolveThemedColor(theme, palette, sh!.color);\n const color = colorWithOpacity(base, opacity);\n return `${ox}px ${oy}px ${blur}px ${spread}px ${color}`;\n};\n\n/** Web `CSSProperties` fragment for `boxShadow`. */\nexport const dropShadowToWebStyle = (\n sh: DropShadow | undefined,\n theme: Theme | undefined,\n palette: 'light' | 'dark',\n): { boxShadow?: string } => {\n const boxShadow = dropShadowToBoxShadow(sh, theme, palette);\n return boxShadow ? { boxShadow } : {};\n};\n\n/** React Native–compatible shadow props (no `react-native` import here). */\nexport type NativeDropShadowStyle = {\n shadowOffset?: { width: number; height: number };\n shadowOpacity?: number;\n shadowRadius?: number;\n shadowColor?: string;\n elevation?: number;\n};\n\nexport const dropShadowToNativeStyle = (\n sh: DropShadow | undefined,\n theme: Theme | undefined,\n palette: 'light' | 'dark',\n): NativeDropShadowStyle => {\n if (!shadowHasAnyField(sh)) return {};\n const ox = sh!.offsetX ?? 0;\n const oy = sh!.offsetY ?? 2;\n const blur = sh!.blur ?? 8;\n const opacity = sh!.opacity ?? 0.25;\n const base = resolveThemedColor(theme, palette, sh!.color);\n const color = colorWithOpacity(base, opacity);\n return {\n shadowOffset: { width: ox, height: oy },\n shadowOpacity: 1,\n shadowRadius: blur,\n shadowColor: color,\n elevation: Math.min(24, Math.max(0, Math.round(blur / 2 + Math.abs(oy)))),\n };\n};\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type ValidateEmailPasswordAuthArgs = {
|
|
2
|
+
mode: 'sign_in' | 'sign_up';
|
|
3
|
+
email: string;
|
|
4
|
+
password: string;
|
|
5
|
+
confirmPassword: string;
|
|
6
|
+
minPasswordLength: number;
|
|
7
|
+
};
|
|
8
|
+
type ValidateEmailPasswordAuthResult = {
|
|
9
|
+
ok: true;
|
|
10
|
+
} | {
|
|
11
|
+
ok: false;
|
|
12
|
+
message: string;
|
|
13
|
+
};
|
|
14
|
+
declare const validateEmailPasswordAuthFields: (args: ValidateEmailPasswordAuthArgs) => ValidateEmailPasswordAuthResult;
|
|
15
|
+
|
|
16
|
+
export { type ValidateEmailPasswordAuthArgs, type ValidateEmailPasswordAuthResult, validateEmailPasswordAuthFields };
|