@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.
Files changed (126) hide show
  1. package/dist/agentPrompt/index.d.ts +72 -0
  2. package/dist/agentPrompt/index.js +739 -0
  3. package/dist/agentPrompt/index.js.map +1 -0
  4. package/dist/aiFlowGenerationMerge.d.ts +32 -0
  5. package/dist/aiFlowGenerationMerge.js +120 -0
  6. package/dist/aiFlowGenerationMerge.js.map +1 -0
  7. package/dist/animations.d.ts +110 -0
  8. package/dist/animations.js +312 -0
  9. package/dist/animations.js.map +1 -0
  10. package/dist/assignment.d.ts +7 -0
  11. package/dist/assignment.js +25 -0
  12. package/dist/assignment.js.map +1 -0
  13. package/dist/brandGradient.d.ts +57 -0
  14. package/dist/brandGradient.js +137 -0
  15. package/dist/brandGradient.js.map +1 -0
  16. package/dist/brandGradientManifestIssues.d.ts +11 -0
  17. package/dist/brandGradientManifestIssues.js +302 -0
  18. package/dist/brandGradientManifestIssues.js.map +1 -0
  19. package/dist/buildFlowPreview.d.ts +7 -0
  20. package/dist/buildFlowPreview.js +81 -0
  21. package/dist/buildFlowPreview.js.map +1 -0
  22. package/dist/buttonVariantChrome.d.ts +26 -0
  23. package/dist/buttonVariantChrome.js +59 -0
  24. package/dist/buttonVariantChrome.js.map +1 -0
  25. package/dist/checkboxGlyphStyle.d.ts +31 -0
  26. package/dist/checkboxGlyphStyle.js +241 -0
  27. package/dist/checkboxGlyphStyle.js.map +1 -0
  28. package/dist/choiceOptionSelection.d.ts +11 -0
  29. package/dist/choiceOptionSelection.js +120 -0
  30. package/dist/choiceOptionSelection.js.map +1 -0
  31. package/dist/colorAlpha.d.ts +8 -0
  32. package/dist/colorAlpha.js +48 -0
  33. package/dist/colorAlpha.js.map +1 -0
  34. package/dist/counterLayer.d.ts +42 -0
  35. package/dist/counterLayer.js +95 -0
  36. package/dist/counterLayer.js.map +1 -0
  37. package/dist/decisionEval.d.ts +27 -0
  38. package/dist/decisionEval.js +197 -0
  39. package/dist/decisionEval.js.map +1 -0
  40. package/dist/dropShadow.d.ts +26 -0
  41. package/dist/dropShadow.js +76 -0
  42. package/dist/dropShadow.js.map +1 -0
  43. package/dist/emailPasswordAuthValidation.d.ts +16 -0
  44. package/dist/emailPasswordAuthValidation.js +25 -0
  45. package/dist/emailPasswordAuthValidation.js.map +1 -0
  46. package/dist/flowBuilderRules.d.ts +15 -0
  47. package/dist/flowBuilderRules.js +368 -0
  48. package/dist/flowBuilderRules.js.map +1 -0
  49. package/dist/flowGraph.d.ts +19 -0
  50. package/dist/flowGraph.js +373 -0
  51. package/dist/flowGraph.js.map +1 -0
  52. package/dist/hyperlinkLabel.d.ts +19 -0
  53. package/dist/hyperlinkLabel.js +232 -0
  54. package/dist/hyperlinkLabel.js.map +1 -0
  55. package/dist/index.d.ts +48 -0
  56. package/dist/index.js +4200 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/interpolateTemplate.d.ts +44 -0
  59. package/dist/interpolateTemplate.js +188 -0
  60. package/dist/interpolateTemplate.js.map +1 -0
  61. package/dist/layerRotate.d.ts +10 -0
  62. package/dist/layerRotate.js +9 -0
  63. package/dist/layerRotate.js.map +1 -0
  64. package/dist/layerTypography.d.ts +36 -0
  65. package/dist/layerTypography.js +68 -0
  66. package/dist/layerTypography.js.map +1 -0
  67. package/dist/layers.d.ts +69 -0
  68. package/dist/layers.js +257 -0
  69. package/dist/layers.js.map +1 -0
  70. package/dist/layout/index.d.ts +57 -0
  71. package/dist/layout/index.js +151 -0
  72. package/dist/layout/index.js.map +1 -0
  73. package/dist/manifestBillingSlice.d.ts +17 -0
  74. package/dist/manifestBillingSlice.js +102 -0
  75. package/dist/manifestBillingSlice.js.map +1 -0
  76. package/dist/prepareAiGeneratedScreen.d.ts +17 -0
  77. package/dist/prepareAiGeneratedScreen.js +99 -0
  78. package/dist/prepareAiGeneratedScreen.js.map +1 -0
  79. package/dist/publish-exports.json +166 -0
  80. package/dist/responsive/breakpoints.d.ts +34 -0
  81. package/dist/responsive/breakpoints.js +52 -0
  82. package/dist/responsive/breakpoints.js.map +1 -0
  83. package/dist/responsive/index.d.ts +8 -0
  84. package/dist/responsive/index.js +307 -0
  85. package/dist/responsive/index.js.map +1 -0
  86. package/dist/responsive/layerResolve.d.ts +43 -0
  87. package/dist/responsive/layerResolve.js +168 -0
  88. package/dist/responsive/layerResolve.js.map +1 -0
  89. package/dist/responsive/merge.d.ts +19 -0
  90. package/dist/responsive/merge.js +74 -0
  91. package/dist/responsive/merge.js.map +1 -0
  92. package/dist/responsive/previewSafeAreaInsets.d.ts +14 -0
  93. package/dist/responsive/previewSafeAreaInsets.js +24 -0
  94. package/dist/responsive/previewSafeAreaInsets.js.map +1 -0
  95. package/dist/responsive/screenContainerResolve.d.ts +11 -0
  96. package/dist/responsive/screenContainerResolve.js +122 -0
  97. package/dist/responsive/screenContainerResolve.js.map +1 -0
  98. package/dist/responsive/screenShellInsets.d.ts +11 -0
  99. package/dist/responsive/screenShellInsets.js +26 -0
  100. package/dist/responsive/screenShellInsets.js.map +1 -0
  101. package/dist/restingMotion.d.ts +167 -0
  102. package/dist/restingMotion.js +484 -0
  103. package/dist/restingMotion.js.map +1 -0
  104. package/dist/rheoAgentManifestMerge.d.ts +33 -0
  105. package/dist/rheoAgentManifestMerge.js +55 -0
  106. package/dist/rheoAgentManifestMerge.js.map +1 -0
  107. package/dist/scaleInputStyle.d.ts +35 -0
  108. package/dist/scaleInputStyle.js +77 -0
  109. package/dist/scaleInputStyle.js.map +1 -0
  110. package/dist/scaleValidation.d.ts +9 -0
  111. package/dist/scaleValidation.js +21 -0
  112. package/dist/scaleValidation.js.map +1 -0
  113. package/dist/stateMachine.d.ts +105 -0
  114. package/dist/stateMachine.js +674 -0
  115. package/dist/stateMachine.js.map +1 -0
  116. package/dist/stepResponse-BXgoZ7o-.d.ts +112 -0
  117. package/dist/textInputValidation.d.ts +14 -0
  118. package/dist/textInputValidation.js +46 -0
  119. package/dist/textInputValidation.js.map +1 -0
  120. package/dist/translationPlaceholders.d.ts +9 -0
  121. package/dist/translationPlaceholders.js +52 -0
  122. package/dist/translationPlaceholders.js.map +1 -0
  123. package/dist/validation.d.ts +31 -0
  124. package/dist/validation.js +233 -0
  125. package/dist/validation.js.map +1 -0
  126. package/package.json +242 -0
