flowboard-react 0.6.8 → 0.6.12
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/README.md +16 -0
- package/lib/module/components/FlowboardFlow.js +24 -66
- package/lib/module/components/FlowboardFlow.js.map +1 -1
- package/lib/module/components/FlowboardRenderer.js +590 -196
- package/lib/module/components/FlowboardRenderer.js.map +1 -1
- package/lib/module/components/layout/stackOverlayModel.js +156 -0
- package/lib/module/components/layout/stackOverlayModel.js.map +1 -0
- package/lib/module/fonts/fontLoader.js +285 -0
- package/lib/module/fonts/fontLoader.js.map +1 -0
- package/lib/module/fonts/fontResolver.js +38 -0
- package/lib/module/fonts/fontResolver.js.map +1 -0
- package/lib/module/fonts/google-fonts-meta.json +1 -0
- package/lib/module/fonts/googleFontCatalog.js +56 -0
- package/lib/module/fonts/googleFontCatalog.js.map +1 -0
- package/lib/module/fonts/googleFontLoader.js +101 -0
- package/lib/module/fonts/googleFontLoader.js.map +1 -0
- package/lib/module/fonts/googleFontsLoader.js +68 -0
- package/lib/module/fonts/googleFontsLoader.js.map +1 -0
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/components/FlowboardFlow.d.ts.map +1 -1
- package/lib/typescript/src/components/FlowboardRenderer.d.ts +11 -4
- package/lib/typescript/src/components/FlowboardRenderer.d.ts.map +1 -1
- package/lib/typescript/src/components/layout/stackOverlayModel.d.ts +13 -0
- package/lib/typescript/src/components/layout/stackOverlayModel.d.ts.map +1 -0
- package/lib/typescript/src/fonts/fontLoader.d.ts +17 -0
- package/lib/typescript/src/fonts/fontLoader.d.ts.map +1 -0
- package/lib/typescript/src/fonts/fontResolver.d.ts +11 -0
- package/lib/typescript/src/fonts/fontResolver.d.ts.map +1 -0
- package/lib/typescript/src/fonts/googleFontCatalog.d.ts +4 -0
- package/lib/typescript/src/fonts/googleFontCatalog.d.ts.map +1 -0
- package/lib/typescript/src/fonts/googleFontLoader.d.ts +7 -0
- package/lib/typescript/src/fonts/googleFontLoader.d.ts.map +1 -0
- package/lib/typescript/src/fonts/googleFontsLoader.d.ts +18 -0
- package/lib/typescript/src/fonts/googleFontsLoader.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +2 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +25 -13
- package/src/components/FlowboardFlow.tsx +33 -82
- package/src/components/FlowboardRenderer.tsx +852 -210
- package/src/components/layout/stackOverlayModel.ts +185 -0
- package/src/fonts/fontLoader.ts +426 -0
- package/src/fonts/fontResolver.ts +69 -0
- package/src/fonts/google-fonts-meta.json +1 -0
- package/src/fonts/googleFontCatalog.ts +77 -0
- package/src/fonts/googleFontLoader.ts +136 -0
- package/src/fonts/googleFontsLoader.ts +124 -0
- package/src/index.tsx +13 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import React, { useMemo } from 'react';
|
|
3
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
4
4
|
import { Animated, KeyboardAvoidingView, Platform, Pressable, ScrollView, StyleSheet, Text, TextInput, View, Image, Vibration } from 'react-native';
|
|
5
5
|
import MaskInput from 'react-native-mask-input';
|
|
6
6
|
import LinearGradient from "../native/linearGradient.js";
|
|
@@ -12,6 +12,10 @@ import Svg, { Circle, G, Line, Polygon, SvgText } from "../native/svg.js";
|
|
|
12
12
|
import { insetsToStyle, insetsToMarginStyle, parseAlignment, parseColor, parseCrossAlignment, parseDimension, parseFlexAlignment, parseFontWeight, parseInsets, parseResizeMode, parseTextAlign, parseTextDecoration, resolveNumericValue, resolveText } from "../utils/flowboardUtils.js";
|
|
13
13
|
import { resolveFontAwesomeIcon, FontAwesome6 } from "../core/fontAwesome.js";
|
|
14
14
|
import { useSliderRegistry } from "./widgets/sliderRegistry.js";
|
|
15
|
+
import { isOverlayStack, isPositionedChild, resolveAlignmentToCss, resolveClipBehavior, resolveFitBehavior, resolveOverlayAlignmentValue, resolvePositionedStyle } from "./layout/stackOverlayModel.js";
|
|
16
|
+
import { ensureGoogleFontLoaded as ensureWebGoogleFontLoaded, resolveFontFamily } from "../fonts/googleFontLoader.js";
|
|
17
|
+
import { ensureFontLoaded as ensureNativeFontLoaded, isFontLoaded, resolveAppliedFontFamily, subscribeFontLoad } from "../fonts/fontLoader.js";
|
|
18
|
+
import { resolveFontSpec } from "../fonts/fontResolver.js";
|
|
15
19
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
16
20
|
const styles = StyleSheet.create({
|
|
17
21
|
root: {
|
|
@@ -48,6 +52,126 @@ function getAxisBoundsForPageScroll(pageScroll) {
|
|
|
48
52
|
heightBounded: true
|
|
49
53
|
};
|
|
50
54
|
}
|
|
55
|
+
const LEGACY_SLIDE_DROP_KEYS = new Set(['badge']);
|
|
56
|
+
function isDevelopmentMode() {
|
|
57
|
+
return process.env.NODE_ENV !== 'production';
|
|
58
|
+
}
|
|
59
|
+
function warnLegacySlideMigration(contextPath, componentId, droppedKeys) {
|
|
60
|
+
if (!isDevelopmentMode() || droppedKeys.length === 0) return;
|
|
61
|
+
const idSuffix = componentId ? ` (id: ${componentId})` : '';
|
|
62
|
+
console.warn(`[slider-migration] Migrated legacy slide to stack at "${contextPath}"${idSuffix}. Dropped unsupported keys: ${droppedKeys.join(', ')}`);
|
|
63
|
+
}
|
|
64
|
+
function warnLegacySliderChildWrap(contextPath, childType) {
|
|
65
|
+
if (!isDevelopmentMode()) return;
|
|
66
|
+
console.warn(`[slider-migration] Wrapped non-stack slider child at "${contextPath}" as a stack page${childType ? ` (type: ${childType})` : ''}.`);
|
|
67
|
+
}
|
|
68
|
+
function normalizeLegacySlidePropsToStackProps(input, contextPath, componentId) {
|
|
69
|
+
const props = input && typeof input === 'object' ? {
|
|
70
|
+
...input
|
|
71
|
+
} : {};
|
|
72
|
+
const droppedKeys = [];
|
|
73
|
+
if (props.fill && typeof props.fill === 'object') {
|
|
74
|
+
const normalizedFill = {
|
|
75
|
+
...props.fill
|
|
76
|
+
};
|
|
77
|
+
const fillType = String(normalizedFill.type ?? '').toLowerCase();
|
|
78
|
+
if (fillType === 'color') {
|
|
79
|
+
normalizedFill.type = 'solid';
|
|
80
|
+
}
|
|
81
|
+
props.fill = normalizedFill;
|
|
82
|
+
}
|
|
83
|
+
for (const key of LEGACY_SLIDE_DROP_KEYS) {
|
|
84
|
+
if (key in props) {
|
|
85
|
+
droppedKeys.push(key);
|
|
86
|
+
delete props[key];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
warnLegacySlideMigration(contextPath, componentId, droppedKeys);
|
|
90
|
+
return props;
|
|
91
|
+
}
|
|
92
|
+
function createStackPageWrapper(child, pageIndex) {
|
|
93
|
+
return {
|
|
94
|
+
id: child?.id ? `${String(child.id)}-page` : `legacy-page-${pageIndex + 1}`,
|
|
95
|
+
type: 'stack',
|
|
96
|
+
properties: {
|
|
97
|
+
axis: 'vertical',
|
|
98
|
+
alignment: 'start',
|
|
99
|
+
distribution: 'start',
|
|
100
|
+
childSpacing: 0,
|
|
101
|
+
size: {
|
|
102
|
+
width: 'fill',
|
|
103
|
+
height: 'fit'
|
|
104
|
+
},
|
|
105
|
+
layout: {
|
|
106
|
+
margin: {
|
|
107
|
+
top: 0,
|
|
108
|
+
right: 0,
|
|
109
|
+
bottom: 0,
|
|
110
|
+
left: 0
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
appearance: {
|
|
114
|
+
shape: 'rectangle',
|
|
115
|
+
cornerRadius: 0
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
children: child ? [child] : []
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function migrateLegacySlideNodes(input, contextPath = 'screen') {
|
|
122
|
+
if (Array.isArray(input)) {
|
|
123
|
+
return input.map((item, index) => migrateLegacySlideNodes(item, `${contextPath}[${index}]`));
|
|
124
|
+
}
|
|
125
|
+
if (!input || typeof input !== 'object') return input;
|
|
126
|
+
const node = {
|
|
127
|
+
...input
|
|
128
|
+
};
|
|
129
|
+
const rawType = String(node.type ?? '');
|
|
130
|
+
if (Array.isArray(node.children)) {
|
|
131
|
+
node.children = node.children.map((child, index) => migrateLegacySlideNodes(child, `${contextPath}.children[${index}]`));
|
|
132
|
+
}
|
|
133
|
+
if (node.child && typeof node.child === 'object') {
|
|
134
|
+
node.child = migrateLegacySlideNodes(node.child, `${contextPath}.child`);
|
|
135
|
+
}
|
|
136
|
+
if (Array.isArray(node.options)) {
|
|
137
|
+
node.options = node.options.map((option, index) => {
|
|
138
|
+
if (!option || typeof option !== 'object') return option;
|
|
139
|
+
const optionNode = {
|
|
140
|
+
...option
|
|
141
|
+
};
|
|
142
|
+
if (optionNode.child && typeof optionNode.child === 'object') {
|
|
143
|
+
optionNode.child = migrateLegacySlideNodes(optionNode.child, `${contextPath}.options[${index}].child`);
|
|
144
|
+
}
|
|
145
|
+
return optionNode;
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (rawType === 'slide') {
|
|
149
|
+
node.type = 'stack';
|
|
150
|
+
node.properties = normalizeLegacySlidePropsToStackProps(node.properties ?? {}, contextPath, node.id ? String(node.id) : undefined);
|
|
151
|
+
}
|
|
152
|
+
if (String(node.type ?? '') === 'slider') {
|
|
153
|
+
const children = Array.isArray(node.children) ? node.children : [];
|
|
154
|
+
const normalizedPages = children.map((child, index) => {
|
|
155
|
+
if (!child || typeof child !== 'object') {
|
|
156
|
+
warnLegacySliderChildWrap(`${contextPath}.children[${index}]`, undefined);
|
|
157
|
+
return createStackPageWrapper(null, index);
|
|
158
|
+
}
|
|
159
|
+
const pageNode = child;
|
|
160
|
+
const childType = String(pageNode.type ?? '');
|
|
161
|
+
if (childType === 'stack') return pageNode;
|
|
162
|
+
warnLegacySliderChildWrap(`${contextPath}.children[${index}]`, childType);
|
|
163
|
+
return createStackPageWrapper(pageNode, index);
|
|
164
|
+
});
|
|
165
|
+
node.children = normalizedPages.length > 0 ? normalizedPages : [createStackPageWrapper(null, 0)];
|
|
166
|
+
}
|
|
167
|
+
return node;
|
|
168
|
+
}
|
|
169
|
+
function useGoogleFontLoadSignal() {
|
|
170
|
+
const [, setVersion] = useState(0);
|
|
171
|
+
useEffect(() => subscribeFontLoad(() => {
|
|
172
|
+
setVersion(version => version + 1);
|
|
173
|
+
}), []);
|
|
174
|
+
}
|
|
51
175
|
export default function FlowboardRenderer(props) {
|
|
52
176
|
const {
|
|
53
177
|
screenData,
|
|
@@ -58,28 +182,30 @@ export default function FlowboardRenderer(props) {
|
|
|
58
182
|
currentIndex = 0,
|
|
59
183
|
totalScreens = 1
|
|
60
184
|
} = props;
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
-
const
|
|
185
|
+
useGoogleFontLoadSignal();
|
|
186
|
+
const migratedScreenData = useMemo(() => migrateLegacySlideNodes(screenData, 'screen') ?? {}, [screenData]);
|
|
187
|
+
const childrenData = Array.isArray(migratedScreenData.children) ? migratedScreenData.children : [];
|
|
188
|
+
const backgroundData = migratedScreenData.background;
|
|
189
|
+
const bgColorCode = migratedScreenData.backgroundColor;
|
|
190
|
+
const showProgress = migratedScreenData.showProgress === true;
|
|
191
|
+
const progressColor = parseColor(migratedScreenData.progressColor ?? '0xFF000000');
|
|
192
|
+
const progressThickness = Number(migratedScreenData.progressThickness ?? 4);
|
|
193
|
+
const progressRadius = Number(migratedScreenData.progressRadius ?? 0);
|
|
194
|
+
const progressStyle = migratedScreenData.progressStyle ?? 'linear';
|
|
195
|
+
const pageScroll = resolvePageScrollAxis(migratedScreenData);
|
|
70
196
|
const pageAxisBounds = getAxisBoundsForPageScroll(pageScroll);
|
|
71
197
|
const scrollable = pageScroll !== 'none';
|
|
72
|
-
const safeArea =
|
|
198
|
+
const safeArea = migratedScreenData.safeArea !== false;
|
|
73
199
|
const safeAreaInsets = useSafeAreaInsets();
|
|
74
200
|
const rootAxis = 'vertical';
|
|
75
|
-
const padding = parseInsets(
|
|
201
|
+
const padding = parseInsets(migratedScreenData.padding);
|
|
76
202
|
const contentPaddingStyle = insetsToStyle(padding);
|
|
77
203
|
const progressPaddingStyle = {
|
|
78
204
|
paddingTop: padding.top,
|
|
79
205
|
paddingRight: padding.right,
|
|
80
206
|
paddingLeft: padding.left
|
|
81
207
|
};
|
|
82
|
-
const rootCrossAxisAlignment =
|
|
208
|
+
const rootCrossAxisAlignment = migratedScreenData.crossAxisAlignment ?? migratedScreenData.crossAxis;
|
|
83
209
|
const safeAreaPaddingStyle = safeArea ? {
|
|
84
210
|
paddingTop: safeAreaInsets.top,
|
|
85
211
|
paddingRight: safeAreaInsets.right,
|
|
@@ -100,6 +226,7 @@ export default function FlowboardRenderer(props) {
|
|
|
100
226
|
keyboardShouldPersistTaps: "handled",
|
|
101
227
|
keyboardDismissMode: Platform.OS === 'ios' ? 'interactive' : 'on-drag',
|
|
102
228
|
contentContainerStyle: {
|
|
229
|
+
flexGrow: 1,
|
|
103
230
|
...contentPaddingStyle,
|
|
104
231
|
paddingTop: showProgress ? 0 : padding.top
|
|
105
232
|
},
|
|
@@ -107,9 +234,9 @@ export default function FlowboardRenderer(props) {
|
|
|
107
234
|
style: {
|
|
108
235
|
flexGrow: 1,
|
|
109
236
|
flexDirection: 'column',
|
|
110
|
-
justifyContent: parseFlexAlignment(
|
|
237
|
+
justifyContent: parseFlexAlignment(migratedScreenData.mainAxisAlignment),
|
|
111
238
|
alignItems: parseRootCrossAlignment(rootCrossAxisAlignment),
|
|
112
|
-
minHeight:
|
|
239
|
+
minHeight: '100%',
|
|
113
240
|
minWidth: 0
|
|
114
241
|
},
|
|
115
242
|
children: childrenData.map((child, index) => buildWidget(child, {
|
|
@@ -120,7 +247,7 @@ export default function FlowboardRenderer(props) {
|
|
|
120
247
|
parentFlexAxis: rootAxis,
|
|
121
248
|
parentMainAxisBounded: pageAxisBounds.heightBounded,
|
|
122
249
|
pageAxisBounds,
|
|
123
|
-
screenData,
|
|
250
|
+
screenData: migratedScreenData,
|
|
124
251
|
enableFontAwesomeIcons,
|
|
125
252
|
key: `child-${index}`
|
|
126
253
|
}))
|
|
@@ -130,7 +257,7 @@ export default function FlowboardRenderer(props) {
|
|
|
130
257
|
flex: 1,
|
|
131
258
|
...contentPaddingStyle,
|
|
132
259
|
paddingTop: showProgress ? 0 : padding.top,
|
|
133
|
-
justifyContent: parseFlexAlignment(
|
|
260
|
+
justifyContent: parseFlexAlignment(migratedScreenData.mainAxisAlignment),
|
|
134
261
|
alignItems: parseRootCrossAlignment(rootCrossAxisAlignment)
|
|
135
262
|
},
|
|
136
263
|
children: childrenData.map((child, index) => buildWidget(child, {
|
|
@@ -141,7 +268,7 @@ export default function FlowboardRenderer(props) {
|
|
|
141
268
|
parentFlexAxis: rootAxis,
|
|
142
269
|
parentMainAxisBounded: true,
|
|
143
270
|
pageAxisBounds,
|
|
144
|
-
screenData,
|
|
271
|
+
screenData: migratedScreenData,
|
|
145
272
|
enableFontAwesomeIcons,
|
|
146
273
|
key: `child-${index}`
|
|
147
274
|
}))
|
|
@@ -374,7 +501,7 @@ function normalizeStackAxis(type, props) {
|
|
|
374
501
|
if (type === 'layout') {
|
|
375
502
|
return props.direction === 'horizontal' ? 'horizontal' : 'vertical';
|
|
376
503
|
}
|
|
377
|
-
if (type === 'stack' &&
|
|
504
|
+
if (type === 'stack' && isLegacyOverlayAlignment(props.alignment)) {
|
|
378
505
|
return 'overlay';
|
|
379
506
|
}
|
|
380
507
|
return 'vertical';
|
|
@@ -422,7 +549,7 @@ function normalizeOverlayAlignment(value) {
|
|
|
422
549
|
case 'bottomRight':
|
|
423
550
|
return 'bottomEnd';
|
|
424
551
|
default:
|
|
425
|
-
return '
|
|
552
|
+
return 'topStart';
|
|
426
553
|
}
|
|
427
554
|
}
|
|
428
555
|
function isFillDimensionValue(value) {
|
|
@@ -445,6 +572,51 @@ function normalizeStackSizeMode(value) {
|
|
|
445
572
|
}
|
|
446
573
|
return undefined;
|
|
447
574
|
}
|
|
575
|
+
export function resolveFillSizeStyle(size, options) {
|
|
576
|
+
const allowWidthFill = options?.allowWidthFill !== false;
|
|
577
|
+
const allowHeightFill = options?.allowHeightFill !== false;
|
|
578
|
+
const fillWidth = allowWidthFill && normalizeStackSizeMode(size?.width) === 'fill';
|
|
579
|
+
const fillHeight = allowHeightFill && normalizeStackSizeMode(size?.height) === 'fill';
|
|
580
|
+
const style = {};
|
|
581
|
+
if (fillWidth) {
|
|
582
|
+
style.width = '100%';
|
|
583
|
+
style.alignSelf = 'stretch';
|
|
584
|
+
style.minWidth = 0;
|
|
585
|
+
}
|
|
586
|
+
if (fillHeight) {
|
|
587
|
+
style.height = '100%';
|
|
588
|
+
style.flexGrow = 1;
|
|
589
|
+
style.flexShrink = 1;
|
|
590
|
+
style.flexBasis = 'auto';
|
|
591
|
+
style.minHeight = 0;
|
|
592
|
+
}
|
|
593
|
+
if (fillWidth && fillHeight) {
|
|
594
|
+
style.flexGrow = 1;
|
|
595
|
+
style.flexShrink = 1;
|
|
596
|
+
style.flexBasis = 'auto';
|
|
597
|
+
}
|
|
598
|
+
return style;
|
|
599
|
+
}
|
|
600
|
+
function resolveOverlayContainerFitStyle(props, axisBounds) {
|
|
601
|
+
if (resolveFitBehavior(props.fit) !== 'expand') return {};
|
|
602
|
+
const widthMode = normalizeStackSizeMode(props.size?.width);
|
|
603
|
+
const heightMode = normalizeStackSizeMode(props.size?.height);
|
|
604
|
+
const style = {
|
|
605
|
+
minWidth: 0,
|
|
606
|
+
minHeight: 0
|
|
607
|
+
};
|
|
608
|
+
if (axisBounds.widthBounded && widthMode !== 'fixed') {
|
|
609
|
+
style.width = '100%';
|
|
610
|
+
style.alignSelf = 'stretch';
|
|
611
|
+
}
|
|
612
|
+
if (axisBounds.heightBounded && heightMode !== 'fixed') {
|
|
613
|
+
style.height = '100%';
|
|
614
|
+
style.flexGrow = 1;
|
|
615
|
+
style.flexShrink = 1;
|
|
616
|
+
style.flexBasis = 'auto';
|
|
617
|
+
}
|
|
618
|
+
return style;
|
|
619
|
+
}
|
|
448
620
|
function wantsFillWidth(props) {
|
|
449
621
|
return normalizeStackSizeMode(props.size?.width) === 'fill' || isFillDimensionValue(props.width);
|
|
450
622
|
}
|
|
@@ -467,13 +639,21 @@ function normalizeStackFill(props) {
|
|
|
467
639
|
...props.fill
|
|
468
640
|
};
|
|
469
641
|
if (!next.type && next.color) next.type = 'solid';
|
|
642
|
+
if (String(next.type ?? '').toLowerCase() === 'color') {
|
|
643
|
+
next.type = 'solid';
|
|
644
|
+
}
|
|
645
|
+
const fillType = String(next.type ?? '').toLowerCase();
|
|
646
|
+
if ((fillType === '' || fillType === 'solid') && (typeof next.color !== 'string' || next.color.trim().length === 0)) {
|
|
647
|
+
next.type = 'solid';
|
|
648
|
+
next.color = '0x00FFFFFF';
|
|
649
|
+
}
|
|
470
650
|
return next;
|
|
471
651
|
}
|
|
472
652
|
if (props.background && typeof props.background === 'object') {
|
|
473
653
|
if (props.background.type === 'color') {
|
|
474
654
|
return {
|
|
475
655
|
type: 'solid',
|
|
476
|
-
color: props.background.color
|
|
656
|
+
color: typeof props.background.color === 'string' && props.background.color.trim().length > 0 ? props.background.color : '0x00FFFFFF'
|
|
477
657
|
};
|
|
478
658
|
}
|
|
479
659
|
return {
|
|
@@ -486,7 +666,10 @@ function normalizeStackFill(props) {
|
|
|
486
666
|
color: props.backgroundColor
|
|
487
667
|
};
|
|
488
668
|
}
|
|
489
|
-
return
|
|
669
|
+
return {
|
|
670
|
+
type: 'solid',
|
|
671
|
+
color: '0x00FFFFFF'
|
|
672
|
+
};
|
|
490
673
|
}
|
|
491
674
|
function normalizeStackBorder(props) {
|
|
492
675
|
if (props.border && typeof props.border === 'object') {
|
|
@@ -563,8 +746,17 @@ function mergeStackProps(parentProps, childProps) {
|
|
|
563
746
|
cornerRadius: Number(childProps.appearance?.cornerRadius ?? parentProps.appearance?.cornerRadius ?? 0)
|
|
564
747
|
}
|
|
565
748
|
};
|
|
566
|
-
if (axis === 'overlay') {
|
|
567
|
-
mergedProps.overlayAlignment = childProps.overlayAlignment ?? parentProps.overlayAlignment ?? '
|
|
749
|
+
if (axis === 'overlay' || childProps.overlayAlignment !== undefined || parentProps.overlayAlignment !== undefined || childProps.mode === 'overlay' || parentProps.mode === 'overlay') {
|
|
750
|
+
mergedProps.overlayAlignment = childProps.overlayAlignment ?? parentProps.overlayAlignment ?? 'topStart';
|
|
751
|
+
}
|
|
752
|
+
if (childProps.mode !== undefined || parentProps.mode !== undefined) {
|
|
753
|
+
mergedProps.mode = childProps.mode ?? parentProps.mode;
|
|
754
|
+
}
|
|
755
|
+
if (childProps.fit !== undefined || parentProps.fit !== undefined) {
|
|
756
|
+
mergedProps.fit = childProps.fit ?? parentProps.fit;
|
|
757
|
+
}
|
|
758
|
+
if (childProps.clipBehavior !== undefined || parentProps.clipBehavior !== undefined) {
|
|
759
|
+
mergedProps.clipBehavior = childProps.clipBehavior ?? parentProps.clipBehavior;
|
|
568
760
|
}
|
|
569
761
|
if (parentProps.fill || childProps.fill) {
|
|
570
762
|
mergedProps.fill = childProps.fill ?? parentProps.fill;
|
|
@@ -612,9 +804,16 @@ function normalizeStackLikeNode(json) {
|
|
|
612
804
|
cornerRadius: Number(props.appearance?.cornerRadius ?? props.borderRadius ?? 0)
|
|
613
805
|
}
|
|
614
806
|
};
|
|
615
|
-
if (
|
|
616
|
-
normalizedProps.
|
|
807
|
+
if (props.mode === 'overlay' || props.mode === 'linear') {
|
|
808
|
+
normalizedProps.mode = props.mode;
|
|
617
809
|
}
|
|
810
|
+
if (props.fit === 'expand' || props.fit === 'loose' || String(props.fit).toLowerCase() === 'expand' || String(props.fit).toLowerCase() === 'loose') {
|
|
811
|
+
normalizedProps.fit = String(props.fit).toLowerCase() === 'expand' ? 'expand' : 'loose';
|
|
812
|
+
}
|
|
813
|
+
if (String(props.clipBehavior ?? '').toLowerCase() === 'none' || String(props.clipBehavior ?? '').toLowerCase() === 'hardedge') {
|
|
814
|
+
normalizedProps.clipBehavior = String(props.clipBehavior).toLowerCase() === 'hardedge' ? 'hardEdge' : 'none';
|
|
815
|
+
}
|
|
816
|
+
normalizedProps.overlayAlignment = normalizeOverlayAlignment(props.overlayAlignment ?? props.alignment);
|
|
618
817
|
const fill = normalizeStackFill(props);
|
|
619
818
|
if (fill) normalizedProps.fill = fill;
|
|
620
819
|
const border = normalizeStackBorder(props);
|
|
@@ -650,56 +849,6 @@ function normalizeStackLikeNode(json) {
|
|
|
650
849
|
child: undefined
|
|
651
850
|
};
|
|
652
851
|
}
|
|
653
|
-
function parseOverlayGridAlignment(value) {
|
|
654
|
-
switch (normalizeOverlayAlignment(value)) {
|
|
655
|
-
case 'topStart':
|
|
656
|
-
return {
|
|
657
|
-
justifyContent: 'flex-start',
|
|
658
|
-
alignItems: 'flex-start'
|
|
659
|
-
};
|
|
660
|
-
case 'top':
|
|
661
|
-
return {
|
|
662
|
-
justifyContent: 'flex-start',
|
|
663
|
-
alignItems: 'center'
|
|
664
|
-
};
|
|
665
|
-
case 'topEnd':
|
|
666
|
-
return {
|
|
667
|
-
justifyContent: 'flex-start',
|
|
668
|
-
alignItems: 'flex-end'
|
|
669
|
-
};
|
|
670
|
-
case 'start':
|
|
671
|
-
return {
|
|
672
|
-
justifyContent: 'center',
|
|
673
|
-
alignItems: 'flex-start'
|
|
674
|
-
};
|
|
675
|
-
case 'end':
|
|
676
|
-
return {
|
|
677
|
-
justifyContent: 'center',
|
|
678
|
-
alignItems: 'flex-end'
|
|
679
|
-
};
|
|
680
|
-
case 'bottomStart':
|
|
681
|
-
return {
|
|
682
|
-
justifyContent: 'flex-end',
|
|
683
|
-
alignItems: 'flex-start'
|
|
684
|
-
};
|
|
685
|
-
case 'bottom':
|
|
686
|
-
return {
|
|
687
|
-
justifyContent: 'flex-end',
|
|
688
|
-
alignItems: 'center'
|
|
689
|
-
};
|
|
690
|
-
case 'bottomEnd':
|
|
691
|
-
return {
|
|
692
|
-
justifyContent: 'flex-end',
|
|
693
|
-
alignItems: 'flex-end'
|
|
694
|
-
};
|
|
695
|
-
case 'center':
|
|
696
|
-
default:
|
|
697
|
-
return {
|
|
698
|
-
justifyContent: 'center',
|
|
699
|
-
alignItems: 'center'
|
|
700
|
-
};
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
852
|
function resolveStackDimension(props, axis, key, axisBounds) {
|
|
704
853
|
const mode = props.size?.[key];
|
|
705
854
|
const legacy = normalizeDimension(parseLayoutDimension(props[key]));
|
|
@@ -713,6 +862,21 @@ function resolveStackDimension(props, axis, key, axisBounds) {
|
|
|
713
862
|
if (key === 'height' && axis === 'horizontal' && axisBounds.heightBounded) return '100%';
|
|
714
863
|
return undefined;
|
|
715
864
|
}
|
|
865
|
+
function resolveTextWidthMode(props) {
|
|
866
|
+
const raw = String(props.size?.width ?? '').trim().toLowerCase();
|
|
867
|
+
if (raw === 'fill' || raw === 'infinity' || raw === 'infinite' || raw === 'double.infinity' || raw === '+infinity') {
|
|
868
|
+
return 'fill';
|
|
869
|
+
}
|
|
870
|
+
if (raw === 'fit') return 'fit';
|
|
871
|
+
if (raw === 'fixed') return 'fixed';
|
|
872
|
+
if (isFillDimensionValue(props.width)) return 'fill';
|
|
873
|
+
return props.width !== undefined ? 'fixed' : 'fit';
|
|
874
|
+
}
|
|
875
|
+
function resolveTextFixedWidth(props) {
|
|
876
|
+
const explicit = normalizeDimension(parseLayoutDimension(props.width, true));
|
|
877
|
+
if (explicit !== undefined) return explicit;
|
|
878
|
+
return normalizeDimension(parseLayoutDimension(props.size?.widthPx, true));
|
|
879
|
+
}
|
|
716
880
|
function buildWidget(json, params) {
|
|
717
881
|
if (!json || typeof json !== 'object') return null;
|
|
718
882
|
const normalizedJson = normalizeStackLikeNode(json);
|
|
@@ -831,6 +995,13 @@ function buildWidget(json, params) {
|
|
|
831
995
|
const gradient = parseGradient(props.foreground);
|
|
832
996
|
const textStyle = getTextStyle(props, 'color');
|
|
833
997
|
const align = parseTextAlign(props.textAlign);
|
|
998
|
+
const widthMode = resolveTextWidthMode(props);
|
|
999
|
+
const fixedWidth = resolveTextFixedWidth(props);
|
|
1000
|
+
const widthBounded = params.pageAxisBounds?.widthBounded ?? true;
|
|
1001
|
+
// Shared width-mode contract across React/Flutter:
|
|
1002
|
+
// fit = intrinsic width (no flex, no 100% stretch)
|
|
1003
|
+
// fill = expand within bounded parent constraints
|
|
1004
|
+
// fixed = explicit width value
|
|
834
1005
|
if (gradient) {
|
|
835
1006
|
node = /*#__PURE__*/_jsx(GradientText, {
|
|
836
1007
|
text: resolvedText,
|
|
@@ -847,6 +1018,58 @@ function buildWidget(json, params) {
|
|
|
847
1018
|
children: resolvedText
|
|
848
1019
|
});
|
|
849
1020
|
}
|
|
1021
|
+
if (widthMode === 'fill') {
|
|
1022
|
+
if (params.parentFlexAxis === 'horizontal') {
|
|
1023
|
+
if (params.parentMainAxisBounded ?? true) {
|
|
1024
|
+
node = /*#__PURE__*/_jsx(View, {
|
|
1025
|
+
style: {
|
|
1026
|
+
flex: 1,
|
|
1027
|
+
minWidth: 0,
|
|
1028
|
+
alignSelf: 'stretch'
|
|
1029
|
+
},
|
|
1030
|
+
children: node
|
|
1031
|
+
});
|
|
1032
|
+
} else {
|
|
1033
|
+
node = /*#__PURE__*/_jsx(View, {
|
|
1034
|
+
style: {
|
|
1035
|
+
minWidth: 0
|
|
1036
|
+
},
|
|
1037
|
+
children: node
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
} else if (widthBounded) {
|
|
1041
|
+
node = /*#__PURE__*/_jsx(View, {
|
|
1042
|
+
style: {
|
|
1043
|
+
width: '100%',
|
|
1044
|
+
minWidth: 0,
|
|
1045
|
+
alignSelf: 'stretch'
|
|
1046
|
+
},
|
|
1047
|
+
children: node
|
|
1048
|
+
});
|
|
1049
|
+
} else {
|
|
1050
|
+
node = /*#__PURE__*/_jsx(View, {
|
|
1051
|
+
style: {
|
|
1052
|
+
minWidth: 0
|
|
1053
|
+
},
|
|
1054
|
+
children: node
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
} else if (widthMode === 'fixed') {
|
|
1058
|
+
node = /*#__PURE__*/_jsx(View, {
|
|
1059
|
+
style: {
|
|
1060
|
+
width: fixedWidth,
|
|
1061
|
+
minWidth: 0
|
|
1062
|
+
},
|
|
1063
|
+
children: node
|
|
1064
|
+
});
|
|
1065
|
+
} else {
|
|
1066
|
+
node = /*#__PURE__*/_jsx(View, {
|
|
1067
|
+
style: {
|
|
1068
|
+
minWidth: 0
|
|
1069
|
+
},
|
|
1070
|
+
children: node
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
850
1073
|
break;
|
|
851
1074
|
}
|
|
852
1075
|
case 'rich_text':
|
|
@@ -1214,11 +1437,11 @@ function buildWidget(json, params) {
|
|
|
1214
1437
|
const direction = props.direction === 'vertical' ? 'vertical' : 'horizontal';
|
|
1215
1438
|
const interaction = props.interaction ?? {};
|
|
1216
1439
|
const pageControl = props.pageControl ?? {};
|
|
1217
|
-
const
|
|
1440
|
+
const sliderPages = (childrenJson ?? []).filter(child => child && String(child.type ?? '') === 'stack');
|
|
1218
1441
|
node = /*#__PURE__*/_jsx(SliderWidget, {
|
|
1219
|
-
id: json._internalId,
|
|
1442
|
+
id: json._internalId ?? json.id,
|
|
1220
1443
|
sliderProps: props,
|
|
1221
|
-
|
|
1444
|
+
pagePropsList: sliderPages.map(child => child?.properties ?? {}),
|
|
1222
1445
|
direction: direction,
|
|
1223
1446
|
pageAlignment: props.pageAlignment === 'start' || props.pageAlignment === 'end' ? props.pageAlignment : 'center',
|
|
1224
1447
|
pageSpacing: Number(props.pageSpacing ?? 16),
|
|
@@ -1228,27 +1451,19 @@ function buildWidget(json, params) {
|
|
|
1228
1451
|
autoAdvanceIntervalMs: Number(interaction.autoAdvanceIntervalMs ?? 4000),
|
|
1229
1452
|
pageControlEnabled: pageControl.enabled !== false,
|
|
1230
1453
|
pageControlPosition: pageControl.position === 'top' ? 'top' : 'bottom',
|
|
1231
|
-
children:
|
|
1454
|
+
children: sliderPages.map((child, index) => /*#__PURE__*/_jsx(View, {
|
|
1232
1455
|
children: buildWidget(child, {
|
|
1233
|
-
...params
|
|
1456
|
+
...params,
|
|
1457
|
+
// Slider pages always render inside a bounded pager viewport.
|
|
1458
|
+
pageAxisBounds: {
|
|
1459
|
+
widthBounded: true,
|
|
1460
|
+
heightBounded: true
|
|
1461
|
+
}
|
|
1234
1462
|
})
|
|
1235
1463
|
}, `slider-${index}`))
|
|
1236
1464
|
});
|
|
1237
1465
|
break;
|
|
1238
1466
|
}
|
|
1239
|
-
case 'slide':
|
|
1240
|
-
{
|
|
1241
|
-
node = buildWidget({
|
|
1242
|
-
...json,
|
|
1243
|
-
type: 'stack',
|
|
1244
|
-
properties: {
|
|
1245
|
-
...(props || {})
|
|
1246
|
-
}
|
|
1247
|
-
}, {
|
|
1248
|
-
...params
|
|
1249
|
-
});
|
|
1250
|
-
break;
|
|
1251
|
-
}
|
|
1252
1467
|
case 'pageview_indicator':
|
|
1253
1468
|
{
|
|
1254
1469
|
node = /*#__PURE__*/_jsx(PageViewIndicator, {
|
|
@@ -1306,12 +1521,13 @@ function buildWidget(json, params) {
|
|
|
1306
1521
|
}
|
|
1307
1522
|
case 'stack':
|
|
1308
1523
|
{
|
|
1309
|
-
const axis = props.axis === 'horizontal'
|
|
1310
|
-
const isOverlay =
|
|
1524
|
+
const axis = props.axis === 'horizontal' ? 'horizontal' : 'vertical';
|
|
1525
|
+
const isOverlay = isOverlayStack(childrenJson, props);
|
|
1311
1526
|
const spacing = Number(props.childSpacing ?? 0);
|
|
1312
1527
|
const applySpacing = !STACK_SPACE_DISTRIBUTIONS.has(String(props.distribution ?? 'start'));
|
|
1313
|
-
const
|
|
1314
|
-
const
|
|
1528
|
+
const resolvedAxis = isOverlay ? 'overlay' : axis;
|
|
1529
|
+
const width = resolveStackDimension(props, resolvedAxis, 'width', pageAxisBounds);
|
|
1530
|
+
const height = resolveStackDimension(props, resolvedAxis, 'height', pageAxisBounds);
|
|
1315
1531
|
const mainAxisBounded = axis === 'horizontal' ? pageAxisBounds.widthBounded : pageAxisBounds.heightBounded;
|
|
1316
1532
|
const borderRadius = Number(props.appearance?.cornerRadius ?? props.borderRadius ?? 0);
|
|
1317
1533
|
const borderWidth = Number(props.border?.width ?? 0);
|
|
@@ -1334,12 +1550,17 @@ function buildWidget(json, params) {
|
|
|
1334
1550
|
...fill,
|
|
1335
1551
|
type: 'gradient'
|
|
1336
1552
|
}) : undefined;
|
|
1337
|
-
const stackColor = fill?.type === 'solid' || !fill?.type && fill?.color ? parseColor(fill?.color ?? '
|
|
1553
|
+
const stackColor = fill?.type === 'solid' || !fill?.type && fill?.color ? parseColor(fill?.color ?? '0x00FFFFFF') : parseColor(props.backgroundColor ?? '#00000000');
|
|
1338
1554
|
const baseStackStyle = {
|
|
1339
1555
|
width,
|
|
1340
1556
|
height,
|
|
1557
|
+
...resolveFillSizeStyle(props.size, {
|
|
1558
|
+
allowWidthFill: pageAxisBounds.widthBounded,
|
|
1559
|
+
allowHeightFill: pageAxisBounds.heightBounded
|
|
1560
|
+
}),
|
|
1561
|
+
...(isOverlay ? resolveOverlayContainerFitStyle(props, pageAxisBounds) : {}),
|
|
1341
1562
|
borderRadius: borderRadius > 0 ? borderRadius : undefined,
|
|
1342
|
-
overflow: borderRadius > 0 ? 'hidden' : undefined,
|
|
1563
|
+
overflow: isOverlay ? resolveClipBehavior(props.clipBehavior) === 'hardEdge' ? 'hidden' : 'visible' : borderRadius > 0 ? 'hidden' : undefined,
|
|
1343
1564
|
borderWidth: borderColor ? borderWidth : undefined,
|
|
1344
1565
|
borderColor: borderColor ?? undefined,
|
|
1345
1566
|
...shadowStyle
|
|
@@ -1356,7 +1577,24 @@ function buildWidget(json, params) {
|
|
|
1356
1577
|
...stackContentSizeStyle
|
|
1357
1578
|
},
|
|
1358
1579
|
children: [(childrenJson ?? []).map((child, index) => {
|
|
1359
|
-
|
|
1580
|
+
if (isPositionedChild(child)) {
|
|
1581
|
+
if (String(child?.type ?? '') === 'positioned') {
|
|
1582
|
+
return /*#__PURE__*/_jsx(React.Fragment, {
|
|
1583
|
+
children: buildWidget(child, {
|
|
1584
|
+
...params,
|
|
1585
|
+
pageAxisBounds
|
|
1586
|
+
})
|
|
1587
|
+
}, `stack-overlay-positioned-${index}`);
|
|
1588
|
+
}
|
|
1589
|
+
return /*#__PURE__*/_jsx(View, {
|
|
1590
|
+
style: resolvePositionedStyle(child?.properties ?? {}),
|
|
1591
|
+
children: buildWidget(child, {
|
|
1592
|
+
...params,
|
|
1593
|
+
pageAxisBounds
|
|
1594
|
+
})
|
|
1595
|
+
}, `stack-overlay-positioned-${index}`);
|
|
1596
|
+
}
|
|
1597
|
+
const alignment = resolveAlignmentToCss(resolveOverlayAlignmentValue(props));
|
|
1360
1598
|
return /*#__PURE__*/_jsx(View, {
|
|
1361
1599
|
style: {
|
|
1362
1600
|
position: 'absolute',
|
|
@@ -1372,7 +1610,7 @@ function buildWidget(json, params) {
|
|
|
1372
1610
|
allowFlexExpansion: true,
|
|
1373
1611
|
pageAxisBounds
|
|
1374
1612
|
})
|
|
1375
|
-
}, `stack-overlay-${index}`);
|
|
1613
|
+
}, `stack-overlay-non-positioned-${index}`);
|
|
1376
1614
|
}), (childrenJson ?? []).length === 0 ? null : null]
|
|
1377
1615
|
}) : /*#__PURE__*/_jsx(View, {
|
|
1378
1616
|
style: {
|
|
@@ -1420,22 +1658,8 @@ function buildWidget(json, params) {
|
|
|
1420
1658
|
}
|
|
1421
1659
|
case 'positioned':
|
|
1422
1660
|
{
|
|
1423
|
-
const left = parseLayoutDimension(props.left);
|
|
1424
|
-
const top = parseLayoutDimension(props.top);
|
|
1425
|
-
const right = parseLayoutDimension(props.right);
|
|
1426
|
-
const bottom = parseLayoutDimension(props.bottom);
|
|
1427
|
-
const width = parseLayoutDimension(props.width);
|
|
1428
|
-
const height = parseLayoutDimension(props.height);
|
|
1429
1661
|
node = /*#__PURE__*/_jsx(View, {
|
|
1430
|
-
style:
|
|
1431
|
-
position: 'absolute',
|
|
1432
|
-
left,
|
|
1433
|
-
top,
|
|
1434
|
-
right,
|
|
1435
|
-
bottom,
|
|
1436
|
-
width,
|
|
1437
|
-
height
|
|
1438
|
-
},
|
|
1662
|
+
style: resolvePositionedStyle(props),
|
|
1439
1663
|
children: childJson ? buildWidget(childJson, {
|
|
1440
1664
|
...params
|
|
1441
1665
|
}) : null
|
|
@@ -1486,6 +1710,7 @@ function buildWidget(json, params) {
|
|
|
1486
1710
|
let shouldExpand = false;
|
|
1487
1711
|
const parentAxis = params.parentFlexAxis ?? 'vertical';
|
|
1488
1712
|
const parentMainAxisBounded = params.parentMainAxisBounded ?? true;
|
|
1713
|
+
const sliderWantsMainAxisFill = type === 'slider' && (parentAxis === 'vertical' && wantsFillHeight(props) || parentAxis === 'horizontal' && wantsFillWidth(props));
|
|
1489
1714
|
if (parentMainAxisBounded) {
|
|
1490
1715
|
if (type === 'stack') {
|
|
1491
1716
|
const legacyExpand = props.fit === 'expand';
|
|
@@ -1511,12 +1736,18 @@ function buildWidget(json, params) {
|
|
|
1511
1736
|
}
|
|
1512
1737
|
}
|
|
1513
1738
|
}
|
|
1739
|
+
if (sliderWantsMainAxisFill) {
|
|
1740
|
+
shouldExpand = true;
|
|
1741
|
+
}
|
|
1514
1742
|
if (shouldExpand) {
|
|
1743
|
+
// Keep cross-axis stretching on the outer expansion wrapper as well.
|
|
1744
|
+
// Without this, a centered parent cross-axis can collapse effective fill width/height.
|
|
1515
1745
|
node = /*#__PURE__*/_jsx(View, {
|
|
1516
1746
|
style: {
|
|
1517
1747
|
flex: 1,
|
|
1518
1748
|
minHeight: 0,
|
|
1519
|
-
minWidth: 0
|
|
1749
|
+
minWidth: 0,
|
|
1750
|
+
alignSelf: shouldStretchCrossAxis ? 'stretch' : undefined
|
|
1520
1751
|
},
|
|
1521
1752
|
children: node
|
|
1522
1753
|
});
|
|
@@ -1548,9 +1779,30 @@ function buildActionPayload(props, json) {
|
|
|
1548
1779
|
return payload;
|
|
1549
1780
|
}
|
|
1550
1781
|
function getTextStyle(props, colorKey, defaultColor) {
|
|
1551
|
-
const
|
|
1782
|
+
const requestedFontFamily = resolveFontFamily(props.fontFamily);
|
|
1552
1783
|
const fontSize = Number(props.fontSize ?? 14);
|
|
1553
|
-
const
|
|
1784
|
+
const parsedFontWeight = parseFontWeight(props.fontWeight);
|
|
1785
|
+
const requestedWeight = Number(parsedFontWeight);
|
|
1786
|
+
const numericRequestedWeight = Number.isFinite(requestedWeight) ? requestedWeight : undefined;
|
|
1787
|
+
let fontFamily = requestedFontFamily;
|
|
1788
|
+
let fontWeight = parsedFontWeight;
|
|
1789
|
+
if (Platform.OS === 'web' && requestedFontFamily) {
|
|
1790
|
+
const resolvedSpec = resolveFontSpec({
|
|
1791
|
+
family: requestedFontFamily,
|
|
1792
|
+
requestedWeight: numericRequestedWeight
|
|
1793
|
+
});
|
|
1794
|
+
fontFamily = resolvedSpec.resolvedFamily;
|
|
1795
|
+
fontWeight = resolvedSpec.resolvedWeight !== undefined ? String(resolvedSpec.resolvedWeight) : parsedFontWeight;
|
|
1796
|
+
ensureWebGoogleFontLoaded(resolvedSpec.resolvedFamily, [fontWeight]);
|
|
1797
|
+
} else if (requestedFontFamily) {
|
|
1798
|
+
const resolvedSpec = resolveFontSpec({
|
|
1799
|
+
family: requestedFontFamily,
|
|
1800
|
+
requestedWeight: numericRequestedWeight
|
|
1801
|
+
});
|
|
1802
|
+
void ensureNativeFontLoaded(resolvedSpec).catch(() => undefined);
|
|
1803
|
+
fontWeight = undefined;
|
|
1804
|
+
fontFamily = isFontLoaded(resolvedSpec) ? resolveAppliedFontFamily(resolvedSpec) : resolvedSpec.resolvedFamily;
|
|
1805
|
+
}
|
|
1554
1806
|
const fontStyle = props.fontStyle === 'italic' ? 'italic' : 'normal';
|
|
1555
1807
|
const color = parseColor(props[colorKey] ?? defaultColor ?? '0xFF000000');
|
|
1556
1808
|
const letterSpacing = props.letterSpacing !== undefined ? Number(props.letterSpacing) : undefined;
|
|
@@ -1573,7 +1825,8 @@ function parseGradient(value) {
|
|
|
1573
1825
|
if (colors.length === 0) return undefined;
|
|
1574
1826
|
const start = alignmentToGradient(value.begin ?? 'topLeft');
|
|
1575
1827
|
const end = alignmentToGradient(value.end ?? 'bottomRight');
|
|
1576
|
-
const
|
|
1828
|
+
const parsedStops = Array.isArray(value.stops) ? value.stops.map(s => Number(s)) : undefined;
|
|
1829
|
+
const stops = parsedStops && parsedStops.length === colors.length ? parsedStops : undefined;
|
|
1577
1830
|
return {
|
|
1578
1831
|
colors,
|
|
1579
1832
|
start,
|
|
@@ -1910,9 +2163,16 @@ function GradientText({
|
|
|
1910
2163
|
gradient,
|
|
1911
2164
|
style
|
|
1912
2165
|
}) {
|
|
2166
|
+
if (Platform.OS === 'web') {
|
|
2167
|
+
return /*#__PURE__*/_jsx(Text, {
|
|
2168
|
+
style: [style, getWebGradientTextStyle(gradient)],
|
|
2169
|
+
children: text
|
|
2170
|
+
});
|
|
2171
|
+
}
|
|
1913
2172
|
return /*#__PURE__*/_jsx(MaskedView, {
|
|
1914
2173
|
maskElement: /*#__PURE__*/_jsx(Text, {
|
|
1915
2174
|
style: [style, {
|
|
2175
|
+
color: '#FFFFFF',
|
|
1916
2176
|
backgroundColor: 'transparent'
|
|
1917
2177
|
}],
|
|
1918
2178
|
children: text
|
|
@@ -1924,6 +2184,7 @@ function GradientText({
|
|
|
1924
2184
|
locations: gradient.stops,
|
|
1925
2185
|
children: /*#__PURE__*/_jsx(Text, {
|
|
1926
2186
|
style: [style, {
|
|
2187
|
+
color: '#FFFFFF',
|
|
1927
2188
|
opacity: 0
|
|
1928
2189
|
}],
|
|
1929
2190
|
children: text
|
|
@@ -1931,6 +2192,27 @@ function GradientText({
|
|
|
1931
2192
|
})
|
|
1932
2193
|
});
|
|
1933
2194
|
}
|
|
2195
|
+
function getWebGradientTextStyle(gradient) {
|
|
2196
|
+
const angle = gradientToCssAngle(gradient.start, gradient.end);
|
|
2197
|
+
const normalizedStops = gradient.stops && gradient.stops.length === gradient.colors.length ? gradient.stops.map(stop => `${clamp01(stop) * 100}%`) : undefined;
|
|
2198
|
+
const gradientStops = gradient.colors.map((color, index) => {
|
|
2199
|
+
if (!normalizedStops) return color;
|
|
2200
|
+
return `${color} ${normalizedStops[index]}`;
|
|
2201
|
+
});
|
|
2202
|
+
return {
|
|
2203
|
+
backgroundImage: `linear-gradient(${angle}deg, ${gradientStops.join(', ')})`,
|
|
2204
|
+
backgroundClip: 'text',
|
|
2205
|
+
WebkitBackgroundClip: 'text',
|
|
2206
|
+
color: 'transparent'
|
|
2207
|
+
};
|
|
2208
|
+
}
|
|
2209
|
+
function gradientToCssAngle(start, end) {
|
|
2210
|
+
const dx = end.x - start.x;
|
|
2211
|
+
const dy = end.y - start.y;
|
|
2212
|
+
const radians = Math.atan2(dy, dx);
|
|
2213
|
+
const degrees = radians * 180 / Math.PI;
|
|
2214
|
+
return (degrees + 90 + 360) % 360;
|
|
2215
|
+
}
|
|
1934
2216
|
function resolveTextInputBackgroundColor(properties) {
|
|
1935
2217
|
const canonical = properties.backgroundColor;
|
|
1936
2218
|
if (typeof canonical === 'string' && canonical.trim().length > 0) {
|
|
@@ -2772,10 +3054,18 @@ function FakeProgressBar({
|
|
|
2772
3054
|
});
|
|
2773
3055
|
}
|
|
2774
3056
|
return /*#__PURE__*/_jsxs(View, {
|
|
3057
|
+
style: {
|
|
3058
|
+
width: '100%',
|
|
3059
|
+
alignSelf: 'stretch',
|
|
3060
|
+
minWidth: 0,
|
|
3061
|
+
flexDirection: 'column'
|
|
3062
|
+
},
|
|
2775
3063
|
children: [/*#__PURE__*/_jsx(View, {
|
|
2776
3064
|
style: {
|
|
2777
3065
|
height: thickness,
|
|
2778
3066
|
width: '100%',
|
|
3067
|
+
alignSelf: 'stretch',
|
|
3068
|
+
minWidth: 0,
|
|
2779
3069
|
borderRadius,
|
|
2780
3070
|
backgroundColor,
|
|
2781
3071
|
overflow: 'hidden'
|
|
@@ -2793,7 +3083,9 @@ function FakeProgressBar({
|
|
|
2793
3083
|
})
|
|
2794
3084
|
}), showProgressText ? /*#__PURE__*/_jsx(Text, {
|
|
2795
3085
|
style: [progressTextStyle, {
|
|
2796
|
-
marginTop: 8
|
|
3086
|
+
marginTop: 8,
|
|
3087
|
+
width: '100%',
|
|
3088
|
+
alignSelf: 'stretch'
|
|
2797
3089
|
}],
|
|
2798
3090
|
children: progressText
|
|
2799
3091
|
}) : null]
|
|
@@ -2810,12 +3102,20 @@ export function resolvePeekInsets(pageAlignment, pagePeek) {
|
|
|
2810
3102
|
}
|
|
2811
3103
|
function resolveSliderSizeMode(sliderProps, key, fallback) {
|
|
2812
3104
|
const raw = String(sliderProps?.size?.[key] ?? '').toLowerCase();
|
|
2813
|
-
if (raw === 'fill' || raw === '
|
|
3105
|
+
if (raw === 'fill' || raw === 'infinity' || raw === 'infinite' || raw === 'double.infinity' || raw === '+infinity') {
|
|
3106
|
+
return 'fill';
|
|
3107
|
+
}
|
|
3108
|
+
if (raw === 'fit' || raw === 'fixed') return raw;
|
|
3109
|
+
if (isFillDimensionValue(sliderProps?.[key])) return 'fill';
|
|
2814
3110
|
return sliderProps?.[key] !== undefined ? 'fixed' : fallback;
|
|
2815
3111
|
}
|
|
2816
|
-
function
|
|
2817
|
-
const raw = String(
|
|
2818
|
-
if (raw === 'fill' || raw === '
|
|
3112
|
+
function resolvePageSizeMode(pageProps, key) {
|
|
3113
|
+
const raw = String(pageProps?.size?.[key] ?? '').toLowerCase();
|
|
3114
|
+
if (raw === 'fill' || raw === 'infinity' || raw === 'infinite' || raw === 'double.infinity' || raw === '+infinity') {
|
|
3115
|
+
return 'fill';
|
|
3116
|
+
}
|
|
3117
|
+
if (raw === 'fit' || raw === 'fixed') return raw;
|
|
3118
|
+
if (isFillDimensionValue(pageProps?.[key])) return 'fill';
|
|
2819
3119
|
return key === 'width' ? 'fill' : 'fit';
|
|
2820
3120
|
}
|
|
2821
3121
|
function toFinite(value) {
|
|
@@ -2827,11 +3127,13 @@ function toFinite(value) {
|
|
|
2827
3127
|
return null;
|
|
2828
3128
|
}
|
|
2829
3129
|
export function resolveSliderContainerSize(args) {
|
|
2830
|
-
const
|
|
2831
|
-
const
|
|
3130
|
+
const dotsTopInset = Math.max(0, args.dotsTopInset ?? 0);
|
|
3131
|
+
const dotsBottomInset = Math.max(0, args.dotsBottomInset ?? (args.showDots ? 18 : 0));
|
|
3132
|
+
const dotsInset = dotsTopInset + dotsBottomInset;
|
|
3133
|
+
const fitPrimary = args.direction === 'horizontal' ? args.activePageWidth : args.activePageHeight;
|
|
2832
3134
|
const fitViewportPrimary = Math.max(1, fitPrimary + args.leadingPeek + args.trailingPeek);
|
|
2833
|
-
const viewportWidth = args.direction === 'horizontal' ? fitViewportPrimary : Math.max(1, args.
|
|
2834
|
-
const viewportHeight = args.direction === 'vertical' ? fitViewportPrimary : Math.max(1, args.
|
|
3135
|
+
const viewportWidth = args.direction === 'horizontal' ? fitViewportPrimary : Math.max(1, args.activePageWidth);
|
|
3136
|
+
const viewportHeight = args.direction === 'vertical' ? fitViewportPrimary : Math.max(1, args.activePageHeight);
|
|
2835
3137
|
const fitOuterWidth = Math.min(Math.max(1, viewportWidth), Math.max(1, args.availableWidth || viewportWidth));
|
|
2836
3138
|
const fitOuterHeight = Math.max(1, viewportHeight + dotsInset);
|
|
2837
3139
|
const outerWidth = args.widthMode === 'fill' ? '100%' : args.widthMode === 'fixed' ? Math.max(1, args.fixedWidth ?? fitOuterWidth) : fitOuterWidth;
|
|
@@ -2843,11 +3145,21 @@ export function resolveSliderContainerSize(args) {
|
|
|
2843
3145
|
viewportHeight: args.heightMode === 'fit' ? Math.max(1, fitOuterHeight - dotsInset) : Math.max(1, args.availableHeight || fitOuterHeight - dotsInset)
|
|
2844
3146
|
};
|
|
2845
3147
|
}
|
|
2846
|
-
|
|
2847
|
-
const widthMode =
|
|
2848
|
-
const heightMode =
|
|
2849
|
-
const
|
|
2850
|
-
const
|
|
3148
|
+
function resolvePageFixedSizeHint(pageProps) {
|
|
3149
|
+
const widthMode = resolvePageSizeMode(pageProps, 'width');
|
|
3150
|
+
const heightMode = resolvePageSizeMode(pageProps, 'height');
|
|
3151
|
+
const width = widthMode === 'fixed' ? toFinite(parseLayoutDimension(pageProps.width ?? pageProps.size?.widthPx, true)) : null;
|
|
3152
|
+
const height = heightMode === 'fixed' ? toFinite(parseLayoutDimension(pageProps.height ?? pageProps.size?.heightPx, true)) : null;
|
|
3153
|
+
return {
|
|
3154
|
+
width,
|
|
3155
|
+
height
|
|
3156
|
+
};
|
|
3157
|
+
}
|
|
3158
|
+
export function resolvePageSize(args) {
|
|
3159
|
+
const widthMode = resolvePageSizeMode(args.pageProps, 'width');
|
|
3160
|
+
const heightMode = resolvePageSizeMode(args.pageProps, 'height');
|
|
3161
|
+
const fixedWidth = toFinite(parseLayoutDimension(args.pageProps.width ?? args.pageProps.size?.widthPx, true));
|
|
3162
|
+
const fixedHeight = toFinite(parseLayoutDimension(args.pageProps.height ?? args.pageProps.size?.heightPx, true));
|
|
2851
3163
|
const width = widthMode === 'fixed' ? Math.max(1, fixedWidth ?? args.pagePrimary) : widthMode === 'fit' ? undefined : args.direction === 'horizontal' ? args.pagePrimary : args.crossSize;
|
|
2852
3164
|
const height = heightMode === 'fixed' ? Math.max(1, fixedHeight ?? args.pagePrimary) : heightMode === 'fit' ? undefined : args.direction === 'vertical' ? args.pagePrimary : args.crossSize;
|
|
2853
3165
|
return {
|
|
@@ -2951,7 +3263,7 @@ function resolveSliderBackgroundColor(sliderProps) {
|
|
|
2951
3263
|
function SliderWidget({
|
|
2952
3264
|
id,
|
|
2953
3265
|
sliderProps,
|
|
2954
|
-
|
|
3266
|
+
pagePropsList,
|
|
2955
3267
|
direction,
|
|
2956
3268
|
pageAlignment,
|
|
2957
3269
|
pageSpacing,
|
|
@@ -2975,7 +3287,8 @@ function SliderWidget({
|
|
|
2975
3287
|
width: 1,
|
|
2976
3288
|
height: 1
|
|
2977
3289
|
});
|
|
2978
|
-
const [
|
|
3290
|
+
const [measuredPageSizes, setMeasuredPageSizes] = React.useState({});
|
|
3291
|
+
const [activePageSize, setActivePageSize] = React.useState({
|
|
2979
3292
|
width: 1,
|
|
2980
3293
|
height: 1
|
|
2981
3294
|
});
|
|
@@ -2989,6 +3302,19 @@ function SliderWidget({
|
|
|
2989
3302
|
React.useEffect(() => {
|
|
2990
3303
|
setCurrentPage(prev => clampSliderPage(prev, pageCount));
|
|
2991
3304
|
}, [pageCount]);
|
|
3305
|
+
React.useEffect(() => {
|
|
3306
|
+
setMeasuredPageSizes(prev => {
|
|
3307
|
+
const next = {};
|
|
3308
|
+
Object.keys(prev).forEach(key => {
|
|
3309
|
+
const index = Number(key);
|
|
3310
|
+
if (Number.isFinite(index) && index < pageCount) {
|
|
3311
|
+
const cached = prev[index];
|
|
3312
|
+
if (cached) next[index] = cached;
|
|
3313
|
+
}
|
|
3314
|
+
});
|
|
3315
|
+
return Object.keys(next).length === Object.keys(prev).length ? prev : next;
|
|
3316
|
+
});
|
|
3317
|
+
}, [pageCount]);
|
|
2992
3318
|
React.useEffect(() => {
|
|
2993
3319
|
if (autoAdvance && !isInteracting && pageLength > 1) {
|
|
2994
3320
|
timerRef.current = setInterval(() => {
|
|
@@ -3009,6 +3335,23 @@ function SliderWidget({
|
|
|
3009
3335
|
pagerRef.current.setPage(clampSliderPage(currentPage, pageCount));
|
|
3010
3336
|
}
|
|
3011
3337
|
}, [currentPage, pageCount]);
|
|
3338
|
+
const syncActivePageSize = React.useCallback(page => {
|
|
3339
|
+
if (pageCount <= 0) return;
|
|
3340
|
+
const safePage = clampSliderPage(page, pageCount);
|
|
3341
|
+
const measured = measuredPageSizes[safePage];
|
|
3342
|
+
const hint = resolvePageFixedSizeHint(pagePropsList[safePage] ?? {});
|
|
3343
|
+
setActivePageSize(prev => {
|
|
3344
|
+
const next = {
|
|
3345
|
+
width: Math.max(1, hint.width ?? measured?.width ?? prev.width),
|
|
3346
|
+
height: Math.max(1, hint.height ?? measured?.height ?? prev.height)
|
|
3347
|
+
};
|
|
3348
|
+
return prev.width === next.width && prev.height === next.height ? prev : next;
|
|
3349
|
+
});
|
|
3350
|
+
}, [measuredPageSizes, pageCount, pagePropsList]);
|
|
3351
|
+
React.useEffect(() => {
|
|
3352
|
+
if (pageCount <= 0) return;
|
|
3353
|
+
syncActivePageSize(currentPage);
|
|
3354
|
+
}, [currentPage, pageCount, syncActivePageSize]);
|
|
3012
3355
|
React.useEffect(() => {
|
|
3013
3356
|
if (registry && id && children.length > 0) {
|
|
3014
3357
|
registry.update(id, currentPage % children.length, children.length);
|
|
@@ -3021,13 +3364,15 @@ function SliderWidget({
|
|
|
3021
3364
|
// 2) trailingPeek = end?0 : start?pagePeek*2 : pagePeek
|
|
3022
3365
|
// 3) pagePrimary = viewportPrimary - leadingPeek - trailingPeek (clamped >= 1)
|
|
3023
3366
|
// 4) track offset = activeIndex * (pagePrimary + pageSpacing)
|
|
3024
|
-
// 5) fit parent mode follows active
|
|
3367
|
+
// 5) fit parent mode follows active page size but is clamped to container width
|
|
3025
3368
|
// 6) viewport always clips track content (no root horizontal overflow)
|
|
3026
3369
|
const {
|
|
3027
3370
|
leading,
|
|
3028
3371
|
trailing
|
|
3029
3372
|
} = resolvePeekInsets(pageAlignment, pagePeek);
|
|
3030
3373
|
const showDots = pageControlEnabled && pageLength > 1;
|
|
3374
|
+
const dotsTopInset = showDots && pageControlPosition === 'top' ? 18 : 0;
|
|
3375
|
+
const dotsBottomInset = showDots && pageControlPosition !== 'top' ? 18 : 0;
|
|
3031
3376
|
const widthMode = resolveSliderSizeMode(sliderProps, 'width', 'fill');
|
|
3032
3377
|
const heightMode = resolveSliderSizeMode(sliderProps, 'height', 'fit');
|
|
3033
3378
|
const fixedWidth = toFinite(parseLayoutDimension(sliderProps.width, true));
|
|
@@ -3039,14 +3384,17 @@ function SliderWidget({
|
|
|
3039
3384
|
heightMode,
|
|
3040
3385
|
availableWidth: availableSize.width,
|
|
3041
3386
|
availableHeight: availableSize.height,
|
|
3042
|
-
|
|
3043
|
-
|
|
3387
|
+
activePageWidth: activePageSize.width,
|
|
3388
|
+
activePageHeight: activePageSize.height,
|
|
3044
3389
|
fixedWidth,
|
|
3045
3390
|
fixedHeight,
|
|
3046
3391
|
leadingPeek: leading,
|
|
3047
3392
|
trailingPeek: trailing,
|
|
3048
|
-
showDots
|
|
3393
|
+
showDots,
|
|
3394
|
+
dotsTopInset,
|
|
3395
|
+
dotsBottomInset
|
|
3049
3396
|
});
|
|
3397
|
+
const sliderFillSizeStyle = resolveFillSizeStyle(sliderProps.size);
|
|
3050
3398
|
const viewportPrimary = direction === 'horizontal' ? resolved.viewportWidth : resolved.viewportHeight;
|
|
3051
3399
|
const pagePrimary = Math.max(1, viewportPrimary - leading - trailing);
|
|
3052
3400
|
return /*#__PURE__*/_jsxs(View, {
|
|
@@ -3066,46 +3414,35 @@ function SliderWidget({
|
|
|
3066
3414
|
style: {
|
|
3067
3415
|
width: resolved.outerWidth,
|
|
3068
3416
|
height: resolved.outerHeight,
|
|
3069
|
-
minWidth:
|
|
3070
|
-
minHeight:
|
|
3417
|
+
minWidth: 0,
|
|
3418
|
+
minHeight: 0,
|
|
3419
|
+
display: 'flex',
|
|
3420
|
+
flexDirection: 'column',
|
|
3421
|
+
...sliderFillSizeStyle,
|
|
3071
3422
|
backgroundColor: sliderBackgroundColor,
|
|
3072
3423
|
borderRadius: 0,
|
|
3073
|
-
overflow: '
|
|
3424
|
+
overflow: 'hidden',
|
|
3425
|
+
position: 'relative'
|
|
3074
3426
|
},
|
|
3075
|
-
children: [
|
|
3076
|
-
style: {
|
|
3077
|
-
marginBottom: 8,
|
|
3078
|
-
flexDirection: 'row',
|
|
3079
|
-
justifyContent: 'center',
|
|
3080
|
-
alignItems: 'center'
|
|
3081
|
-
},
|
|
3082
|
-
children: Array.from({
|
|
3083
|
-
length: pageLength
|
|
3084
|
-
}).map((_, index) => {
|
|
3085
|
-
const isActive = index === currentPage;
|
|
3086
|
-
return /*#__PURE__*/_jsx(View, {
|
|
3087
|
-
style: {
|
|
3088
|
-
width: 6,
|
|
3089
|
-
height: 6,
|
|
3090
|
-
borderRadius: 3,
|
|
3091
|
-
marginHorizontal: 3,
|
|
3092
|
-
backgroundColor: isActive ? parseColor('0xFF111827') : parseColor('0xFFD1D5DB')
|
|
3093
|
-
}
|
|
3094
|
-
}, `slider-dot-top-${index}`);
|
|
3095
|
-
})
|
|
3096
|
-
}) : null, /*#__PURE__*/_jsx(View, {
|
|
3427
|
+
children: [/*#__PURE__*/_jsx(View, {
|
|
3097
3428
|
style: {
|
|
3098
3429
|
overflow: 'hidden',
|
|
3430
|
+
width: widthMode === 'fit' ? resolved.viewportWidth : '100%',
|
|
3431
|
+
height: heightMode === 'fit' ? resolved.viewportHeight : '100%',
|
|
3432
|
+
minWidth: 0,
|
|
3433
|
+
minHeight: 0,
|
|
3434
|
+
display: 'flex',
|
|
3435
|
+
flexDirection: 'column',
|
|
3436
|
+
flexGrow: heightMode === 'fit' ? 0 : 1,
|
|
3437
|
+
flexShrink: 1,
|
|
3099
3438
|
...(direction === 'horizontal' ? {
|
|
3100
|
-
width: resolved.viewportWidth,
|
|
3101
|
-
height: resolved.viewportHeight,
|
|
3102
3439
|
paddingLeft: leading,
|
|
3103
|
-
paddingRight: trailing
|
|
3440
|
+
paddingRight: trailing,
|
|
3441
|
+
paddingTop: dotsTopInset,
|
|
3442
|
+
paddingBottom: dotsBottomInset
|
|
3104
3443
|
} : {
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
paddingTop: leading,
|
|
3108
|
-
paddingBottom: trailing
|
|
3444
|
+
paddingTop: leading + dotsTopInset,
|
|
3445
|
+
paddingBottom: trailing + dotsBottomInset
|
|
3109
3446
|
})
|
|
3110
3447
|
},
|
|
3111
3448
|
children: /*#__PURE__*/_jsx(PagerView, {
|
|
@@ -3113,7 +3450,9 @@ function SliderWidget({
|
|
|
3113
3450
|
style: {
|
|
3114
3451
|
width: '100%',
|
|
3115
3452
|
height: '100%',
|
|
3116
|
-
|
|
3453
|
+
minWidth: 0,
|
|
3454
|
+
minHeight: 0,
|
|
3455
|
+
flex: 1
|
|
3117
3456
|
},
|
|
3118
3457
|
orientation: direction,
|
|
3119
3458
|
pageMargin: Math.max(0, pageSpacing),
|
|
@@ -3122,6 +3461,7 @@ function SliderWidget({
|
|
|
3122
3461
|
const page = event.nativeEvent.position;
|
|
3123
3462
|
const safePage = clampSliderPage(page, pageCount);
|
|
3124
3463
|
setCurrentPage(safePage);
|
|
3464
|
+
syncActivePageSize(safePage);
|
|
3125
3465
|
markInteracting();
|
|
3126
3466
|
if (registry && id) {
|
|
3127
3467
|
registry.update(id, safePage % pageLength, pageLength);
|
|
@@ -3130,33 +3470,83 @@ function SliderWidget({
|
|
|
3130
3470
|
children: Array.from({
|
|
3131
3471
|
length: pageCount
|
|
3132
3472
|
}).map((_, index) => /*#__PURE__*/_jsx(View, {
|
|
3133
|
-
onLayout: index === currentPage ? event => {
|
|
3134
|
-
const nextWidth = Math.max(1, Math.round(event.nativeEvent.layout.width));
|
|
3135
|
-
const nextHeight = Math.max(1, Math.round(event.nativeEvent.layout.height));
|
|
3136
|
-
setActiveSlideSize(prev => prev.width === nextWidth && prev.height === nextHeight ? prev : {
|
|
3137
|
-
width: nextWidth,
|
|
3138
|
-
height: nextHeight
|
|
3139
|
-
});
|
|
3140
|
-
} : undefined,
|
|
3141
3473
|
style: {
|
|
3142
|
-
|
|
3474
|
+
width: '100%',
|
|
3475
|
+
height: '100%',
|
|
3143
3476
|
overflow: 'hidden',
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
crossSize: '100%'
|
|
3149
|
-
})
|
|
3477
|
+
minWidth: 0,
|
|
3478
|
+
minHeight: 0,
|
|
3479
|
+
display: 'flex',
|
|
3480
|
+
flexDirection: 'column'
|
|
3150
3481
|
},
|
|
3151
|
-
children:
|
|
3482
|
+
children: /*#__PURE__*/_jsx(View, {
|
|
3483
|
+
onLayout: event => {
|
|
3484
|
+
const nextWidth = Math.max(1, Math.round(event.nativeEvent.layout.width));
|
|
3485
|
+
const nextHeight = Math.max(1, Math.round(event.nativeEvent.layout.height));
|
|
3486
|
+
setMeasuredPageSizes(prev => {
|
|
3487
|
+
const current = prev[index];
|
|
3488
|
+
if (current && current.width === nextWidth && current.height === nextHeight) {
|
|
3489
|
+
return prev;
|
|
3490
|
+
}
|
|
3491
|
+
return {
|
|
3492
|
+
...prev,
|
|
3493
|
+
[index]: {
|
|
3494
|
+
width: nextWidth,
|
|
3495
|
+
height: nextHeight
|
|
3496
|
+
}
|
|
3497
|
+
};
|
|
3498
|
+
});
|
|
3499
|
+
if (index === currentPage) {
|
|
3500
|
+
setActivePageSize(prev => prev.width === nextWidth && prev.height === nextHeight ? prev : {
|
|
3501
|
+
width: nextWidth,
|
|
3502
|
+
height: nextHeight
|
|
3503
|
+
});
|
|
3504
|
+
}
|
|
3505
|
+
},
|
|
3506
|
+
style: {
|
|
3507
|
+
alignSelf: (direction === 'horizontal' ? resolvePageSizeMode(pagePropsList[index] ?? {}, 'height') === 'fill' : resolvePageSizeMode(pagePropsList[index] ?? {}, 'width') === 'fill') ? 'stretch' : 'flex-start',
|
|
3508
|
+
overflow: 'hidden',
|
|
3509
|
+
minWidth: 0,
|
|
3510
|
+
minHeight: 0,
|
|
3511
|
+
display: 'flex',
|
|
3512
|
+
flexDirection: 'column',
|
|
3513
|
+
...resolvePageSize({
|
|
3514
|
+
pageProps: pagePropsList[index] ?? {},
|
|
3515
|
+
direction,
|
|
3516
|
+
pagePrimary,
|
|
3517
|
+
crossSize: '100%'
|
|
3518
|
+
})
|
|
3519
|
+
},
|
|
3520
|
+
children: /*#__PURE__*/_jsx(View, {
|
|
3521
|
+
style: {
|
|
3522
|
+
width: '100%',
|
|
3523
|
+
height: '100%',
|
|
3524
|
+
minWidth: 0,
|
|
3525
|
+
minHeight: 0,
|
|
3526
|
+
display: 'flex',
|
|
3527
|
+
flexDirection: 'column',
|
|
3528
|
+
flexGrow: 1
|
|
3529
|
+
},
|
|
3530
|
+
children: children[index % pageLength]
|
|
3531
|
+
})
|
|
3532
|
+
})
|
|
3152
3533
|
}, `slider-page-${index}`))
|
|
3153
3534
|
})
|
|
3154
|
-
}), showDots
|
|
3535
|
+
}), showDots ? /*#__PURE__*/_jsx(View, {
|
|
3155
3536
|
style: {
|
|
3156
|
-
|
|
3537
|
+
position: 'absolute',
|
|
3538
|
+
left: 0,
|
|
3539
|
+
right: 0,
|
|
3540
|
+
...(pageControlPosition === 'top' ? {
|
|
3541
|
+
top: 4
|
|
3542
|
+
} : {
|
|
3543
|
+
bottom: 4
|
|
3544
|
+
}),
|
|
3545
|
+
height: 12,
|
|
3157
3546
|
flexDirection: 'row',
|
|
3158
3547
|
justifyContent: 'center',
|
|
3159
|
-
alignItems: 'center'
|
|
3548
|
+
alignItems: 'center',
|
|
3549
|
+
pointerEvents: 'none'
|
|
3160
3550
|
},
|
|
3161
3551
|
children: Array.from({
|
|
3162
3552
|
length: pageLength
|
|
@@ -3170,7 +3560,7 @@ function SliderWidget({
|
|
|
3170
3560
|
marginHorizontal: 3,
|
|
3171
3561
|
backgroundColor: isActive ? parseColor('0xFF111827') : parseColor('0xFFD1D5DB')
|
|
3172
3562
|
}
|
|
3173
|
-
}, `slider-dot
|
|
3563
|
+
}, `slider-dot-${index}`);
|
|
3174
3564
|
})
|
|
3175
3565
|
}) : null]
|
|
3176
3566
|
});
|
|
@@ -3192,11 +3582,15 @@ function PageViewIndicator({
|
|
|
3192
3582
|
}) {
|
|
3193
3583
|
const registry = useSliderRegistry();
|
|
3194
3584
|
const [current, setCurrent] = React.useState(0);
|
|
3585
|
+
const [count, setCount] = React.useState(0);
|
|
3195
3586
|
const indicatorStyle = style ?? 'dots';
|
|
3196
|
-
const count = linkedTo && registry ? registry.getPageCount(linkedTo) : 0;
|
|
3197
3587
|
React.useEffect(() => {
|
|
3198
3588
|
if (!linkedTo || !registry) return;
|
|
3199
|
-
|
|
3589
|
+
setCount(registry.getPageCount(linkedTo));
|
|
3590
|
+
return registry.getNotifier(linkedTo, page => {
|
|
3591
|
+
setCurrent(page);
|
|
3592
|
+
setCount(registry.getPageCount(linkedTo));
|
|
3593
|
+
});
|
|
3200
3594
|
}, [linkedTo, registry]);
|
|
3201
3595
|
if (!linkedTo || !registry || count <= 1) return null;
|
|
3202
3596
|
if (indicatorStyle !== 'dots') {
|