@@ -0,0 +1,19 @@
1
+ import { StyleBreakpointKey } from './breakpoints.js';
2
+
3
+ /**
4
+ * Deep-merge style-like objects: nested plain objects merge per-key; scalars
5
+ * and arrays replace. Suitable for padding/margin/border/shadow objects.
6
+ */
7
+ declare const deepMergeStyle: <T extends Record<string, unknown>>(base: T | undefined, ...overrides: (Partial<T> | undefined)[]) => T | undefined;
8
+ /**
9
+ * Mobile-first merge: `base` applies below `sm`; each breakpoint partial stacks
10
+ * from `sm` through the bucket implied by `widthPx`.
11
+ */
12
+ declare const mergeResponsivePartial: <T extends Record<string, unknown>>(base: Partial<T> | undefined, breakpoints: Partial<Record<StyleBreakpointKey, Partial<T>>> | undefined, widthPx: number) => Partial<T> | undefined;
13
+ /**
14
+ * Merge breakpoint partials up to and including `bucket` (not using viewport width).
15
+ * Use when editing a specific bucket's effective preview.
16
+ */
17
+ declare const mergeResponsivePartialUpToBucket: <T extends Record<string, unknown>>(base: Partial<T> | undefined, breakpoints: Partial<Record<StyleBreakpointKey, Partial<T>>> | undefined, bucket: StyleBreakpointKey | "default") => Partial<T> | undefined;
18
+
19
+ export { deepMergeStyle, mergeResponsivePartial, mergeResponsivePartialUpToBucket };
@@ -0,0 +1,74 @@
1
+ // src/responsive/breakpoints.ts
2
+ var TAILWIND_DEFAULT_BREAKPOINTS = {
3
+ sm: 640,
4
+ md: 768,
5
+ lg: 1024,
6
+ xl: 1280,
7
+ "2xl": 1536
8
+ };
9
+ var STYLE_BREAKPOINT_MERGE_ORDER = ["sm", "md", "lg", "xl", "2xl"];
10
+ var getScreenSizeBucketForWidth = (width) => {
11
+ const { sm, md, lg, xl, "2xl": xxl } = TAILWIND_DEFAULT_BREAKPOINTS;
12
+ if (width < sm) return "default";
13
+ if (width < md) return "sm";
14
+ if (width < lg) return "md";
15
+ if (width < xl) return "lg";
16
+ if (width < xxl) return "xl";
17
+ return "2xl";
18
+ };
19
+ var getActiveStyleBreakpointChain = (widthPx) => {
20
+ const bucket = getScreenSizeBucketForWidth(widthPx);
21
+ if (bucket === "default") return [];
22
+ const idx = STYLE_BREAKPOINT_MERGE_ORDER.indexOf(bucket);
23
+ if (idx < 0) return [];
24
+ return STYLE_BREAKPOINT_MERGE_ORDER.slice(0, idx + 1);
25
+ };
26
+
27
+ // src/responsive/merge.ts
28
+ var isPlainObject = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
29
+ var deepMergeStyle = (base, ...overrides) => {
30
+ let acc = base ? { ...base } : void 0;
31
+ for (const o of overrides) {
32
+ if (!o) continue;
33
+ acc = acc ?? {};
34
+ for (const [k, v] of Object.entries(o)) {
35
+ if (v === void 0) continue;
36
+ const prev = acc[k];
37
+ if (isPlainObject(v) && isPlainObject(prev)) {
38
+ const merged = deepMergeStyle(prev, v);
39
+ if (merged !== void 0) acc[k] = merged;
40
+ } else {
41
+ acc[k] = v;
42
+ }
43
+ }
44
+ }
45
+ return acc;
46
+ };
47
+ var mergeResponsivePartial = (base, breakpoints, widthPx) => {
48
+ const chain = getActiveStyleBreakpointChain(widthPx);
49
+ if (chain.length === 0) return base ? { ...base } : void 0;
50
+ let acc = base ? { ...base } : void 0;
51
+ for (const key of chain) {
52
+ const patch = breakpoints?.[key];
53
+ if (!patch) continue;
54
+ acc = deepMergeStyle(acc, patch);
55
+ }
56
+ return acc;
57
+ };
58
+ var mergeResponsivePartialUpToBucket = (base, breakpoints, bucket) => {
59
+ if (bucket === "default") return base ? { ...base } : void 0;
60
+ const end = STYLE_BREAKPOINT_MERGE_ORDER.indexOf(bucket);
61
+ if (end < 0) return base ? { ...base } : void 0;
62
+ let acc = base ? { ...base } : void 0;
63
+ for (let i = 0; i <= end; i++) {
64
+ const key = STYLE_BREAKPOINT_MERGE_ORDER[i];
65
+ const patch = breakpoints?.[key];
66
+ if (!patch) continue;
67
+ acc = deepMergeStyle(acc, patch);
68
+ }
69
+ return acc;
70
+ };
71
+
72
+ export { deepMergeStyle, mergeResponsivePartial, mergeResponsivePartialUpToBucket };
73
+ //# sourceMappingURL=merge.js.map
74
+ //# sourceMappingURL=merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/responsive/breakpoints.ts","../../src/responsive/merge.ts"],"names":[],"mappings":"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","file":"merge.js","sourcesContent":["/**\n * Tailwind CSS default `screens` min-width values (px). Single source of truth\n * for preview buckets, manifest breakpoints, and runtime style resolution.\n *\n * @see https://tailwindcss.com/docs/screens\n */\nexport const TAILWIND_DEFAULT_BREAKPOINTS = {\n sm: 640,\n md: 768,\n lg: 1024,\n xl: 1280,\n '2xl': 1536,\n} as const;\n\n/** Viewport classification used by preview UI and editing scope. */\nexport type ScreenSizeBucket = 'default' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n\n/** Ordered keys stored on layers (`styleBreakpoints`) and merged mobile-first. */\nexport const STYLE_BREAKPOINT_MERGE_ORDER = ['sm', 'md', 'lg', 'xl', '2xl'] as const;\nexport type StyleBreakpointKey = (typeof STYLE_BREAKPOINT_MERGE_ORDER)[number];\n\nexport const SCREEN_SIZE_BUCKET_ORDER: readonly ScreenSizeBucket[] = [\n 'default',\n 'sm',\n 'md',\n 'lg',\n 'xl',\n '2xl',\n] as const;\n\n/** Buckets shown in the flow builder inspector (xl / 2xl omitted from authoring UI). */\nexport const BUILDER_INSPECTOR_BUCKET_ORDER: readonly ScreenSizeBucket[] = [\n 'default',\n 'sm',\n 'md',\n 'lg',\n] as const;\n\n/** Human-readable bucket titles; ranges lie between consecutive breakpoints. */\nexport const SCREEN_SIZE_BUCKET_LABEL: Record<ScreenSizeBucket, string> = {\n default: 'Default (< 640px)',\n sm: 'sm (640–767px)',\n md: 'md (768–1023px)',\n lg: 'lg (1024–1279px)',\n xl: 'xl (1280–1535px)',\n '2xl': '2xl (1536px+)',\n};\n\n/** Fallback viewport width when no `previewWidthPx` is passed (simulator / static previews). */\nexport const DEFAULT_PREVIEW_VIEWPORT_WIDTH_PX = 390;\n\n/** Maps viewport width (CSS px) to the Tailwind viewport bucket. */\nexport const getScreenSizeBucketForWidth = (width: number): ScreenSizeBucket => {\n const { sm, md, lg, xl, '2xl': xxl } = TAILWIND_DEFAULT_BREAKPOINTS;\n if (width < sm) return 'default';\n if (width < md) return 'sm';\n if (width < lg) return 'md';\n if (width < xl) return 'lg';\n if (width < xxl) return 'xl';\n return '2xl';\n};\n\n/**\n * Breakpoint keys whose partials apply at this width (mobile-first), e.g.\n * width 800 → `['sm','md']`.\n */\nexport const getActiveStyleBreakpointChain = (widthPx: number): StyleBreakpointKey[] => {\n const bucket = getScreenSizeBucketForWidth(widthPx);\n if (bucket === 'default') return [];\n const idx = STYLE_BREAKPOINT_MERGE_ORDER.indexOf(bucket as StyleBreakpointKey);\n if (idx < 0) return [];\n return STYLE_BREAKPOINT_MERGE_ORDER.slice(0, idx + 1) as StyleBreakpointKey[];\n};\n","import {\n STYLE_BREAKPOINT_MERGE_ORDER,\n getActiveStyleBreakpointChain,\n} from './breakpoints';\nimport type { StyleBreakpointKey } from './breakpoints';\n\nconst isPlainObject = (v: unknown): v is Record<string, unknown> =>\n v !== null && typeof v === 'object' && !Array.isArray(v);\n\n/**\n * Deep-merge style-like objects: nested plain objects merge per-key; scalars\n * and arrays replace. Suitable for padding/margin/border/shadow objects.\n */\nexport const deepMergeStyle = <T extends Record<string, unknown>>(\n base: T | undefined,\n ...overrides: (Partial<T> | undefined)[]\n): T | undefined => {\n let acc: T | undefined = base ? ({ ...base } as T) : undefined;\n for (const o of overrides) {\n if (!o) continue;\n acc = acc ?? ({} as T);\n for (const [k, v] of Object.entries(o) as [keyof T, T[keyof T] | undefined][]) {\n if (v === undefined) continue;\n const prev = acc[k as keyof T] as unknown;\n if (isPlainObject(v) && isPlainObject(prev)) {\n const merged = deepMergeStyle(prev as Record<string, unknown>, v as Partial<T>);\n if (merged !== undefined) (acc as Record<string, unknown>)[k as string] = merged;\n } else {\n (acc as Record<string, unknown>)[k as string] = v as unknown;\n }\n }\n }\n return acc;\n};\n\n/**\n * Mobile-first merge: `base` applies below `sm`; each breakpoint partial stacks\n * from `sm` through the bucket implied by `widthPx`.\n */\nexport const mergeResponsivePartial = <T extends Record<string, unknown>>(\n base: Partial<T> | undefined,\n breakpoints: Partial<Record<StyleBreakpointKey, Partial<T>>> | undefined,\n widthPx: number,\n): Partial<T> | undefined => {\n const chain = getActiveStyleBreakpointChain(widthPx);\n if (chain.length === 0) return base ? { ...base } : undefined;\n let acc = base ? ({ ...base } as Partial<T>) : undefined;\n for (const key of chain) {\n const patch = breakpoints?.[key];\n if (!patch) continue;\n acc = deepMergeStyle(acc as Record<string, unknown> | undefined, patch as Partial<T>) as\n | Partial<T>\n | undefined;\n }\n return acc;\n};\n\n/**\n * Merge breakpoint partials up to and including `bucket` (not using viewport width).\n * Use when editing a specific bucket's effective preview.\n */\nexport const mergeResponsivePartialUpToBucket = <T extends Record<string, unknown>>(\n base: Partial<T> | undefined,\n breakpoints: Partial<Record<StyleBreakpointKey, Partial<T>>> | undefined,\n bucket: StyleBreakpointKey | 'default',\n): Partial<T> | undefined => {\n if (bucket === 'default') return base ? { ...base } : undefined;\n const end = STYLE_BREAKPOINT_MERGE_ORDER.indexOf(bucket);\n if (end < 0) return base ? { ...base } : undefined;\n let acc = base ? ({ ...base } as Partial<T>) : undefined;\n for (let i = 0; i <= end; i++) {\n const key = STYLE_BREAKPOINT_MERGE_ORDER[i]!;\n const patch = breakpoints?.[key];\n if (!patch) continue;\n acc = deepMergeStyle(acc as Record<string, unknown> | undefined, patch as Partial<T>) as\n | Partial<T>\n | undefined;\n }\n return acc;\n};\n"]}
@@ -0,0 +1,14 @@
1
+ /** Preview / sim status bar + home-indicator insets (portrait phone). */
2
+ type PreviewPhoneSystemUi = 'ios' | 'android';
3
+ declare const previewPhoneSafeAreaInsetTopPx: (width: number) => number;
4
+ declare const previewPhoneSafeAreaInsetBottomPx: (width: number, systemUi?: PreviewPhoneSystemUi) => number;
5
+ /** Portrait phone preview: no horizontal inset (matches RN `SafeAreaView` in portrait). */
6
+ declare const previewPhoneSafeAreaInsetHorizontalPx: (_width: number) => number;
7
+ declare const previewPhoneSafeAreaPadding: (widthPx: number, systemUi?: PreviewPhoneSystemUi) => {
8
+ t: number;
9
+ r: number;
10
+ b: number;
11
+ l: number;
12
+ };
13
+
14
+ export { type PreviewPhoneSystemUi, previewPhoneSafeAreaInsetBottomPx, previewPhoneSafeAreaInsetHorizontalPx, previewPhoneSafeAreaInsetTopPx, previewPhoneSafeAreaPadding };
@@ -0,0 +1,24 @@
1
+ // src/responsive/previewSafeAreaInsets.ts
2
+ var previewPhoneSafeAreaInsetTopPx = (width) => {
3
+ const statusChromePadY = Math.max(6, Math.round(width * 0.016));
4
+ const chromePadBottom = Math.max(4, Math.round(width * 0.01));
5
+ const padY = Math.max(5, Math.round(width * 0.012));
6
+ const statusH = Math.max(23, Math.round(width * 0.058));
7
+ return statusChromePadY + statusH + 2 * padY + chromePadBottom;
8
+ };
9
+ var previewPhoneSafeAreaInsetBottomPx = (width, systemUi = "ios") => {
10
+ const pad = systemUi === "ios" ? 8 : 10;
11
+ const pill = systemUi === "ios" ? 5 : 4;
12
+ return pad + pill + Math.max(6, Math.round(width * 0.014));
13
+ };
14
+ var previewPhoneSafeAreaInsetHorizontalPx = (_width) => 0;
15
+ var previewPhoneSafeAreaPadding = (widthPx, systemUi = "ios") => ({
16
+ t: previewPhoneSafeAreaInsetTopPx(widthPx),
17
+ r: previewPhoneSafeAreaInsetHorizontalPx(),
18
+ b: previewPhoneSafeAreaInsetBottomPx(widthPx, systemUi),
19
+ l: previewPhoneSafeAreaInsetHorizontalPx()
20
+ });
21
+
22
+ export { previewPhoneSafeAreaInsetBottomPx, previewPhoneSafeAreaInsetHorizontalPx, previewPhoneSafeAreaInsetTopPx, previewPhoneSafeAreaPadding };
23
+ //# sourceMappingURL=previewSafeAreaInsets.js.map
24
+ //# sourceMappingURL=previewSafeAreaInsets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/responsive/previewSafeAreaInsets.ts"],"names":[],"mappings":";AAIO,IAAM,8BAAA,GAAiC,CAAC,KAAA,KAA0B;AACvE,EAAA,MAAM,gBAAA,GAAmB,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,KAAA,GAAQ,KAAK,CAAC,CAAA;AAC9D,EAAA,MAAM,eAAA,GAAkB,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,KAAA,GAAQ,IAAI,CAAC,CAAA;AAC5D,EAAA,MAAM,IAAA,GAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,KAAA,GAAQ,KAAK,CAAC,CAAA;AAClD,EAAA,MAAM,OAAA,GAAU,KAAK,GAAA,CAAI,EAAA,EAAI,KAAK,KAAA,CAAM,KAAA,GAAQ,KAAK,CAAC,CAAA;AACtD,EAAA,OAAO,gBAAA,GAAmB,OAAA,GAAU,CAAA,GAAI,IAAA,GAAO,eAAA;AACjD;AAEO,IAAM,iCAAA,GAAoC,CAC/C,KAAA,EACA,QAAA,GAAiC,KAAA,KACtB;AACX,EAAA,MAAM,GAAA,GAAM,QAAA,KAAa,KAAA,GAAQ,CAAA,GAAI,EAAA;AACrC,EAAA,MAAM,IAAA,GAAO,QAAA,KAAa,KAAA,GAAQ,CAAA,GAAI,CAAA;AACtC,EAAA,OAAO,GAAA,GAAM,OAAO,IAAA,CAAK,GAAA,CAAI,GAAG,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,KAAK,CAAC,CAAA;AAC3D;AAGO,IAAM,qCAAA,GAAwC,CAAC,MAAA,KAA2B;AAE1E,IAAM,2BAAA,GAA8B,CACzC,OAAA,EACA,QAAA,GAAiC,KAAA,MACmB;AAAA,EACpD,CAAA,EAAG,+BAA+B,OAAO,CAAA;AAAA,EACzC,CAAA,EAAG,sCAA6C,CAAA;AAAA,EAChD,CAAA,EAAG,iCAAA,CAAkC,OAAA,EAAS,QAAQ,CAAA;AAAA,EACtD,CAAA,EAAG,sCAA6C;AAClD,CAAA","file":"previewSafeAreaInsets.js","sourcesContent":["/** Preview / sim status bar + home-indicator insets (portrait phone). */\n\nexport type PreviewPhoneSystemUi = 'ios' | 'android';\n\nexport const previewPhoneSafeAreaInsetTopPx = (width: number): number => {\n const statusChromePadY = Math.max(6, Math.round(width * 0.016));\n const chromePadBottom = Math.max(4, Math.round(width * 0.01));\n const padY = Math.max(5, Math.round(width * 0.012));\n const statusH = Math.max(23, Math.round(width * 0.058));\n return statusChromePadY + statusH + 2 * padY + chromePadBottom;\n};\n\nexport const previewPhoneSafeAreaInsetBottomPx = (\n width: number,\n systemUi: PreviewPhoneSystemUi = 'ios',\n): number => {\n const pad = systemUi === 'ios' ? 8 : 10;\n const pill = systemUi === 'ios' ? 5 : 4;\n return pad + pill + Math.max(6, Math.round(width * 0.014));\n};\n\n/** Portrait phone preview: no horizontal inset (matches RN `SafeAreaView` in portrait). */\nexport const previewPhoneSafeAreaInsetHorizontalPx = (_width: number): number => 0;\n\nexport const previewPhoneSafeAreaPadding = (\n widthPx: number,\n systemUi: PreviewPhoneSystemUi = 'ios',\n): { t: number; r: number; b: number; l: number } => ({\n t: previewPhoneSafeAreaInsetTopPx(widthPx),\n r: previewPhoneSafeAreaInsetHorizontalPx(widthPx),\n b: previewPhoneSafeAreaInsetBottomPx(widthPx, systemUi),\n l: previewPhoneSafeAreaInsetHorizontalPx(widthPx),\n});\n"]}
@@ -0,0 +1,11 @@
1
+ import { ScreenContainerStyle, ScreenContainerStyleBreakpoints, ScreenBackgroundFill } from '@getrheo/contracts';
2
+ import { StyleBreakpointKey } from './breakpoints.js';
3
+
4
+ declare const resolveScreenContainerStyleAtWidth: (base: ScreenContainerStyle | undefined, breakpoints: ScreenContainerStyleBreakpoints | undefined, widthPx: number) => ScreenContainerStyle | undefined;
5
+ declare const screenBackgroundFillUsesMedia: (fill: ScreenBackgroundFill | undefined) => fill is Extract<ScreenBackgroundFill, {
6
+ kind: "image" | "video";
7
+ }>;
8
+ /** Effective shell style for builder inspector at a specific breakpoint bucket. */
9
+ declare const resolveScreenContainerForEditBucket: (base: ScreenContainerStyle | undefined, breakpoints: ScreenContainerStyleBreakpoints | undefined, bucket: StyleBreakpointKey | "default") => ScreenContainerStyle | undefined;
10
+
11
+ export { resolveScreenContainerForEditBucket, resolveScreenContainerStyleAtWidth, screenBackgroundFillUsesMedia };
@@ -0,0 +1,122 @@
1
+ // src/responsive/breakpoints.ts
2
+ var TAILWIND_DEFAULT_BREAKPOINTS = {
3
+ sm: 640,
4
+ md: 768,
5
+ lg: 1024,
6
+ xl: 1280,
7
+ "2xl": 1536
8
+ };
9
+ var STYLE_BREAKPOINT_MERGE_ORDER = ["sm", "md", "lg", "xl", "2xl"];
10
+ var getScreenSizeBucketForWidth = (width) => {
11
+ const { sm, md, lg, xl, "2xl": xxl } = TAILWIND_DEFAULT_BREAKPOINTS;
12
+ if (width < sm) return "default";
13
+ if (width < md) return "sm";
14
+ if (width < lg) return "md";
15
+ if (width < xl) return "lg";
16
+ if (width < xxl) return "xl";
17
+ return "2xl";
18
+ };
19
+ var getActiveStyleBreakpointChain = (widthPx) => {
20
+ const bucket = getScreenSizeBucketForWidth(widthPx);
21
+ if (bucket === "default") return [];
22
+ const idx = STYLE_BREAKPOINT_MERGE_ORDER.indexOf(bucket);
23
+ if (idx < 0) return [];
24
+ return STYLE_BREAKPOINT_MERGE_ORDER.slice(0, idx + 1);
25
+ };
26
+
27
+ // src/responsive/merge.ts
28
+ var isPlainObject = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
29
+ var deepMergeStyle = (base, ...overrides) => {
30
+ let acc = base ? { ...base } : void 0;
31
+ for (const o of overrides) {
32
+ if (!o) continue;
33
+ acc = acc ?? {};
34
+ for (const [k, v] of Object.entries(o)) {
35
+ if (v === void 0) continue;
36
+ const prev = acc[k];
37
+ if (isPlainObject(v) && isPlainObject(prev)) {
38
+ const merged = deepMergeStyle(prev, v);
39
+ if (merged !== void 0) acc[k] = merged;
40
+ } else {
41
+ acc[k] = v;
42
+ }
43
+ }
44
+ }
45
+ return acc;
46
+ };
47
+
48
+ // src/responsive/screenContainerResolve.ts
49
+ var mergeBackgroundFillPatch = (fill, patch) => {
50
+ if (fill.kind === "color") {
51
+ return {
52
+ ...fill,
53
+ kind: "color",
54
+ ...patch.color !== void 0 ? { color: patch.color } : {},
55
+ ...patch.opacity !== void 0 ? { opacity: patch.opacity } : {}
56
+ };
57
+ }
58
+ const scrim = patch.scrim !== void 0 ? deepMergeStyle(fill.scrim, patch.scrim) : fill.scrim;
59
+ const shared = {
60
+ ...fill,
61
+ ...patch.fit !== void 0 ? { fit: patch.fit } : {},
62
+ ...patch.opacity !== void 0 ? { opacity: patch.opacity } : {},
63
+ ...scrim !== void 0 ? { scrim } : {}
64
+ };
65
+ if (fill.kind === "image") {
66
+ return shared;
67
+ }
68
+ return {
69
+ ...shared,
70
+ ...patch.loop !== void 0 ? { loop: patch.loop } : {},
71
+ ...patch.autoPlay !== void 0 ? { autoPlay: patch.autoPlay } : {},
72
+ ...patch.triggerLayerId !== void 0 ? { triggerLayerId: patch.triggerLayerId } : {},
73
+ ...patch.onComplete !== void 0 ? { onComplete: patch.onComplete } : {},
74
+ ...patch.audioEnabled !== void 0 ? { audioEnabled: patch.audioEnabled } : {}
75
+ };
76
+ };
77
+ var resolveScreenContainerStyleAtWidth = (base, breakpoints, widthPx) => {
78
+ const chain = getActiveStyleBreakpointChain(widthPx);
79
+ let acc = base ? { ...base } : void 0;
80
+ for (const key of chain) {
81
+ const patch = breakpoints?.[key];
82
+ if (!patch) continue;
83
+ acc = acc ?? {};
84
+ if (patch.padding !== void 0) acc = { ...acc, padding: patch.padding };
85
+ if (patch.margin !== void 0) acc = { ...acc, margin: patch.margin };
86
+ if (patch.insetSafeArea !== void 0) acc = { ...acc, insetSafeArea: patch.insetSafeArea };
87
+ if (patch.backgroundFillPatch && acc.backgroundFill) {
88
+ acc = {
89
+ ...acc,
90
+ backgroundFill: mergeBackgroundFillPatch(acc.backgroundFill, patch.backgroundFillPatch)
91
+ };
92
+ }
93
+ }
94
+ return acc;
95
+ };
96
+ var screenBackgroundFillUsesMedia = (fill) => fill?.kind === "image" || fill?.kind === "video";
97
+ var resolveScreenContainerForEditBucket = (base, breakpoints, bucket) => {
98
+ if (bucket === "default") return base ? { ...base } : void 0;
99
+ const end = STYLE_BREAKPOINT_MERGE_ORDER.indexOf(bucket);
100
+ if (end < 0) return base ? { ...base } : void 0;
101
+ let acc = base ? { ...base } : {};
102
+ for (let i = 0; i <= end; i++) {
103
+ const patch = breakpoints?.[STYLE_BREAKPOINT_MERGE_ORDER[i]];
104
+ if (!patch) continue;
105
+ acc = acc ?? {};
106
+ if (patch.padding !== void 0) acc = { ...acc, padding: patch.padding };
107
+ if (patch.margin !== void 0) acc = { ...acc, margin: patch.margin };
108
+ if (patch.insetSafeArea !== void 0) acc = { ...acc, insetSafeArea: patch.insetSafeArea };
109
+ if (patch.backgroundFillPatch && acc.backgroundFill) {
110
+ acc = {
111
+ ...acc,
112
+ backgroundFill: mergeBackgroundFillPatch(acc.backgroundFill, patch.backgroundFillPatch)
113
+ };
114
+ }
115
+ }
116
+ const hasKeys = acc && (acc.padding !== void 0 || acc.margin !== void 0 || acc.insetSafeArea !== void 0 || acc.backgroundFill !== void 0);
117
+ return hasKeys ? acc : void 0;
118
+ };
119
+
120
+ export { resolveScreenContainerForEditBucket, resolveScreenContainerStyleAtWidth, screenBackgroundFillUsesMedia };
121
+ //# sourceMappingURL=screenContainerResolve.js.map
122
+ //# sourceMappingURL=screenContainerResolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/responsive/breakpoints.ts","../../src/responsive/merge.ts","../../src/responsive/screenContainerResolve.ts"],"names":[],"mappings":"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","file":"screenContainerResolve.js","sourcesContent":["/**\n * Tailwind CSS default `screens` min-width values (px). Single source of truth\n * for preview buckets, manifest breakpoints, and runtime style resolution.\n *\n * @see https://tailwindcss.com/docs/screens\n */\nexport const TAILWIND_DEFAULT_BREAKPOINTS = {\n sm: 640,\n md: 768,\n lg: 1024,\n xl: 1280,\n '2xl': 1536,\n} as const;\n\n/** Viewport classification used by preview UI and editing scope. */\nexport type ScreenSizeBucket = 'default' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n\n/** Ordered keys stored on layers (`styleBreakpoints`) and merged mobile-first. */\nexport const STYLE_BREAKPOINT_MERGE_ORDER = ['sm', 'md', 'lg', 'xl', '2xl'] as const;\nexport type StyleBreakpointKey = (typeof STYLE_BREAKPOINT_MERGE_ORDER)[number];\n\nexport const SCREEN_SIZE_BUCKET_ORDER: readonly ScreenSizeBucket[] = [\n 'default',\n 'sm',\n 'md',\n 'lg',\n 'xl',\n '2xl',\n] as const;\n\n/** Buckets shown in the flow builder inspector (xl / 2xl omitted from authoring UI). */\nexport const BUILDER_INSPECTOR_BUCKET_ORDER: readonly ScreenSizeBucket[] = [\n 'default',\n 'sm',\n 'md',\n 'lg',\n] as const;\n\n/** Human-readable bucket titles; ranges lie between consecutive breakpoints. */\nexport const SCREEN_SIZE_BUCKET_LABEL: Record<ScreenSizeBucket, string> = {\n default: 'Default (< 640px)',\n sm: 'sm (640–767px)',\n md: 'md (768–1023px)',\n lg: 'lg (1024–1279px)',\n xl: 'xl (1280–1535px)',\n '2xl': '2xl (1536px+)',\n};\n\n/** Fallback viewport width when no `previewWidthPx` is passed (simulator / static previews). */\nexport const DEFAULT_PREVIEW_VIEWPORT_WIDTH_PX = 390;\n\n/** Maps viewport width (CSS px) to the Tailwind viewport bucket. */\nexport const getScreenSizeBucketForWidth = (width: number): ScreenSizeBucket => {\n const { sm, md, lg, xl, '2xl': xxl } = TAILWIND_DEFAULT_BREAKPOINTS;\n if (width < sm) return 'default';\n if (width < md) return 'sm';\n if (width < lg) return 'md';\n if (width < xl) return 'lg';\n if (width < xxl) return 'xl';\n return '2xl';\n};\n\n/**\n * Breakpoint keys whose partials apply at this width (mobile-first), e.g.\n * width 800 → `['sm','md']`.\n */\nexport const getActiveStyleBreakpointChain = (widthPx: number): StyleBreakpointKey[] => {\n const bucket = getScreenSizeBucketForWidth(widthPx);\n if (bucket === 'default') return [];\n const idx = STYLE_BREAKPOINT_MERGE_ORDER.indexOf(bucket as StyleBreakpointKey);\n if (idx < 0) return [];\n return STYLE_BREAKPOINT_MERGE_ORDER.slice(0, idx + 1) as StyleBreakpointKey[];\n};\n","import {\n STYLE_BREAKPOINT_MERGE_ORDER,\n getActiveStyleBreakpointChain,\n} from './breakpoints';\nimport type { StyleBreakpointKey } from './breakpoints';\n\nconst isPlainObject = (v: unknown): v is Record<string, unknown> =>\n v !== null && typeof v === 'object' && !Array.isArray(v);\n\n/**\n * Deep-merge style-like objects: nested plain objects merge per-key; scalars\n * and arrays replace. Suitable for padding/margin/border/shadow objects.\n */\nexport const deepMergeStyle = <T extends Record<string, unknown>>(\n base: T | undefined,\n ...overrides: (Partial<T> | undefined)[]\n): T | undefined => {\n let acc: T | undefined = base ? ({ ...base } as T) : undefined;\n for (const o of overrides) {\n if (!o) continue;\n acc = acc ?? ({} as T);\n for (const [k, v] of Object.entries(o) as [keyof T, T[keyof T] | undefined][]) {\n if (v === undefined) continue;\n const prev = acc[k as keyof T] as unknown;\n if (isPlainObject(v) && isPlainObject(prev)) {\n const merged = deepMergeStyle(prev as Record<string, unknown>, v as Partial<T>);\n if (merged !== undefined) (acc as Record<string, unknown>)[k as string] = merged;\n } else {\n (acc as Record<string, unknown>)[k as string] = v as unknown;\n }\n }\n }\n return acc;\n};\n\n/**\n * Mobile-first merge: `base` applies below `sm`; each breakpoint partial stacks\n * from `sm` through the bucket implied by `widthPx`.\n */\nexport const mergeResponsivePartial = <T extends Record<string, unknown>>(\n base: Partial<T> | undefined,\n breakpoints: Partial<Record<StyleBreakpointKey, Partial<T>>> | undefined,\n widthPx: number,\n): Partial<T> | undefined => {\n const chain = getActiveStyleBreakpointChain(widthPx);\n if (chain.length === 0) return base ? { ...base } : undefined;\n let acc = base ? ({ ...base } as Partial<T>) : undefined;\n for (const key of chain) {\n const patch = breakpoints?.[key];\n if (!patch) continue;\n acc = deepMergeStyle(acc as Record<string, unknown> | undefined, patch as Partial<T>) as\n | Partial<T>\n | undefined;\n }\n return acc;\n};\n\n/**\n * Merge breakpoint partials up to and including `bucket` (not using viewport width).\n * Use when editing a specific bucket's effective preview.\n */\nexport const mergeResponsivePartialUpToBucket = <T extends Record<string, unknown>>(\n base: Partial<T> | undefined,\n breakpoints: Partial<Record<StyleBreakpointKey, Partial<T>>> | undefined,\n bucket: StyleBreakpointKey | 'default',\n): Partial<T> | undefined => {\n if (bucket === 'default') return base ? { ...base } : undefined;\n const end = STYLE_BREAKPOINT_MERGE_ORDER.indexOf(bucket);\n if (end < 0) return base ? { ...base } : undefined;\n let acc = base ? ({ ...base } as Partial<T>) : undefined;\n for (let i = 0; i <= end; i++) {\n const key = STYLE_BREAKPOINT_MERGE_ORDER[i]!;\n const patch = breakpoints?.[key];\n if (!patch) continue;\n acc = deepMergeStyle(acc as Record<string, unknown> | undefined, patch as Partial<T>) as\n | Partial<T>\n | undefined;\n }\n return acc;\n};\n","import type {\n ScreenBackgroundFill,\n ScreenBackgroundFillPatch,\n ScreenContainerStyle,\n ScreenContainerStyleBreakpoints,\n} from '@getrheo/contracts';\nimport type { StyleBreakpointKey } from './breakpoints';\nimport { getActiveStyleBreakpointChain, STYLE_BREAKPOINT_MERGE_ORDER } from './breakpoints';\nimport { deepMergeStyle } from './merge';\n\nconst mergeBackgroundFillPatch = (\n fill: ScreenBackgroundFill,\n patch: ScreenBackgroundFillPatch,\n): ScreenBackgroundFill => {\n if (fill.kind === 'color') {\n return {\n ...fill,\n kind: 'color',\n ...(patch.color !== undefined ? { color: patch.color } : {}),\n ...(patch.opacity !== undefined ? { opacity: patch.opacity } : {}),\n };\n }\n const scrim =\n patch.scrim !== undefined\n ? deepMergeStyle(fill.scrim as Record<string, unknown> | undefined, patch.scrim)\n : fill.scrim;\n const shared = {\n ...fill,\n ...(patch.fit !== undefined ? { fit: patch.fit } : {}),\n ...(patch.opacity !== undefined ? { opacity: patch.opacity } : {}),\n ...(scrim !== undefined ? { scrim } : {}),\n };\n if (fill.kind === 'image') {\n return shared as ScreenBackgroundFill;\n }\n return {\n ...shared,\n ...(patch.loop !== undefined ? { loop: patch.loop } : {}),\n ...(patch.autoPlay !== undefined ? { autoPlay: patch.autoPlay } : {}),\n ...(patch.triggerLayerId !== undefined ? { triggerLayerId: patch.triggerLayerId } : {}),\n ...(patch.onComplete !== undefined ? { onComplete: patch.onComplete } : {}),\n ...(patch.audioEnabled !== undefined ? { audioEnabled: patch.audioEnabled } : {}),\n } as ScreenBackgroundFill;\n};\n\nexport const resolveScreenContainerStyleAtWidth = (\n base: ScreenContainerStyle | undefined,\n breakpoints: ScreenContainerStyleBreakpoints | undefined,\n widthPx: number,\n): ScreenContainerStyle | undefined => {\n const chain = getActiveStyleBreakpointChain(widthPx);\n let acc: ScreenContainerStyle | undefined = base ? { ...base } : undefined;\n for (const key of chain) {\n const patch = breakpoints?.[key as StyleBreakpointKey];\n if (!patch) continue;\n acc = acc ?? {};\n if (patch.padding !== undefined) acc = { ...acc, padding: patch.padding };\n if (patch.margin !== undefined) acc = { ...acc, margin: patch.margin };\n if (patch.insetSafeArea !== undefined) acc = { ...acc, insetSafeArea: patch.insetSafeArea };\n if (patch.backgroundFillPatch && acc.backgroundFill) {\n acc = {\n ...acc,\n backgroundFill: mergeBackgroundFillPatch(acc.backgroundFill, patch.backgroundFillPatch),\n };\n }\n }\n return acc;\n};\n\nexport const screenBackgroundFillUsesMedia = (\n fill: ScreenBackgroundFill | undefined,\n): fill is Extract<ScreenBackgroundFill, { kind: 'image' | 'video' }> =>\n fill?.kind === 'image' || fill?.kind === 'video';\n\n/** Effective shell style for builder inspector at a specific breakpoint bucket. */\nexport const resolveScreenContainerForEditBucket = (\n base: ScreenContainerStyle | undefined,\n breakpoints: ScreenContainerStyleBreakpoints | undefined,\n bucket: StyleBreakpointKey | 'default',\n): ScreenContainerStyle | undefined => {\n if (bucket === 'default') return base ? { ...base } : undefined;\n const end = STYLE_BREAKPOINT_MERGE_ORDER.indexOf(bucket);\n if (end < 0) return base ? { ...base } : undefined;\n let acc: ScreenContainerStyle | undefined = base ? { ...base } : {};\n for (let i = 0; i <= end; i++) {\n const patch = breakpoints?.[STYLE_BREAKPOINT_MERGE_ORDER[i]!];\n if (!patch) continue;\n acc = acc ?? {};\n if (patch.padding !== undefined) acc = { ...acc, padding: patch.padding };\n if (patch.margin !== undefined) acc = { ...acc, margin: patch.margin };\n if (patch.insetSafeArea !== undefined) acc = { ...acc, insetSafeArea: patch.insetSafeArea };\n if (patch.backgroundFillPatch && acc.backgroundFill) {\n acc = {\n ...acc,\n backgroundFill: mergeBackgroundFillPatch(acc.backgroundFill, patch.backgroundFillPatch),\n };\n }\n }\n const hasKeys =\n acc &&\n (acc.padding !== undefined ||\n acc.margin !== undefined ||\n acc.insetSafeArea !== undefined ||\n acc.backgroundFill !== undefined);\n return hasKeys ? acc : undefined;\n};\n"]}
@@ -0,0 +1,11 @@
1
+ import { Padding } from '@getrheo/contracts';
2
+
3
+ /** Per-edge sum of two padding objects; omits zero edges. */
4
+ declare const addPadding: (a?: Padding, b?: Padding) => Padding | undefined;
5
+ declare const resolveEffectiveScreenShellPadding: (opts: {
6
+ manual?: Padding;
7
+ insetSafeArea?: boolean;
8
+ safeAreaInsets: Padding;
9
+ }) => Padding | undefined;
10
+
11
+ export { addPadding, resolveEffectiveScreenShellPadding };
@@ -0,0 +1,26 @@
1
+ // src/responsive/screenShellInsets.ts
2
+ var edge = (a, b) => {
3
+ const sum = (a ?? 0) + (b ?? 0);
4
+ return sum === 0 ? void 0 : sum;
5
+ };
6
+ var addPadding = (a, b) => {
7
+ if (!a && !b) return void 0;
8
+ const out = {
9
+ t: edge(a?.t, b?.t),
10
+ r: edge(a?.r, b?.r),
11
+ b: edge(a?.b, b?.b),
12
+ l: edge(a?.l, b?.l)
13
+ };
14
+ const cleaned = Object.fromEntries(
15
+ Object.entries(out).filter(([, v]) => v !== void 0)
16
+ );
17
+ return Object.keys(cleaned).length === 0 ? void 0 : cleaned;
18
+ };
19
+ var resolveEffectiveScreenShellPadding = (opts) => {
20
+ if (!opts.insetSafeArea) return opts.manual;
21
+ return addPadding(opts.manual, opts.safeAreaInsets);
22
+ };
23
+
24
+ export { addPadding, resolveEffectiveScreenShellPadding };
25
+ //# sourceMappingURL=screenShellInsets.js.map
26
+ //# sourceMappingURL=screenShellInsets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/responsive/screenShellInsets.ts"],"names":[],"mappings":";AAEA,IAAM,IAAA,GAAO,CAAC,CAAA,EAAuB,CAAA,KAA8C;AACjF,EAAA,MAAM,GAAA,GAAA,CAAO,CAAA,IAAK,CAAA,KAAM,CAAA,IAAK,CAAA,CAAA;AAC7B,EAAA,OAAO,GAAA,KAAQ,IAAI,MAAA,GAAY,GAAA;AACjC,CAAA;AAGO,IAAM,UAAA,GAAa,CAAC,CAAA,EAAa,CAAA,KAAqC;AAC3E,EAAA,IAAI,CAAC,CAAA,IAAK,CAAC,CAAA,EAAG,OAAO,MAAA;AACrB,EAAA,MAAM,GAAA,GAAe;AAAA,IACnB,CAAA,EAAG,IAAA,CAAK,CAAA,EAAG,CAAA,EAAG,GAAG,CAAC,CAAA;AAAA,IAClB,CAAA,EAAG,IAAA,CAAK,CAAA,EAAG,CAAA,EAAG,GAAG,CAAC,CAAA;AAAA,IAClB,CAAA,EAAG,IAAA,CAAK,CAAA,EAAG,CAAA,EAAG,GAAG,CAAC,CAAA;AAAA,IAClB,CAAA,EAAG,IAAA,CAAK,CAAA,EAAG,CAAA,EAAG,GAAG,CAAC;AAAA,GACpB;AACA,EAAA,MAAM,UAAU,MAAA,CAAO,WAAA;AAAA,IACrB,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,CAAE,MAAA,CAAO,CAAC,GAAG,CAAC,CAAA,KAAM,CAAA,KAAM,MAAS;AAAA,GACvD;AACA,EAAA,OAAO,OAAO,IAAA,CAAK,OAAO,CAAA,CAAE,MAAA,KAAW,IAAI,MAAA,GAAY,OAAA;AACzD;AAEO,IAAM,kCAAA,GAAqC,CAAC,IAAA,KAIxB;AACzB,EAAA,IAAI,CAAC,IAAA,CAAK,aAAA,EAAe,OAAO,IAAA,CAAK,MAAA;AACrC,EAAA,OAAO,UAAA,CAAW,IAAA,CAAK,MAAA,EAAQ,IAAA,CAAK,cAAc,CAAA;AACpD","file":"screenShellInsets.js","sourcesContent":["import type { Padding } from '@getrheo/contracts';\n\nconst edge = (a: number | undefined, b: number | undefined): number | undefined => {\n const sum = (a ?? 0) + (b ?? 0);\n return sum === 0 ? undefined : sum;\n};\n\n/** Per-edge sum of two padding objects; omits zero edges. */\nexport const addPadding = (a?: Padding, b?: Padding): Padding | undefined => {\n if (!a && !b) return undefined;\n const out: Padding = {\n t: edge(a?.t, b?.t),\n r: edge(a?.r, b?.r),\n b: edge(a?.b, b?.b),\n l: edge(a?.l, b?.l),\n };\n const cleaned = Object.fromEntries(\n Object.entries(out).filter(([, v]) => v !== undefined),\n ) as Padding;\n return Object.keys(cleaned).length === 0 ? undefined : cleaned;\n};\n\nexport const resolveEffectiveScreenShellPadding = (opts: {\n manual?: Padding;\n insetSafeArea?: boolean;\n safeAreaInsets: Padding;\n}): Padding | undefined => {\n if (!opts.insetSafeArea) return opts.manual;\n return addPadding(opts.manual, opts.safeAreaInsets);\n};\n"]}
@@ -0,0 +1,167 @@
1
+ import { RestingMotionPreset, RestingMotion, RestingMotionEntry } from '@getrheo/contracts/layers';
2
+ import { Screen } from '@getrheo/contracts/screens';
3
+
4
+ type RuntimeStyle = Record<string, string | number | undefined>;
5
+ declare const RESTING_MOTION_DEFAULT_DURATION_MS: Record<RestingMotionPreset, number>;
6
+ /** Matches {@link RestingMotionSchema} `durationMs` / `scalePatternDurationMs` bounds. */
7
+ declare const RESTING_MOTION_SEGMENT_DURATION_MS_MIN = 200;
8
+ declare const RESTING_MOTION_SEGMENT_DURATION_MS_MAX = 20000;
9
+ declare const clampRestingMotionSegmentDurationMs: (ms: number) => number;
10
+ /** Synthetic id for manifests that only had {@link Layer.restingMotion} (no `restingMotions`). */
11
+ declare const LEGACY_RESTING_MOTION_ID: "__legacy";
12
+ /**
13
+ * Canonical list of motion segments for a layer (array wins; legacy single field becomes one entry).
14
+ */
15
+ declare const layerRestingMotionEntries: (layer: {
16
+ restingMotion?: RestingMotion;
17
+ restingMotions?: RestingMotionEntry[] | null;
18
+ }) => RestingMotionEntry[];
19
+ /** Persist motion segments; clears legacy single field when using the array. */
20
+ declare const layerWithRestingMotionEntries: <L extends {
21
+ restingMotion?: RestingMotion;
22
+ restingMotions?: RestingMotionEntry[];
23
+ }>(layer: L, entries: RestingMotionEntry[]) => L;
24
+ /**
25
+ * Non-loop scale: keep timeline segment and pattern duration identical in saved state.
26
+ * Call when updating motion speed or clip length from the builder.
27
+ */
28
+ declare const restingMotionSyncScaleNonLoopClipAndPattern: (r: RestingMotion, ms: number) => RestingMotion;
29
+ /** Align stored fields after paste/import when scale is one-shot. */
30
+ declare const restingMotionNormalizeScaleNonLoopClip: (r: RestingMotion) => RestingMotion;
31
+ /** Timeline segment length: motion runs from start until start + this value. */
32
+ declare const restingMotionEffectiveDurationMs: (r: RestingMotion) => number;
33
+ /** One full pattern cycle (ms), used when looping. */
34
+ declare const restingMotionCycleDurationMs: (r: RestingMotion) => number;
35
+ /**
36
+ * Value for the Motion speed slider: one-shot → clip length ({@link restingMotionEffectiveDurationMs});
37
+ * looping → one repeat ({@link restingMotionCycleDurationMs}).
38
+ */
39
+ declare const restingMotionMotionSpeedSliderMs: (r: RestingMotion) => number;
40
+ declare const restingMotionIntensity: (r: RestingMotion) => number;
41
+ declare const restingMotionDelayAfterMountEndMs: (r: RestingMotion) => number;
42
+
43
+ /**
44
+ * Latest end time (ms from screen mount) of mount/stagger clips for a layer.
45
+ * `0` when none — layer motion may run immediately.
46
+ */
47
+ declare const layerMountClipsEndMs: (screen: Screen, layerId: string) => number;
48
+ /**
49
+ * Absolute time (ms from screen mount) when layer motion should begin: after all
50
+ * mount/stagger clips end, plus optional author delay.
51
+ */
52
+ declare const layerRestingMotionStartMs: (screen: Screen, layerId: string, cfg: RestingMotion) => number;
53
+ /** Latest end (ms) of any layer motion segment (start + segment duration) — for timeline rulers. */
54
+ declare const screenRestingTimelineExtentMs: (screen: Screen) => number;
55
+ /**
56
+ * Upper bound for editor scrub time (ms from screen mount). Mount/unmount clips
57
+ * alone cap at {@link screenAnimationsDurationMs}; layer motion may start and
58
+ * end later, so the scrub clock must allow times up to this value or motion
59
+ * never becomes "allowed" in the preview.
60
+ */
61
+ declare const motionTimelineScrubClampMs: (screen: Screen) => number;
62
+ /** Default ruler span when the screen has no timed motion content yet. */
63
+ declare const DEFAULT_WORKBENCH_TIMELINE_MS = 10000;
64
+ /**
65
+ * Animation workbench ruler/scrub length (ms). Grows with clips, resting motion,
66
+ * and timed loader segments; never capped. Uses
67
+ * {@link DEFAULT_WORKBENCH_TIMELINE_MS} only when nothing is scheduled yet.
68
+ */
69
+ declare const workbenchTimelineTotalMs: (screen: Screen) => number;
70
+ declare const layerRestingMotionEndMs: (screen: Screen, layerId: string, cfg: RestingMotion) => number;
71
+ /** Pure gate for tests and web scrub (no React): inside the motion segment [start, end). */
72
+ declare const restingMotionAllowedAtTime: (screen: Screen, layerId: string, tMs: number, cfg: RestingMotion) => boolean;
73
+ /** Elapsed ms inside the motion segment, or null if outside [start, end). */
74
+ declare const restingMotionLocalElapsedMs: (screen: Screen, layerId: string, cfg: RestingMotion, tMs: number) => number | null;
75
+
76
+ /** Peak lift (px) matched to legacy `14 * intensity` when {@link RestingMotion.bounceAmplitudePx} is unset. */
77
+ declare const RESTING_MOTION_BOUNCE_BASE_PX = 14;
78
+ declare const restingMotionBounceAmplitudePx: (r: RestingMotion) => number;
79
+ /** Single bounce arc: 0 → peak → 0 over phase ∈ [0, 1]. Negative Y is upward. */
80
+ declare const bouncePhaseToTranslateY: (ph: number, amplitudePx: number) => number;
81
+ /** Default scale magnitude (%), used when {@link RestingMotion.scalePercent} / legacy fields omitted. */
82
+ declare const RESTING_MOTION_DEFAULT_SCALE_UP_PERCENT = 8;
83
+ declare const RESTING_MOTION_DEFAULT_SCALE_DOWN_PERCENT = 0;
84
+ declare const RESTING_MOTION_DEFAULT_SCALE_PERCENT = 8;
85
+ /** Default peak Y (% of layer box) when translate percent peaks omitted (no legacy px). */
86
+ declare const RESTING_MOTION_DEFAULT_TRANSLATE_PEAK_Y_PERCENT = 6;
87
+ /** Default legacy peak Y in px when only deprecated {@link RestingMotion.translateRangePx} applies. */
88
+ declare const RESTING_MOTION_DEFAULT_TRANSLATE_PEAK_Y_PX = 6;
89
+ /** @deprecated Use {@link RESTING_MOTION_DEFAULT_TRANSLATE_PEAK_Y_PX}. */
90
+ declare const RESTING_MOTION_DEFAULT_TRANSLATE_RANGE_PX = 6;
91
+ /** Default peak rotation (°) from rest when {@link RestingMotion.rotateMaxDeg} is omitted. */
92
+ declare const RESTING_MOTION_DEFAULT_ROTATE_DEG = 5;
93
+ declare const RESTING_MOTION_PULSE_DIP_BASE = 0.38;
94
+ /** Scale preset: ms for one rest → peak → rest cycle (authoring + native + web fallback). */
95
+ declare const restingMotionScalePatternDurationMs: (r: RestingMotion) => number;
96
+ /**
97
+ * Phase 0..1 for the current motion pattern. Non-loop: one full pattern stretched over segment.
98
+ * Loop: pattern repeats every cycle duration within the segment.
99
+ */
100
+ declare const restingMotionPhase01: (cfg: RestingMotion, localMs: number) => number;
101
+ declare const restingMotionScaleDirection: (r: RestingMotion) => "up" | "down";
102
+ declare const restingMotionScalePercentResolved: (r: RestingMotion) => number;
103
+ declare const restingMotionScaleAmountFraction: (r: RestingMotion) => number;
104
+ /** Scale preset: return to rest after the peak (default). If false, ramp to peak and hold (per cycle when looping). */
105
+ declare const restingMotionScaleSpringBack: (r: RestingMotion) => boolean;
106
+ /** @deprecated Prefer {@link restingMotionScaleAmountFraction} / {@link restingMotionScalePeakMultiplier}. */
107
+ declare const restingMotionScaleUpFraction: (r: RestingMotion) => number;
108
+ /** @deprecated Prefer {@link restingMotionScaleAmountFraction} / {@link restingMotionScalePeakMultiplier}. */
109
+ declare const restingMotionScaleDownFraction: (r: RestingMotion) => number;
110
+ /** Peak scale multiplier (1±amount) for CSS vars and authoring; independent of {@link restingMotionScaleSpringBack}. */
111
+ declare const restingMotionScalePeakMultiplier: (cfg: RestingMotion) => number;
112
+ /**
113
+ * One scale cycle over ph ∈ [0,1]: rest (1) → peak (1±amount) → rest when spring back is on;
114
+ * linear rest → peak when off (matches rotate ramp semantics).
115
+ */
116
+ declare const restingMotionScaleAtPhase: (cfg: RestingMotion, ph: number) => number;
117
+ /**
118
+ * Authoring translate peaks in % of the layer box (−200–200) for the editor. Maps legacy px fields
119
+ * to a comparable % for display (old ±80 px range → full ±200% scale).
120
+ */
121
+ declare const restingMotionTranslateAuthoringPeakPercent: (r: RestingMotion) => {
122
+ x: number;
123
+ y: number;
124
+ };
125
+ /** @deprecated Use {@link restingMotionTranslateAuthoringPeakPercent} or {@link restingMotionTranslatePeakResolved}. */
126
+ declare const restingMotionTranslateAuthoringPeakPx: (r: RestingMotion) => {
127
+ x: number;
128
+ y: number;
129
+ };
130
+ /** Resolved peak translation for transform: % of layer box, or legacy px. After intensity; clamped. */
131
+ declare const restingMotionTranslatePeakResolved: (r: RestingMotion) => {
132
+ unit: "percent" | "px";
133
+ x: number;
134
+ y: number;
135
+ };
136
+ /** @deprecated Use {@link restingMotionTranslatePeakResolved}. */
137
+ declare const restingMotionTranslatePeakPx: (r: RestingMotion) => {
138
+ x: number;
139
+ y: number;
140
+ };
141
+ /** Translate preset: spring back to origin after the peak (default). */
142
+ declare const restingMotionTranslateSpringBack: (r: RestingMotion) => boolean;
143
+ /** Resolved peak rotation (°), clamped to [0, 360]. Intensity scales the authored angle. */
144
+ declare const restingMotionRotateMaxDeg: (r: RestingMotion) => number;
145
+ /** Rotate preset: oscillate back to 0° after the peak (default). If false, ramp to peak and hold (per cycle when looping). */
146
+ declare const restingMotionRotateSpringBack: (r: RestingMotion) => boolean;
147
+ /** Rotate preset: authored spin direction (default clockwise). */
148
+ declare const restingMotionRotateDirection: (r: RestingMotion) => "clockwise" | "counterclockwise";
149
+ /** +1 for clockwise, −1 for counter-clockwise (anti-clockwise). */
150
+ declare const restingMotionRotateSign: (r: RestingMotion) => 1 | -1;
151
+ declare const restingMotionPulseMinOpacity: (r: RestingMotion) => number;
152
+ /** Sample motion at phase 0..1 (same geometry as web keyframes / native worklets). */
153
+ declare const restingMotionSampleStyle: (cfg: RestingMotion, ph: number) => RuntimeStyle;
154
+ /** Driven by timeline clock (editor / scrub). Returns null outside the motion segment. */
155
+ declare const restingMotionStyleAtTime: (screen: Screen, layerId: string, cfg: RestingMotion, tMs: number) => RuntimeStyle | null;
156
+ /**
157
+ * Injected once in web sim DOM. Intensity scales via `--ob-rm-i` on the
158
+ * animated element (default 1).
159
+ */
160
+ declare const RESTING_MOTION_KEYFRAMES_CSS: string;
161
+ /**
162
+ * Fallback when no motion clock is available (e.g. static export). Prefer
163
+ * {@link restingMotionStyleAtTime} in the editor where the timeline drives sampling.
164
+ */
165
+ declare const restingMotionWebStyle: (config: RestingMotion) => RuntimeStyle | null;
166
+
167
+ export { DEFAULT_WORKBENCH_TIMELINE_MS, LEGACY_RESTING_MOTION_ID, RESTING_MOTION_BOUNCE_BASE_PX, RESTING_MOTION_DEFAULT_DURATION_MS, RESTING_MOTION_DEFAULT_ROTATE_DEG, RESTING_MOTION_DEFAULT_SCALE_DOWN_PERCENT, RESTING_MOTION_DEFAULT_SCALE_PERCENT, RESTING_MOTION_DEFAULT_SCALE_UP_PERCENT, RESTING_MOTION_DEFAULT_TRANSLATE_PEAK_Y_PERCENT, RESTING_MOTION_DEFAULT_TRANSLATE_PEAK_Y_PX, RESTING_MOTION_DEFAULT_TRANSLATE_RANGE_PX, RESTING_MOTION_KEYFRAMES_CSS, RESTING_MOTION_PULSE_DIP_BASE, RESTING_MOTION_SEGMENT_DURATION_MS_MAX, RESTING_MOTION_SEGMENT_DURATION_MS_MIN, type RuntimeStyle, bouncePhaseToTranslateY, clampRestingMotionSegmentDurationMs, layerMountClipsEndMs, layerRestingMotionEndMs, layerRestingMotionEntries, layerRestingMotionStartMs, layerWithRestingMotionEntries, motionTimelineScrubClampMs, restingMotionAllowedAtTime, restingMotionBounceAmplitudePx, restingMotionCycleDurationMs, restingMotionDelayAfterMountEndMs, restingMotionEffectiveDurationMs, restingMotionIntensity, restingMotionLocalElapsedMs, restingMotionMotionSpeedSliderMs, restingMotionNormalizeScaleNonLoopClip, restingMotionPhase01, restingMotionPulseMinOpacity, restingMotionRotateDirection, restingMotionRotateMaxDeg, restingMotionRotateSign, restingMotionRotateSpringBack, restingMotionSampleStyle, restingMotionScaleAmountFraction, restingMotionScaleAtPhase, restingMotionScaleDirection, restingMotionScaleDownFraction, restingMotionScalePatternDurationMs, restingMotionScalePeakMultiplier, restingMotionScalePercentResolved, restingMotionScaleSpringBack, restingMotionScaleUpFraction, restingMotionStyleAtTime, restingMotionSyncScaleNonLoopClipAndPattern, restingMotionTranslateAuthoringPeakPercent, restingMotionTranslateAuthoringPeakPx, restingMotionTranslatePeakPx, restingMotionTranslatePeakResolved, restingMotionTranslateSpringBack, restingMotionWebStyle, screenRestingTimelineExtentMs, workbenchTimelineTotalMs };